mirror of https://github.com/crytic/slither
commit
560319ab04
@ -1,3 +1,9 @@ |
||||
contract A{ |
||||
pragma solidity 0.8.19; |
||||
|
||||
} |
||||
error RevertIt(); |
||||
|
||||
contract Example { |
||||
function reverts() external pure { |
||||
revert RevertIt(); |
||||
} |
||||
} |
@ -1,5 +1,16 @@ |
||||
import "./a.sol"; |
||||
|
||||
contract B is A{ |
||||
pragma solidity 0.8.19; |
||||
|
||||
enum B { |
||||
a, |
||||
b |
||||
} |
||||
|
||||
contract T { |
||||
Example e = new Example(); |
||||
function b() public returns(uint) { |
||||
B b = B.a; |
||||
return 4; |
||||
} |
||||
} |
@ -0,0 +1,95 @@ |
||||
#!/usr/bin/env bash |
||||
|
||||
### Test slither-interface |
||||
|
||||
DIR_TESTS="tests/tools/interface" |
||||
|
||||
solc-select use 0.8.19 --always-install |
||||
|
||||
#Test 1 - Etherscan target |
||||
slither-interface WETH9 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 |
||||
DIFF=$(diff crytic-export/interfaces/IWETH9.sol "$DIR_TESTS/test_1.sol" --strip-trailing-cr) |
||||
if [ "$DIFF" != "" ] |
||||
then |
||||
echo "slither-interface test 1 failed" |
||||
cat "crytic-export/interfaces/IWETH9.sol" |
||||
echo "" |
||||
cat "$DIR_TESTS/test_1.sol" |
||||
exit 255 |
||||
fi |
||||
|
||||
|
||||
#Test 2 - Local file target |
||||
slither-interface Mock tests/tools/interface/ContractMock.sol |
||||
DIFF=$(diff crytic-export/interfaces/IMock.sol "$DIR_TESTS/test_2.sol" --strip-trailing-cr) |
||||
if [ "$DIFF" != "" ] |
||||
then |
||||
echo "slither-interface test 2 failed" |
||||
cat "crytic-export/interfaces/IMock.sol" |
||||
echo "" |
||||
cat "$DIR_TESTS/test_2.sol" |
||||
exit 255 |
||||
fi |
||||
|
||||
|
||||
#Test 3 - unroll structs |
||||
slither-interface Mock tests/tools/interface/ContractMock.sol --unroll-structs |
||||
DIFF=$(diff crytic-export/interfaces/IMock.sol "$DIR_TESTS/test_3.sol" --strip-trailing-cr) |
||||
if [ "$DIFF" != "" ] |
||||
then |
||||
echo "slither-interface test 3 failed" |
||||
cat "crytic-export/interfaces/IMock.sol" |
||||
echo "" |
||||
cat "$DIR_TESTS/test_3.sol" |
||||
exit 255 |
||||
fi |
||||
|
||||
#Test 4 - exclude structs |
||||
slither-interface Mock tests/tools/interface/ContractMock.sol --exclude-structs |
||||
DIFF=$(diff crytic-export/interfaces/IMock.sol "$DIR_TESTS/test_4.sol" --strip-trailing-cr) |
||||
if [ "$DIFF" != "" ] |
||||
then |
||||
echo "slither-interface test 4 failed" |
||||
cat "crytic-export/interfaces/IMock.sol" |
||||
echo "" |
||||
cat "$DIR_TESTS/test_4.sol" |
||||
exit 255 |
||||
fi |
||||
|
||||
#Test 5 - exclude errors |
||||
slither-interface Mock tests/tools/interface/ContractMock.sol --exclude-errors |
||||
DIFF=$(diff crytic-export/interfaces/IMock.sol "$DIR_TESTS/test_5.sol" --strip-trailing-cr) |
||||
if [ "$DIFF" != "" ] |
||||
then |
||||
echo "slither-interface test 5 failed" |
||||
cat "crytic-export/interfaces/IMock.sol" |
||||
echo "" |
||||
cat "$DIR_TESTS/test_5.sol" |
||||
exit 255 |
||||
fi |
||||
|
||||
#Test 6 - exclude enums |
||||
slither-interface Mock tests/tools/interface/ContractMock.sol --exclude-enums |
||||
DIFF=$(diff crytic-export/interfaces/IMock.sol "$DIR_TESTS/test_6.sol" --strip-trailing-cr) |
||||
if [ "$DIFF" != "" ] |
||||
then |
||||
echo "slither-interface test 6 failed" |
||||
cat "crytic-export/interfaces/IMock.sol" |
||||
echo "" |
||||
cat "$DIR_TESTS/test_6.sol" |
||||
exit 255 |
||||
fi |
||||
|
||||
#Test 7 - exclude events |
||||
slither-interface Mock tests/tools/interface/ContractMock.sol --exclude-events |
||||
DIFF=$(diff crytic-export/interfaces/IMock.sol "$DIR_TESTS/test_7.sol" --strip-trailing-cr) |
||||
if [ "$DIFF" != "" ] |
||||
then |
||||
echo "slither-interface test 7 failed" |
||||
cat "crytic-export/interfaces/IMock.sol" |
||||
echo "" |
||||
cat "$DIR_TESTS/test_7.sol" |
||||
exit 255 |
||||
fi |
||||
|
||||
rm -r crytic-export |
@ -0,0 +1,104 @@ |
||||
""" |
||||
Module detecting usage of more than one dynamic type in abi.encodePacked() arguments which could lead to collision |
||||
""" |
||||
|
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.core.declarations.solidity_variables import SolidityFunction |
||||
from slither.slithir.operations import SolidityCall |
||||
from slither.analyses.data_dependency.data_dependency import is_tainted |
||||
from slither.core.solidity_types import ElementaryType |
||||
from slither.core.solidity_types import ArrayType |
||||
|
||||
|
||||
def _is_dynamic_type(arg): |
||||
""" |
||||
Args: |
||||
arg (function argument) |
||||
Returns: |
||||
Bool |
||||
""" |
||||
if isinstance(arg.type, ElementaryType) and (arg.type.name in ["string", "bytes"]): |
||||
return True |
||||
if isinstance(arg.type, ArrayType) and arg.type.length is None: |
||||
return True |
||||
|
||||
return False |
||||
|
||||
|
||||
def _detect_abi_encodePacked_collision(contract): |
||||
""" |
||||
Args: |
||||
contract (Contract) |
||||
Returns: |
||||
list((Function), (list (Node))) |
||||
""" |
||||
ret = [] |
||||
# pylint: disable=too-many-nested-blocks |
||||
for f in contract.functions_and_modifiers_declared: |
||||
for n in f.nodes: |
||||
for ir in n.irs: |
||||
if isinstance(ir, SolidityCall) and ir.function == SolidityFunction( |
||||
"abi.encodePacked()" |
||||
): |
||||
dynamic_type_count = 0 |
||||
for arg in ir.arguments: |
||||
if is_tainted(arg, contract) and _is_dynamic_type(arg): |
||||
dynamic_type_count += 1 |
||||
elif dynamic_type_count > 1: |
||||
ret.append((f, n)) |
||||
dynamic_type_count = 0 |
||||
else: |
||||
dynamic_type_count = 0 |
||||
if dynamic_type_count > 1: |
||||
ret.append((f, n)) |
||||
return ret |
||||
|
||||
|
||||
class EncodePackedCollision(AbstractDetector): |
||||
""" |
||||
Detect usage of more than one dynamic type in abi.encodePacked() arguments which could to collision |
||||
""" |
||||
|
||||
ARGUMENT = "encode-packed-collision" |
||||
HELP = "ABI encodePacked Collision" |
||||
IMPACT = DetectorClassification.HIGH |
||||
CONFIDENCE = DetectorClassification.HIGH |
||||
|
||||
WIKI = ( |
||||
"https://github.com/crytic/slither/wiki/Detector-Documentation#abi-encodePacked-collision" |
||||
) |
||||
|
||||
WIKI_TITLE = "ABI encodePacked Collision" |
||||
WIKI_DESCRIPTION = """Detect collision due to dynamic type usages in `abi.encodePacked`""" |
||||
|
||||
WIKI_EXPLOIT_SCENARIO = """ |
||||
```solidity |
||||
contract Sign { |
||||
function get_hash_for_signature(string name, string doc) external returns(bytes32) { |
||||
return keccak256(abi.encodePacked(name, doc)); |
||||
} |
||||
} |
||||
``` |
||||
Bob calls `get_hash_for_signature` with (`bob`, `This is the content`). The hash returned is used as an ID. |
||||
Eve creates a collision with the ID using (`bo`, `bThis is the content`) and compromises the system. |
||||
""" |
||||
WIKI_RECOMMENDATION = """Do not use more than one dynamic type in `abi.encodePacked()` |
||||
(see the [Solidity documentation](https://solidity.readthedocs.io/en/v0.5.10/abi-spec.html?highlight=abi.encodePacked#non-standard-packed-modeDynamic)). |
||||
Use `abi.encode()`, preferably.""" |
||||
|
||||
def _detect(self): |
||||
"""Detect usage of more than one dynamic type in abi.encodePacked(..) arguments which could lead to collision""" |
||||
results = [] |
||||
for c in self.compilation_unit.contracts: |
||||
values = _detect_abi_encodePacked_collision(c) |
||||
for func, node in values: |
||||
info = [ |
||||
func, |
||||
" calls abi.encodePacked() with multiple dynamic arguments:\n\t- ", |
||||
node, |
||||
"\n", |
||||
] |
||||
json = self.generate_result(info) |
||||
results.append(json) |
||||
|
||||
return results |
@ -0,0 +1,105 @@ |
||||
import argparse |
||||
import logging |
||||
from pathlib import Path |
||||
|
||||
from crytic_compile import cryticparser |
||||
|
||||
from slither import Slither |
||||
from slither.utils.code_generation import generate_interface |
||||
|
||||
logging.basicConfig() |
||||
logger = logging.getLogger("Slither-Interface") |
||||
logger.setLevel(logging.INFO) |
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace: |
||||
""" |
||||
Parse the underlying arguments for the program. |
||||
:return: Returns the arguments for the program. |
||||
""" |
||||
parser = argparse.ArgumentParser( |
||||
description="Generates code for a Solidity interface from contract", |
||||
usage=("slither-interface <ContractName> <source file or deployment address>"), |
||||
) |
||||
|
||||
parser.add_argument( |
||||
"contract_source", |
||||
help="The name of the contract (case sensitive) followed by the deployed contract address if verified on etherscan or project directory/filename for local contracts.", |
||||
nargs="+", |
||||
) |
||||
|
||||
parser.add_argument( |
||||
"--unroll-structs", |
||||
help="Whether to use structures' underlying types instead of the user-defined type", |
||||
default=False, |
||||
action="store_true", |
||||
) |
||||
|
||||
parser.add_argument( |
||||
"--exclude-events", |
||||
help="Excludes event signatures in the interface", |
||||
default=False, |
||||
action="store_true", |
||||
) |
||||
|
||||
parser.add_argument( |
||||
"--exclude-errors", |
||||
help="Excludes custom error signatures in the interface", |
||||
default=False, |
||||
action="store_true", |
||||
) |
||||
|
||||
parser.add_argument( |
||||
"--exclude-enums", |
||||
help="Excludes enum definitions in the interface", |
||||
default=False, |
||||
action="store_true", |
||||
) |
||||
|
||||
parser.add_argument( |
||||
"--exclude-structs", |
||||
help="Exclude struct definitions in the interface", |
||||
default=False, |
||||
action="store_true", |
||||
) |
||||
|
||||
cryticparser.init(parser) |
||||
|
||||
return parser.parse_args() |
||||
|
||||
|
||||
def main() -> None: |
||||
args = parse_args() |
||||
|
||||
contract_name, target = args.contract_source |
||||
slither = Slither(target, **vars(args)) |
||||
|
||||
_contract = slither.get_contract_from_name(contract_name)[0] |
||||
|
||||
interface = generate_interface( |
||||
contract=_contract, |
||||
unroll_structs=args.unroll_structs, |
||||
include_events=not args.exclude_events, |
||||
include_errors=not args.exclude_errors, |
||||
include_enums=not args.exclude_enums, |
||||
include_structs=not args.exclude_structs, |
||||
) |
||||
|
||||
# add version pragma |
||||
interface = ( |
||||
f"pragma solidity {_contract.compilation_unit.pragma_directives[0].version};\n\n" |
||||
+ interface |
||||
) |
||||
|
||||
# write interface to file |
||||
export = Path("crytic-export", "interfaces") |
||||
export.mkdir(parents=True, exist_ok=True) |
||||
filename = f"I{contract_name}.sol" |
||||
path = Path(export, filename) |
||||
logger.info(f" Interface exported to {path}") |
||||
with open(path, "w", encoding="utf8") as f: |
||||
f.write(interface) |
||||
|
||||
|
||||
if __name__ == "__main__": |
||||
main() |
@ -0,0 +1,15 @@ |
||||
EncodePackedCollision.bad4(bytes,bytes) (tests/e2e/detectors/test_data/encode-packed-collision/0.7.6/encode_packed_collision.sol#34-36) calls abi.encodePacked() with multiple dynamic arguments: |
||||
- packed = abi.encodePacked(a,a2,a3,a) (tests/e2e/detectors/test_data/encode-packed-collision/0.7.6/encode_packed_collision.sol#35) |
||||
|
||||
EncodePackedCollision.bad2(string,uint256[]) (tests/e2e/detectors/test_data/encode-packed-collision/0.7.6/encode_packed_collision.sol#24-26) calls abi.encodePacked() with multiple dynamic arguments: |
||||
- packed = abi.encodePacked(stra,arra) (tests/e2e/detectors/test_data/encode-packed-collision/0.7.6/encode_packed_collision.sol#25) |
||||
|
||||
EncodePackedCollision.bad3_get_hash_for_signature(string,string) (tests/e2e/detectors/test_data/encode-packed-collision/0.7.6/encode_packed_collision.sol#29-31) calls abi.encodePacked() with multiple dynamic arguments: |
||||
- keccak256(bytes)(abi.encodePacked(name,doc)) (tests/e2e/detectors/test_data/encode-packed-collision/0.7.6/encode_packed_collision.sol#30) |
||||
|
||||
EncodePackedCollision.bad0(string,string) (tests/e2e/detectors/test_data/encode-packed-collision/0.7.6/encode_packed_collision.sol#14-16) calls abi.encodePacked() with multiple dynamic arguments: |
||||
- packed = abi.encodePacked(stra,strb) (tests/e2e/detectors/test_data/encode-packed-collision/0.7.6/encode_packed_collision.sol#15) |
||||
|
||||
EncodePackedCollision.bad1(string,bytes) (tests/e2e/detectors/test_data/encode-packed-collision/0.7.6/encode_packed_collision.sol#19-21) calls abi.encodePacked() with multiple dynamic arguments: |
||||
- packed = abi.encodePacked(stra,bytesa) (tests/e2e/detectors/test_data/encode-packed-collision/0.7.6/encode_packed_collision.sol#20) |
||||
|
@ -1,2 +1,2 @@ |
||||
C.f() (tests/e2e/detectors/test_data/incorrect-shift/0.7.6/shift_parameter_mixup.sol#3-7) contains an incorrect shift operation: a = 8 >> a (tests/e2e/detectors/test_data/incorrect-shift/0.7.6/shift_parameter_mixup.sol#5) |
||||
C.f() (tests/e2e/detectors/test_data/incorrect-shift/0.7.6/shift_parameter_mixup.sol#3-8) contains an incorrect shift operation: a = 8 >> a (tests/e2e/detectors/test_data/incorrect-shift/0.7.6/shift_parameter_mixup.sol#5) |
||||
|
||||
|
@ -1,4 +1,8 @@ |
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.4.25/unused_return.sol#17-29) ignores return value by t.f() (tests/e2e/detectors/test_data/unused-return/0.4.25/unused_return.sol#18) |
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.4.25/unused_return.sol#18-37) ignores return value by t.g() (tests/e2e/detectors/test_data/unused-return/0.4.25/unused_return.sol#31) |
||||
|
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.4.25/unused_return.sol#17-29) ignores return value by a.add(0) (tests/e2e/detectors/test_data/unused-return/0.4.25/unused_return.sol#22) |
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.4.25/unused_return.sol#18-37) ignores return value by t.f() (tests/e2e/detectors/test_data/unused-return/0.4.25/unused_return.sol#19) |
||||
|
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.4.25/unused_return.sol#18-37) ignores return value by a.add(0) (tests/e2e/detectors/test_data/unused-return/0.4.25/unused_return.sol#23) |
||||
|
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.4.25/unused_return.sol#18-37) ignores return value by (e) = t.g() (tests/e2e/detectors/test_data/unused-return/0.4.25/unused_return.sol#36) |
||||
|
||||
|
@ -1,4 +1,8 @@ |
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.5.16/unused_return.sol#17-29) ignores return value by t.f() (tests/e2e/detectors/test_data/unused-return/0.5.16/unused_return.sol#18) |
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.5.16/unused_return.sol#18-37) ignores return value by (e) = t.g() (tests/e2e/detectors/test_data/unused-return/0.5.16/unused_return.sol#36) |
||||
|
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.5.16/unused_return.sol#17-29) ignores return value by a.add(0) (tests/e2e/detectors/test_data/unused-return/0.5.16/unused_return.sol#22) |
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.5.16/unused_return.sol#18-37) ignores return value by a.add(0) (tests/e2e/detectors/test_data/unused-return/0.5.16/unused_return.sol#23) |
||||
|
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.5.16/unused_return.sol#18-37) ignores return value by t.g() (tests/e2e/detectors/test_data/unused-return/0.5.16/unused_return.sol#31) |
||||
|
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.5.16/unused_return.sol#18-37) ignores return value by t.f() (tests/e2e/detectors/test_data/unused-return/0.5.16/unused_return.sol#19) |
||||
|
||||
|
@ -1,4 +1,8 @@ |
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.6.11/unused_return.sol#17-29) ignores return value by a.add(0) (tests/e2e/detectors/test_data/unused-return/0.6.11/unused_return.sol#22) |
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.6.11/unused_return.sol#18-37) ignores return value by t.f() (tests/e2e/detectors/test_data/unused-return/0.6.11/unused_return.sol#19) |
||||
|
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.6.11/unused_return.sol#17-29) ignores return value by t.f() (tests/e2e/detectors/test_data/unused-return/0.6.11/unused_return.sol#18) |
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.6.11/unused_return.sol#18-37) ignores return value by a.add(0) (tests/e2e/detectors/test_data/unused-return/0.6.11/unused_return.sol#23) |
||||
|
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.6.11/unused_return.sol#18-37) ignores return value by t.g() (tests/e2e/detectors/test_data/unused-return/0.6.11/unused_return.sol#31) |
||||
|
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.6.11/unused_return.sol#18-37) ignores return value by (e) = t.g() (tests/e2e/detectors/test_data/unused-return/0.6.11/unused_return.sol#36) |
||||
|
||||
|
@ -1,4 +1,8 @@ |
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.7.6/unused_return.sol#17-29) ignores return value by a.add(0) (tests/e2e/detectors/test_data/unused-return/0.7.6/unused_return.sol#22) |
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.7.6/unused_return.sol#18-37) ignores return value by t.g() (tests/e2e/detectors/test_data/unused-return/0.7.6/unused_return.sol#31) |
||||
|
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.7.6/unused_return.sol#17-29) ignores return value by t.f() (tests/e2e/detectors/test_data/unused-return/0.7.6/unused_return.sol#18) |
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.7.6/unused_return.sol#18-37) ignores return value by a.add(0) (tests/e2e/detectors/test_data/unused-return/0.7.6/unused_return.sol#23) |
||||
|
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.7.6/unused_return.sol#18-37) ignores return value by t.f() (tests/e2e/detectors/test_data/unused-return/0.7.6/unused_return.sol#19) |
||||
|
||||
User.test(Target) (tests/e2e/detectors/test_data/unused-return/0.7.6/unused_return.sol#18-37) ignores return value by (e) = t.g() (tests/e2e/detectors/test_data/unused-return/0.7.6/unused_return.sol#36) |
||||
|
||||
|
@ -0,0 +1,78 @@ |
||||
contract ABIencodePacked{ |
||||
|
||||
uint a; |
||||
string str1 = "a"; |
||||
string str2 = "bc"; |
||||
bytes _bytes = "hello world"; |
||||
uint[] arr; |
||||
uint[2] arr2; |
||||
string[3] str_arr3; /* This nested dynamic type is not supported in abi.encodePacked mode by solc */ |
||||
string[] str_array; /* This nested dynamic type is not supported in abi.encodePacked mode by solc */ |
||||
bytes[] bytes_array; /* This nested dynamic type and tuples are not supported in abi.encodePacked mode by solc */ |
||||
|
||||
/* Two dynamic types */ |
||||
function bad0(string calldata stra, string calldata strb) external{ |
||||
bytes memory packed = abi.encodePacked(stra, strb); |
||||
} |
||||
|
||||
/* Two dynamic types */ |
||||
function bad1(string calldata stra, bytes calldata bytesa) external{ |
||||
bytes memory packed = abi.encodePacked(stra, bytesa); |
||||
} |
||||
|
||||
/* Two dynamic types */ |
||||
function bad2(string calldata stra, uint[] calldata arra) external{ |
||||
bytes memory packed = abi.encodePacked(stra, arra); |
||||
} |
||||
|
||||
/* Two dynamic types */ |
||||
function bad3_get_hash_for_signature(string calldata name, string calldata doc) external returns (bytes32) { |
||||
return keccak256(abi.encodePacked(name, doc)); |
||||
} |
||||
|
||||
/* Two dynamic types between non dynamic types */ |
||||
function bad4(bytes calldata a2, bytes calldata a3) external { |
||||
bytes memory packed = abi.encodePacked(a, a2, a3, a); |
||||
} |
||||
|
||||
/* Two dynamic types but static values*/ |
||||
function good0() external{ |
||||
bytes memory packed = abi.encodePacked(str1, str2); |
||||
} |
||||
|
||||
/* Two dynamic types but static values*/ |
||||
function good1() external{ |
||||
bytes memory packed = abi.encodePacked(str1, _bytes); |
||||
} |
||||
|
||||
/* Two dynamic types but static values*/ |
||||
function good2() external{ |
||||
bytes memory packed = abi.encodePacked(str1, arr); |
||||
} |
||||
|
||||
/* No dynamic types */ |
||||
function good3() external{ |
||||
bytes memory packed = abi.encodePacked(a); |
||||
} |
||||
|
||||
/* One dynamic type */ |
||||
function good4() external{ |
||||
bytes memory packed = abi.encodePacked(str1); |
||||
} |
||||
|
||||
/* One dynamic type */ |
||||
function good5() external{ |
||||
bytes memory packed = abi.encodePacked(a, str1); |
||||
} |
||||
|
||||
/* One dynamic type */ |
||||
function good6() external{ |
||||
bytes memory packed = abi.encodePacked(str1, arr2); |
||||
} |
||||
|
||||
/* Two dynamic types but not consecutive*/ |
||||
function good7(string calldata a, uint b, string calldata c) external{ |
||||
bytes memory packed = abi.encodePacked(a, b, c); |
||||
} |
||||
} |
||||
|
Binary file not shown.
Binary file not shown.
@ -1,8 +1,9 @@ |
||||
contract C { |
||||
|
||||
function f() internal returns (uint a) { |
||||
function f() internal returns (uint a, uint b) { |
||||
assembly { |
||||
a := shr(a, 8) |
||||
b := shl(248, 0xff) |
||||
} |
||||
} |
||||
} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue