├── rule_descriptions ├── SOLIDITY_DIV_MUL │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── links_en.html │ ├── name_en.txt │ ├── recommendation.html │ ├── recommendation_en.html │ ├── description.html │ ├── description_en.html │ ├── example_en.html │ └── example.html ├── SOLIDITY_SEND │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation_en.html │ ├── recommendation.html │ ├── links_en.html │ ├── description_en.html │ ├── example_en.html │ ├── example.html │ └── description.html ├── SOLIDITY_VAR │ ├── severity.txt │ ├── links.html │ ├── name_en.txt │ ├── name.txt │ ├── recommendation.html │ ├── recommendation_en.html │ ├── links_en.html │ ├── example.html │ ├── example_en.html │ ├── description.html │ └── description_en.html ├── SOLIDITY_EXACT_TIME │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation_en.html │ ├── recommendation.html │ ├── links_en.html │ ├── description.html │ ├── description_en.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_LOCKED_MONEY │ ├── severity.txt │ ├── name_en.txt │ ├── links.html │ ├── name.txt │ ├── recommendation_en.html │ ├── recommendation.html │ ├── links_en.html │ ├── description_en.html │ ├── description.html │ ├── example_en.html │ └── example.html ├── SOLIDITY_SAFEMATH │ ├── severity.txt │ ├── links.html │ ├── name_en.txt │ ├── links_en.html │ ├── name.txt │ ├── description.html │ ├── description_en.html │ ├── recommendation_en.html │ └── recommendation.html ├── SOLIDITY_TX_ORIGIN │ ├── severity.txt │ ├── links.html │ ├── name_en.txt │ ├── name.txt │ ├── description.html │ ├── recommendation.html │ ├── recommendation_en.html │ ├── links_en.html │ └── description_en.html ├── SOLIDITY_VISIBILITY │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation.html │ ├── recommendation_en.html │ ├── links_en.html │ ├── example.html │ ├── example_en.html │ ├── description_en.html │ └── description.html ├── VYPER_ERC20_APPROVE │ ├── severity.txt │ ├── links.html │ ├── name_en.txt │ ├── name.txt │ ├── description.html │ ├── description_en.html │ ├── recommendation.html │ ├── recommendation_en.html │ ├── links_en.html │ ├── example.html │ └── example_en.html ├── VYPER_LOCKED_MONEY │ ├── severity.txt │ ├── links.html │ ├── name_en.txt │ ├── links_en.html │ ├── name.txt │ ├── recommendation.html │ ├── recommendation_en.html │ ├── description_en.html │ ├── description.html │ ├── example.html │ └── example_en.html ├── VYPER_UNITLESS_NUMBER │ ├── severity.txt │ ├── links.html │ ├── name_en.txt │ ├── name.txt │ ├── links_en.html │ ├── recommendation_en.html │ ├── description_en.html │ ├── recommendation.html │ ├── description.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_ADDRESS_HARDCODED │ ├── severity.txt │ ├── links.html │ ├── links_en.html │ ├── name_en.txt │ ├── name.txt │ ├── recommendation.html │ ├── description_en.html │ ├── recommendation_en.html │ ├── description.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_BALANCE_EQUALITY │ ├── severity.txt │ ├── links.html │ ├── links_en.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation_en.html │ ├── recommendation.html │ ├── description.html │ ├── example.html │ ├── example_en.html │ └── description_en.html ├── SOLIDITY_CALL_WITHOUT_DATA │ ├── severity.txt │ ├── links.html │ ├── links_en.html │ ├── name.txt │ ├── name_en.txt │ ├── description.html │ ├── description_en.html │ ├── example_en.html │ ├── recommendation_en.html │ ├── example.html │ └── recommendation.html ├── SOLIDITY_DO_WHILE_CONTINUE │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation.html │ ├── recommendation_en.html │ ├── links_en.html │ ├── description.html │ ├── example.html │ ├── description_en.html │ └── example_en.html ├── SOLIDITY_ERC20_APPROVE │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation.html │ ├── recommendation_en.html │ ├── description.html │ ├── description_en.html │ ├── links_en.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_ERC20_INDEXED │ ├── severity.txt │ ├── name_en.txt │ ├── name.txt │ ├── recommendation.html │ ├── recommendation_en.html │ ├── links.html │ ├── links_en.html │ ├── description_en.html │ ├── description.html │ ├── example_en.html │ └── example.html ├── SOLIDITY_OVERPOWERED_ROLE │ ├── severity.txt │ ├── name.txt │ ├── name_en.txt │ ├── links_en.html │ ├── recommendation_en.html │ ├── links.html │ ├── description.html │ ├── recommendation.html │ ├── description_en.html │ ├── example_en.html │ └── example.html ├── SOLIDITY_PRAGMAS_VERSION │ ├── severity.txt │ ├── links.html │ ├── links_en.html │ ├── name_en.txt │ ├── name.txt │ ├── recommendation.html │ ├── recommendation_en.html │ ├── example.html │ ├── example_en.html │ ├── description_en.html │ └── description.html ├── SOLIDITY_REVERT_REQUIRE │ ├── severity.txt │ ├── links.html │ ├── name_en.txt │ ├── name.txt │ ├── description.html │ ├── description_en.html │ ├── recommendation_en.html │ ├── recommendation.html │ ├── links_en.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_TRANSFER_IN_LOOP │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation.html │ ├── recommendation_en.html │ ├── links_en.html │ ├── description.html │ ├── description_en.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_UNCHECKED_CALL │ ├── severity.txt │ ├── links.html │ ├── name_en.txt │ ├── name.txt │ ├── recommendation_en.html │ ├── recommendation.html │ ├── links_en.html │ ├── description_en.html │ ├── description.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_UPGRADE_TO_050 │ ├── severity.txt │ ├── name.txt │ ├── name_en.txt │ ├── description.html │ ├── description_en.html │ ├── links.html │ ├── links_en.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_VAR_IN_LOOP_FOR │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation.html │ ├── recommendation_en.html │ ├── links_en.html │ ├── example.html │ ├── example_en.html │ ├── description.html │ └── description_en.html ├── SOLIDITY_WRONG_SIGNATURE │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation_en.html │ ├── recommendation.html │ ├── links_en.html │ ├── description.html │ ├── description_en.html │ ├── example_en.html │ └── example.html ├── VYPER_BALANCE_EQUALITY │ ├── severity.txt │ ├── links.html │ ├── links_en.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation_en.html │ ├── recommendation.html │ ├── description_en.html │ ├── description.html │ ├── example.html │ └── example_en.html ├── VYPER_TIMESTAMP_DEPENDENCE │ ├── severity.txt │ ├── links.html │ ├── links_en.html │ ├── name_en.txt │ ├── name.txt │ ├── recommendation.html │ ├── recommendation_en.html │ ├── description.html │ ├── description_en.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_CONSTRUCTOR_RETURN │ ├── severity.txt │ ├── links.html │ ├── name_en.txt │ ├── name.txt │ ├── links_en.html │ ├── recommendation.html │ ├── description.html │ ├── recommendation_en.html │ └── description_en.html ├── SOLIDITY_EXTRA_GAS_IN_LOOPS │ ├── severity.txt │ ├── links.html │ ├── name_en.txt │ ├── links_en.html │ ├── name.txt │ ├── description_en.html │ ├── description.html │ ├── recommendation_en.html │ ├── recommendation.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_GAS_LIMIT_IN_LOOPS │ ├── severity.txt │ ├── name_en.txt │ ├── links.html │ ├── name.txt │ ├── recommendation_en.html │ ├── recommendation.html │ ├── links_en.html │ └── description.html ├── SOLIDITY_INCORRECT_BLOCKHASH │ ├── severity.txt │ ├── links.html │ ├── name_en.txt │ ├── name.txt │ ├── recommendation_en.html │ ├── recommendation.html │ ├── description.html │ ├── links_en.html │ ├── description_en.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_MSGVALUE_EQUALS_ZERO │ ├── example.html │ ├── example_en.html │ ├── severity.txt │ ├── links.html │ ├── links_en.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation_en.html │ ├── recommendation.html │ ├── description.html │ └── description_en.html ├── SOLIDITY_SHOULD_NOT_BE_PURE │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── description_en.html │ ├── description.html │ ├── links_en.html │ ├── example_en.html │ └── example.html ├── SOLIDITY_SHOULD_NOT_BE_VIEW │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── description.html │ ├── description_en.html │ ├── links_en.html │ ├── example_en.html │ ├── example.html │ ├── recommendation_en.html │ └── recommendation.html ├── SOLIDITY_SHOULD_RETURN_STRUCT │ ├── severity.txt │ ├── links.html │ ├── name_en.txt │ ├── name.txt │ ├── recommendation_en.html │ ├── recommendation.html │ ├── description_en.html │ ├── links_en.html │ ├── description.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_UINT_CANT_BE_NEGATIVE │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation.html │ ├── links_en.html │ ├── recommendation_en.html │ ├── description_en.html │ ├── description.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_USING_INLINE_ASSEMBLY │ ├── severity.txt │ ├── links.html │ ├── name_en.txt │ ├── name.txt │ ├── recommendation_en.html │ ├── recommendation.html │ ├── links_en.html │ ├── description.html │ └── description_en.html ├── VYPER_REDUNDANT_FALLBACK_REJECT │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── description_en.html │ ├── description.html │ ├── recommendation.html │ ├── recommendation_en.html │ ├── links_en.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_ARRAY_LENGTH_MANIPULATION │ ├── severity.txt │ ├── links.html │ ├── links_en.html │ ├── name.txt │ ├── name_en.txt │ ├── description.html │ ├── description_en.html │ ├── recommendation.html │ └── recommendation_en.html ├── SOLIDITY_BYTE_ARRAY_INSTEAD_BYTES │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation_en.html │ ├── recommendation.html │ ├── description_en.html │ ├── description.html │ ├── links_en.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_DELETE_ON_DYNAMIC_ARRAYS │ ├── severity.txt │ ├── links.html │ ├── links_en.html │ ├── name.txt │ ├── name_en.txt │ ├── description_en.html │ ├── recommendation_en.html │ ├── description.html │ └── recommendation.html ├── SOLIDITY_DEPRECATED_CONSTRUCTIONS │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── description.html │ ├── description_en.html │ ├── recommendation_en.html │ ├── recommendation.html │ └── links_en.html ├── SOLIDITY_ERC20_TRANSFER_SHOULD_THROW │ ├── severity.txt │ ├── links.html │ ├── name_en.txt │ ├── name.txt │ ├── recommendation.html │ ├── recommendation_en.html │ ├── links_en.html │ ├── description_en.html │ ├── description.html │ └── example_en.html ├── SOLIDITY_REDUNDANT_FALLBACK_REJECT │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation.html │ ├── recommendation_en.html │ ├── links_en.html │ ├── example_en.html │ ├── example.html │ ├── description_en.html │ └── description.html ├── SOLIDITY_REWRITE_ON_ASSEMBLY_CALL │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation_en.html │ ├── recommendation.html │ ├── links_en.html │ ├── description_en.html │ └── description.html ├── VYPER_PRIVATE_MODIFIER_DONT_HIDE_DATA │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── links_en.html │ ├── name_en.txt │ ├── recommendation_en.html │ ├── recommendation.html │ ├── description.html │ ├── description_en.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_ERC20_FUNCTIONS_ALWAYS_RETURN_FALSE │ ├── severity.txt │ ├── links.html │ ├── recommendation_en.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation.html │ ├── links_en.html │ ├── description_en.html │ ├── description.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_FUNCTION_RETURNS_TYPE_AND_NO_RETURN │ ├── severity.txt │ ├── links.html │ ├── links_en.html │ ├── name_en.txt │ ├── name.txt │ ├── description_en.html │ ├── description.html │ ├── recommendation.html │ ├── recommendation_en.html │ ├── example.html │ └── example_en.html ├── SOLIDITY_PRIVATE_MODIFIER_DOES_NOT_HIDE_DATA │ ├── severity.txt │ ├── links.html │ ├── name.txt │ ├── name_en.txt │ ├── recommendation.html │ ├── recommendation_en.html │ ├── links_en.html │ ├── description.html │ └── description_en.html └── SOLIDITY_UNUSED_FUNCTION_SHOULD_BE_EXTERNAL │ ├── severity.txt │ ├── links.html │ ├── name_en.txt │ ├── name.txt │ ├── recommendation_en.html │ ├── recommendation.html │ ├── links_en.html │ ├── description.html │ └── description_en.html ├── tests_not_used_now ├── SOLIDITY_INTEGER_OVERFLOW_UNDERFLOW.sol ├── SOLIDITY_SIMILAR_VARIABLE_NAMES.sol ├── SOLIDITY_SHORT_ADDRESS_ATTACK.sol ├── SOLIDITY_DEAD_CODE.sol ├── SOLIDITY_LOOP_FUSION.sol ├── SOLIDITY_CONSTANT_STATE_VARIABLE.sol ├── SOLIDITY_CONSTANT_OUTCOME_OF_LOOP.sol ├── SOLIDITY_OPAQUE_PREDICATE.sol ├── SOLIDITY_EXPENSIVE_OPERATIONS_IN_LOOP.sol ├── SOLIDITY_REPEATED_COMPUTATION_IN_LOOP.sol ├── SOLIDITY_SEND_BALANCE_BEFORE_CHANGE.sol ├── SOLIDITY_DIVISION_BY_ZERO.sol ├── SOLIDITY_USING_UBTRUSTED_INPUTS.sol ├── SOLIDITY_DOS_WITH_BLOCK_GAS_LIMIT.sol ├── SOLIDITY_MISSING_INPUT_VALIDATION.sol ├── SOLIDITY_DUPLICATED_STORAGE.sol ├── SOLIDITY_REFACTOR_CONFUSING_PRECONDITION.sol ├── SOLIDITY_TRANSACTION_ORDERING_DEPENDENCE.sol ├── SOLIDITY_CROSS_FUNCTION_RACE_CONDITION.sol ├── SOLIDITY_UNCHECKED_MATH.sol ├── SOLIDITY_PITFALLS_IN_RACE_CONDITION.sol └── SOLIDITY_IMMUTABILITY.sol ├── src ├── main │ └── java │ │ └── ru │ │ └── smartdec │ │ └── smartcheck │ │ ├── app │ │ ├── package-info.java │ │ ├── cli │ │ │ ├── package-info.java │ │ │ └── Arguments.java │ │ ├── Media.java │ │ ├── Report.java │ │ ├── TreeFactory.java │ │ ├── SourceLanguage.java │ │ ├── ReportDefault.java │ │ └── DirectoryAnalysis.java │ │ ├── Pattern.java │ │ ├── Source.java │ │ ├── Query.java │ │ ├── Rule.java │ │ ├── package-info.java │ │ ├── Rules.java │ │ ├── ParseTree.java │ │ └── SearchableTreeDefault.java └── test │ └── resources │ └── rules │ ├── SOLIDITY_PRAGMAS_VERSION.sol │ ├── VYPER_PRIVATE_MODIFIER_DONT_HIDE_DATA.vy │ ├── SOLIDITY_PRIVATE_MODIFIER_DOES_NOT_HIDE_DATA.sol │ ├── SOLIDITY_BYTE_ARRAY_INSTEAD_BYTES.sol │ ├── VYPER_BALANCE_EQUALITY.vy │ ├── VYPER_REDUNDANT_FALLBACK_REJECT.vy │ ├── SOLIDITY_SAFEMATH.sol │ ├── SOLIDITY_VAR_IN_LOOP_FOR.sol │ ├── VYPER_ERC20_APPROVE.vy │ ├── SOLIDITY_VAR.sol │ ├── SOLIDITY_REDUNDANT_FALLBACK_REJECT.sol │ ├── SOLIDITY_EXACT_TIME.sol │ ├── VYPER_UNITLESS_NUMBER.vy │ ├── SOLIDITY_USING_INLINE_ASSEMBLY.sol │ ├── SOLIDITY_DOS_WITH_THROW.sol │ ├── SOLIDITY_DO_WHILE_CONTINUE.sol │ └── VYPER_LOCKED_MONEY.vy ├── .gitattributes └── .gitignore /rule_descriptions/SOLIDITY_DIV_MUL/severity.txt: -------------------------------------------------------------------------------- 1 | 2 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_SEND/severity.txt: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_VAR/severity.txt: -------------------------------------------------------------------------------- 1 | 2 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_EXACT_TIME/severity.txt: -------------------------------------------------------------------------------- 1 | 2 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_LOCKED_MONEY/severity.txt: -------------------------------------------------------------------------------- 1 | 3 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_SAFEMATH/severity.txt: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_TX_ORIGIN/severity.txt: -------------------------------------------------------------------------------- 1 | 3 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_VISIBILITY/severity.txt: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /rule_descriptions/VYPER_ERC20_APPROVE/severity.txt: -------------------------------------------------------------------------------- 1 | 2 -------------------------------------------------------------------------------- /rule_descriptions/VYPER_LOCKED_MONEY/severity.txt: -------------------------------------------------------------------------------- 1 | 3 -------------------------------------------------------------------------------- /rule_descriptions/VYPER_UNITLESS_NUMBER/severity.txt: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_ADDRESS_HARDCODED/severity.txt: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_BALANCE_EQUALITY/severity.txt: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_CALL_WITHOUT_DATA/severity.txt: -------------------------------------------------------------------------------- 1 | 2 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_DO_WHILE_CONTINUE/severity.txt: -------------------------------------------------------------------------------- 1 | 2 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_ERC20_APPROVE/severity.txt: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_ERC20_INDEXED/severity.txt: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_OVERPOWERED_ROLE/severity.txt: -------------------------------------------------------------------------------- 1 | 2 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_PRAGMAS_VERSION/severity.txt: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_REVERT_REQUIRE/severity.txt: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_SEND/links.html: -------------------------------------------------------------------------------- 1 |
2 | Используется библиотека SafeMath.
3 |
2 | SafeMath library is used.
3 |
2 | Подготовьте ваш код к релизу Solidity 0.5.0. 3 |
-------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_ERC20_INDEXED/recommendation.html: -------------------------------------------------------------------------------- 1 |Используйте индексированные аргументы, как указано в стандарте.
-------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_REWRITE_ON_ASSEMBLY_CALL/recommendation_en.html: -------------------------------------------------------------------------------- 1 |Save output to the separate area of memory.
2 | -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_UPGRADE_TO_050/description_en.html: -------------------------------------------------------------------------------- 1 |2 | Prepare your code for Solidity 0.5.0 release. 3 |
-------------------------------------------------------------------------------- /src/main/java/ru/smartdec/smartcheck/app/cli/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package ru.smartdec.smartcheck.app.cli; 5 | -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_BALANCE_EQUALITY/recommendation_en.html: -------------------------------------------------------------------------------- 1 |Use indexed events' arguments, as stated in ERC-20 Token Standard
-------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_REWRITE_ON_ASSEMBLY_CALL/recommendation.html: -------------------------------------------------------------------------------- 1 |Записывайте возвращаемое значение в очищенную память.
2 | -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_TX_ORIGIN/description.html: -------------------------------------------------------------------------------- 1 |
2 | tx.origin используется для авторизации.
3 |
bytes.
4 | bytes.
4 | 2 | Avoid loops with big or unknown number of steps. 3 |
4 | -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_MSGVALUE_EQUALS_ZERO/recommendation.html: -------------------------------------------------------------------------------- 1 |
2 | Функция approve() стандарта ERC-20 является уязвимой.
3 |
2 | Вызов функции call без передачи каких-либо данных.
3 |
2 | Выполнение деления после умножения позволит повысить точность вычислений. 3 |
-------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_DIV_MUL/recommendation_en.html: -------------------------------------------------------------------------------- 1 |2 | Multiplication before division may increase the rounding precision. 3 |
4 | -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_DO_WHILE_CONTINUE/recommendation.html: -------------------------------------------------------------------------------- 1 |
2 | Не используйте инструкцию continue в цикле do-while.
3 |
2 | The payment rejection default function is redundant. 3 |
4 | -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_PRAGMAS_VERSION/recommendation.html: -------------------------------------------------------------------------------- 1 |2 | Укажите конкретную версию компилятора (pragma solidity x.y.z;). 3 |
4 | -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_PRAGMAS_VERSION/recommendation_en.html: -------------------------------------------------------------------------------- 1 |2 | Specify the exact compiler version (pragma solidity x.y.z;). 3 |
4 | -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_TX_ORIGIN/recommendation.html: -------------------------------------------------------------------------------- 1 |tx.origin для авторизации.
4 |
2 | ERC-20 approve function is vulnerable to front-running attack.
3 |
2 | Do not use continue instruction in the do-while loop.
3 |
2 | Use blockhash function only for last 256 blocks.
3 |
В Solidity функции, которые обозначены как view, не должны изменять состояние.
assembly if possible.
4 | 2 | Default-функция, отклоняющая платежи, является избыточной. 3 |
4 |5 | -------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_CALL_WITHOUT_DATA/description_en.html: -------------------------------------------------------------------------------- 1 |
2 | Use of low-level call function with no arguments provided.
3 |
It is required to return true, if the function was successful.
2 | Проверка условия msg.value == 0 бессмысленна в большинстве случаев.
3 |
2 | The msg.value == 0 condition check is meaningless in most cases.
3 |
Следует использовать такую схему вывода ETH, в которой пользователи сами забрают свои средства.
-------------------------------------------------------------------------------- /rule_descriptions/SOLIDITY_VAR/recommendation_en.html: -------------------------------------------------------------------------------- 1 |uint256).
4 | 2 | Реализуйте функции вывода средств или не реализуйте функции, принимающие платежи. 3 |
4 | -------------------------------------------------------------------------------- /rule_descriptions/VYPER_LOCKED_MONEY/recommendation_en.html: -------------------------------------------------------------------------------- 1 |
2 | Implement a function with withdrawal functionality or reject all the payments. 3 |
4 |
--------------------------------------------------------------------------------
/src/test/resources/rules/SOLIDITY_PRAGMAS_VERSION.sol:
--------------------------------------------------------------------------------
1 | // Function doesn't initialize return value. As result default value will be returned.
2 | Избегайте циклов со слишком большим или заранее неизвестным количеством шагов.
3 |
2 | Используйте функцию
2 | Use
2 | Keep in mind that anyone can read values of variables in Ethereum.
3 |
4 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_BYTE_ARRAY_INSTEAD_BYTES/description_en.html:
--------------------------------------------------------------------------------
1 |
2 | Use Использование конструкции вида Using the construction
2 | Имейте в виду, что значения переменных в Ethereum являются общедоступными.
3 |
4 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ERC20_FUNCTIONS_ALWAYS_RETURN_FALSE/recommendation.html:
--------------------------------------------------------------------------------
1 |
2 | Необходимо возвращать In Solidity, function that do not read from the state or modify it can be declared as In Solidity, functions that do not read from the state or modify it can be declared as Возвращаемое значение не инициализировано, поэтому всегда будет возвращаться значение по умолчанию.
2 | Удалите функцию для экономии пространства: контракт автоматически отклонит платежи.
3 |
2 | Remove the function to save space: the contract will reject payments automatically.
3 | Используйте функцию
2 | Используйте Используйте функцию Если не требуется, чтобы функция возвращала значение, не указывайте
2 | Имейте в виду, что модификатор
2 | Используйте функцию Withdrawal pattern is the recommended method of sending funds. In this pattern, users take their ETH by themselves. В стандарте ERC-20 рекомендуется бросать исключения в функциях
2 | Keep in mind that the
2 | В Solidity функции, которые обозначены как
2 | Address arguments of The ERC20 standard recommends throwing exceptions in functions
2 | Implement a withdraw function or reject payments (contracts without a fallback function do it automatically).
3 |
2 | Удалите функцию для экономии газа и улучшения читаемости кода: контракт автоматически отклонит платежи.
3 |
4 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ERC20_INDEXED/description.html:
--------------------------------------------------------------------------------
1 |
2 | Аргументы типа address событий
2 | Solidity работает только с целыми числами. Таким образом, при делении, предшевствующем умноженитю, может возникать большая погрешность.
3 |
2 | If you don't need the return value of the function, do not specify Only use
2 | Use structure for
2 | Use the
2 | Remove the function to save on gas and increase code readability: the contract will reject payments automatically.
3 |
4 |
--------------------------------------------------------------------------------
/src/test/resources/rules/VYPER_PRIVATE_MODIFIER_DONT_HIDE_DATA.vy:
--------------------------------------------------------------------------------
1 | #
2 | Applying Only use the
2 | Реализуйте функции вывода средств или отклонения платежей (контракты без функции резервного копирования выполняют это автоматически).
3 |
2 | Используйте уровень видимости
2 | Компилятор до версии 0.5.0 неправильно обрабатывает
2 | Этот цикл является бесконечным:
3 | Use
2 | Используйте структуры для
2 | Устаревшие конструкции:
2 | Prior to version 0.5.0, Solidity compiler handles
2 | The following loop is infinite:
3 | Используйте
2 | The contract contains unknown address. This address might be used for some malicious activity. Please check hardcoded address and it's usage.
3 |
2 | Функция
2 | Для сравнения переменных типа
2 | По возможности, избегайте использование
2 | Inline assembly is a way to access the Ethereum Virtual Machine at a low level. This discards several important safety features of Solidity.
3 |
2 | Deprecated constructions:
2 | В следующем примере используется неявный тип
2 | In the following example, the type
2 | Consider using struct instead of multiple return values for
2 | Использование в коде контракта адресов других контрактов потенциально может привести к уязвимостям. Требуется проверить на уязвимости и код вызываемого контракта.
3 |
2 | Применение
2 | Функция Use Since the construction
2 | Если
2 | The
2 | Не используйте Для лучшей читаемости кода используйте Поскольку конструкция
2 | For comparison of
2 | В сигнатурах функций надо использовать каноническое представление для типов, например,
2 | В функциях
2 | Contracts programmed to receive ether should implement a way to withdraw it, i.e., call
2 | Expect calls to external contract to fail. When sending ether, check for the return value and handle errors. The recommended way of doing ether transfers is
2 | Не используйте
4 |
--------------------------------------------------------------------------------
/tests_not_used_now/SOLIDITY_EXPENSIVE_OPERATIONS_IN_LOOP.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.5;
2 | contract Voting {
3 | uint sum= 0;
4 | function p3 ( uint x ){
5 | for ( uint i = 0 ; i< x ; i ++){
6 | sum+=i;
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/tests_not_used_now/SOLIDITY_REPEATED_COMPUTATION_IN_LOOP.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.5;
2 | contract Voting {
3 | uint x=1;
4 | uint y=2;
5 | function p(uint k){
6 | uint sum=0;
7 | for(uint i=1;i<=k;i++) sum=sum+x+y;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/tests_not_used_now/SOLIDITY_SEND_BALANCE_BEFORE_CHANGE.sol:
--------------------------------------------------------------------------------
1 | contract SimpleBank {
2 | mapping(address => uint) balances;
3 |
4 | function withdraw(uint amount) {
5 | balances[msg.sender] -= amount;
6 | msg.sender.transfer(amount);
7 | }
8 | }
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_VAR_IN_LOOP_FOR/example.html:
--------------------------------------------------------------------------------
1 |
2 | В следующем примере используется неявный тип В следующем примере default-функция по отклонению платежа является избыточной:
2 | Длина динамического массива изменяется напрямую. Это может привести к гигантским массивам, которые в свою очередь могут сделать возможной overlap атаку (перезапись других данных в хранилище).
3 |
2 | In the following example, the type In the following example, the payment rejection default function is redundant:
2 |
2 | We recommend designing contracts in a trustless manner. For instance, this functionality can be implemented in the contract's constructor. Another option is to use MultiSig wallet at this address.
3 | Here is the example of correct
2 | State variable,
2 | Контракты, запрограммированные на получение эфира, должны реализовать способ его снятия, т.е. вызывать функции
2 | Производится отправка ETH в цикле. В случае, если хотя бы один из адресатов не может принимать ETH (например, является контрактом со стандартной fallback функцией), то отправка ETH в таком цикле будет невозможна.
3 |
2 | Dangerous use of inline assembly instruction of
2 | We do not recommend using
2 | В конструкторе контракта используется
2 | Данная функция предназначена для вызова только с одного адреса. Таким образом, работа контракта зависит от данного адреса. В таком случае возможны нежелательные ситуации, например если приватный ключ данного адреса будет утерян.
3 |
2 | Ожидайте, что вызовы внешнего контракта могут завершиться неудачей. При отправке эфира проверьте возвращаемое значение и обработайте ошибки. Рекомендованный способ передачи эфира — с помощью функции
2 |
5 | Vulnerability type by SmartDec classification:
6 | Authorization with tx.origin.
7 |
2 | Contracts including at least one function with
4 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_BALANCE_EQUALITY/description.html:
--------------------------------------------------------------------------------
1 |
2 | Используется проверка баланса на строгое равенство.
3 |
5 | Избегайте проверки баланса на строгое равенство: злоумышленник может принудительно отправить эфир на любой адрес, используя уничтожение контракта или майнинг.
6 | Here is the example of correct
2 |
4 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_UNITLESS_NUMBER/recommendation_en.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_PRIVATE_MODIFIER_DOES_NOT_HIDE_DATA/description.html:
--------------------------------------------------------------------------------
1 |
2 | Вопреки распространенному заблуждению, модификатор
2 | Мы не рекомендуем использовать библиотеку
2 | Контракты, в которых есть хотя бы одна функция с декоратором
2 | Опасное использование
2 | В контракте используется
2 | Do not use Ниже приведен пример корректной
2 |
4 |
5 |
--------------------------------------------------------------------------------
/src/main/java/ru/smartdec/smartcheck/Source.java:
--------------------------------------------------------------------------------
1 | package ru.smartdec.smartcheck;
2 |
3 | import org.antlr.v4.runtime.CharStream;
4 |
5 | /**
6 | *
7 | */
8 | public interface Source {
9 |
10 | /**
11 | * @return char chars
12 | * @throws Exception exception
13 | */
14 | CharStream chars() throws Exception;
15 | }
16 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_SEND/description_en.html:
--------------------------------------------------------------------------------
1 |
2 | The
5 | The recommended way to perform checked ether payments is In the following example, the Preferred alternative:
2 | Используется строгое сравнение с
2 | Ниже приведен пример корректной
2 | The balance is checked for strict equality.
3 |
5 | Avoid checking for strict balance equality: an adversary can forcibly send Ether to any address via
2 | В следующем примере используется функция Предпочтительный вариант:
2 | В условии цикла
2 | If state variable,
2 | Мы рекомендуем разрабатывать контракты так, чтобы их работа ни от кого не зависела. Один из возможных вариантов решения данной задачи - реализация данной функциональности в конструкторе контракта либо в скрипте деплоя. Ещё один вариант - использовать MultiSig кошелек по этому адресу.
3 |
2 | Variables of
2 | В следующем примере используется функция
2 | В следующем примере используется небезопасный способ указания версий компиляторов:
3 |
10 | Безопасный вариант:
11 |
2 | In the following example, the
2 | Используется проверка баланса на строгое равенство.
3 |
5 | Избегайте проверки баланса на строгое равенство: злоумышленник может принудительно отправить эфир на любой адрес, используя уничтожение контракта или майнинг. Также эфир мог быть прислан на предвычисленный адрес контракта.
6 |
2 | In the following example, аn unsafe way to specify versions of the compiler is used:
3 |
10 | Safe alternative:
11 |
2 | В следующем примере не используется модификатор при объявлении функции:
3 |
10 | Безопасный вариант:
11 |
2 | Solidity operates only with integers. Thus, if the division is done before the multiplication, the rounding errors can increase dramatically.
3 |
5 | Vulnerability type by SmartDec classification:
6 | Precision issues.
7 |
2 | Используется функция
5 | Рекомендуемым способом выполнения проверенных эфирных платежей является
2 | In the following example, a specific modifier is not used when declaring a function:
3 |
10 | Preferred alternatives:
11 |
2 | Vyper allows you to use unit label to either
4 |
5 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_UNITLESS_NUMBER/recommendation.html:
--------------------------------------------------------------------------------
1 |
2 | Функция
4 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_INCORRECT_BLOCKHASH/example.html:
--------------------------------------------------------------------------------
1 |
2 | В следующем примере функция
2 | Переменные типа
2 | Функция с уровнем видимости
2 | Vyper позволяет использовать единицы измерения для типов
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 |
3 | # Compiled class file
4 | *.class
5 |
6 | # Log file
7 | *.log
8 |
9 | # BlueJ files
10 | *.ctxt
11 |
12 | # Mobile Tools for Java (J2ME)
13 | .mtj.tmp/
14 |
15 | # Package Files #
16 | *.jar
17 | *.war
18 | *.ear
19 | *.zip
20 | *.tar.gz
21 | *.rar
22 |
23 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
24 | hs_err_pid*
25 | /.idea/
26 | /gen/
27 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_INCORRECT_BLOCKHASH/example_en.html:
--------------------------------------------------------------------------------
1 |
2 | In the following example, In the following example, the payment rejection fallback is redundant:
2 | A function with
2 | In the following example,
2 | In this case, В следующем примере fallback-функция по отклонению платежа является избыточной:
2 | ETH is transferred in a loop. If at least one address cannot receive ETH (e.g. it is a contract with default fallback function), the whole transaction will be reverted.
3 |
5 | Vulnerability type by SmartDec classification:
6 | DoS with revert.
7 |
2 | В следующем примере используются функция
2 | В случаях, когда переменные, хранящиеся в В следующем примере обращение к переменной
2 | In the following example, contracts programmed to receive ether does not call
2 | The length of the dynamic array is changed directly. In this case, the appearance of gigantic arrays is possible and it can lead to a storage overlap attack (collisions with other data in storage).
3 |
5 | Vulnerability type by SmartDec classification:
6 | Overlap attack.
7 |
2 | В следующем примере
2 | В данной ситуации более безопасными являются функции In the following example,
2 | В следующем примере контракт, запрограммированный на получение эфира, не вызывает ни одну из функций
2 | In the following example, В следующем примере в сигнатуре функции обозначен только тип возвращаемого значения, а в ее теле нет
2 | В следующем примере используется проверка баланса на строгое равенство:
3 |
12 | Безопасный вариант:
13 |
2 | Contrary to a popular misconception, the
5 | Vulnerability type by SmartDec classification:
6 | Privacy.
7 |
2 | In Solidity, the function signature is defined as the canonical expression of the basic prototype without data location specifier, i.e. the function name with the parenthesised list of parameter types. Parameter types are split by a single comma - no spaces are used. This means one should use
2 | In the following example, checking for strict balance equality is used:
3 |
12 | Secure alternative:
13 |
2 | Functions of ERC-20 Token Standard should throw in special cases:
3 |
2 | The balance is checked for strict equality.
3 |
5 | Avoid checking for strict balance equality: an adversary can forcibly send ether to any address via
8 | Vulnerability type by SmartDec classification:
9 | Ether transfer.
10 | В следующем примере используется массив байтов:
13 | Альтернатива:
14 | In the following example, byte array is used:
13 | Alternative:
14 |
2 | Strict comparison with
5 | Vulnerability type by SmartDec classification:
6 | Timestamp manipulation.
7 |
2 | The default function visibility level in contracts is В следующем контракте используется функция In the following contract the function
2 | Функции стандарта ERC-20 должны бросать исключения в случиях:
3 |
2 | По умолчанию, переменные, не объявленные как
2 | This function is callable only from one address. Therefore, the system depends heavily on this address. In this case, there are scenarios that may lead to undesirable consequences for investors, e.g. if the private key of this address becomes compromised.
3 |
5 | Vulnerability type by SmartDec classification:
6 | Overpowered owner.
7 |
2 |
5 | Vulnerability type by SmartDec classification:
6 | Assembly return in constructor.
7 |
2 | The payment rejection fallback is redundant.
3 |
5 | Contracts should reject unexpected payments. Before Solidity 0.4.0, it was done manually:
6 |
13 | Starting from Solidity 0.4.0, contracts without a fallback function automatically
14 | revert payments, making the code above redundant.
15 | In the following example, the function's signature only denotes the type of the return value, but the function's body does not contain
2 | Fallback-функция по отклонению платежа является избыточной.
3 |
5 | Контракты должны отклонять неожиданные платежи. До версии 0.4.0 в Solidity это делалось вручную:
6 |
12 | Начиная с Solidity 0.4.0, контракты без fallback-функции автоматически возвращают платежи, что делает код, представленный выше, избыточным.
13 |
2 | В Solidity есть уровни видимости по умолчанию. Для функций в контрактах -
2 | This code uses incorrect function signature:
3 |
17 | Use
2 | Initializing the variables without the
2 | Solidity source files indicate the versions of the compiler they can be compiled with.
3 |
11 | It is recommended to follow the latter example, as future compiler versions may handle certain language constructions in a way the developer did not foresee.
12 |
2 | Файлы исходных текстов Solidity указывают версии компилятора, с которыми они могут быть скомпилированы.
3 |
11 | Рекомендуется следовать последнему примеру, поскольку будущие версии компилятора могут обрабатывать определенные языковые конструкции способом, который разработчик не предвидел.
12 | В следующем примере переменная
2 | В этом примере используется неправильно сформированная сигнатура фукнции:
3 |
17 | Правильный вариант -
2 | В следующем контракте адрес задан в исходном коде:
3 |
17 | Не забудьте проверить код контракта по адресу
18 | In the following example, sensitive data is stored in
2 | В следующем примере майнер может воздействовать на значение
2 | In the following example,
2 | В данном примере у контракта есть
19 | Однако, вывести средства с адреса контракта невозможно.
20 |
2 | В следующем примере используется проверка баланса на строгое равенство:
3 |
14 | Безопасный вариант:
15 |
2 | In the following example, checking for strict balance equality is used:
3 |
14 | Secure alternative:
15 |
2 | In the following example, В следующем контракте определена функция In the following contract, the address is specified in the source code:
2 |
16 | Do not forget to check the contract at the address
2 | В данном примере величина In the following contract
2 | In the following example the contract implements a function with
19 | However, it is impossible to withdraw ETH from the contract address.
20 | В следующем примере в теле условного оператора
2 | В данном примере используется функция
2 | In the following example, use of blockhash только для последних 256 блоков.
3 | transfer, which is equivalent to if (!send()) { revert();}.
3 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_PRIVATE_MODIFIER_DONT_HIDE_DATA/recommendation_en.html:
--------------------------------------------------------------------------------
1 | uint256).
4 | bytes instead of byte[] for lower gas consumption.
3 | if (условие) {revert();} вместо require(условие);if (condition) {revert();} instead of require(condition);
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_VAR_IN_LOOP_FOR/recommendation_en.html:
--------------------------------------------------------------------------------
1 | assembly.
4 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_PRIVATE_MODIFIER_DONT_HIDE_DATA/recommendation.html:
--------------------------------------------------------------------------------
1 | uint256).
4 | true в случае успешного выполнения функции.
3 | pure.
2 | view.
2 |
4 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_FUNCTION_RETURNS_TYPE_AND_NO_RETURN/description.html:
--------------------------------------------------------------------------------
1 | approve стандарта ERC-20 только для изменения одобренного количества токенов с или до 0.bytes вместо byte[] для более низкого расхода газа.
3 | approve стандарта ERC-20 только для изменения одобренного количества токенов с 0 или до 0.
2 |
4 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_FUNCTION_RETURNS_TYPE_AND_NO_RETURN/recommendation.html:
--------------------------------------------------------------------------------
1 | returns в сигнатуре.private не делает переменную невидимой.
3 | transfer, которая является эквивалентом if (!send()) { revert();}.
3 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_WRONG_SIGNATURE/recommendation_en.html:
--------------------------------------------------------------------------------
1 | tx.origin for authorization. Use msg.sender instead.
4 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ERC20_TRANSFER_SHOULD_THROW/recommendation.html:
--------------------------------------------------------------------------------
1 | uint256).
4 | transfer и transferFrom.private modifier does not make a variable invisible.
3 | pure, не должны считывать или изменять состояние.
3 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ERC20_INDEXED/description_en.html:
--------------------------------------------------------------------------------
1 | Transfer and Approve events of ERC-20 token standard must be indexed.
3 | transfer and transferFrom.Transfer и Approve стандарта ERC-20 должны быть индексированными.
3 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_VAR/links_en.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_WRONG_SIGNATURE/recommendation.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tests_not_used_now/SOLIDITY_SHORT_ADDRESS_ATTACK.sol:
--------------------------------------------------------------------------------
1 | contract SimpleBank {
2 | function sendMoney(address to, uint amount) {
3 | to.transfer(amount);//нет проверки на длину адреса
4 | }
5 | }
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_DIV_MUL/description.html:
--------------------------------------------------------------------------------
1 | uint256).
4 | returns in function signature.
3 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_ERC20_APPROVE/recommendation_en.html:
--------------------------------------------------------------------------------
1 | approve function of ERC-20 standard to change allowed amount to 0 or from 0 (wait till transaction is mined and approved).
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_SHOULD_RETURN_STRUCT/recommendation_en.html:
--------------------------------------------------------------------------------
1 | internal function, which returns several parameters, if it improves code readability.
3 | external visibility modifier for functions never called from the contract via internal call.
3 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_REDUNDANT_FALLBACK_REJECT/recommendation_en.html:
--------------------------------------------------------------------------------
1 | delete or .length = 0 to dynamically-sized storage arrays may lead to Out-of-Gas exception.
3 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ERC20_APPROVE/recommendation_en.html:
--------------------------------------------------------------------------------
1 | approve function of the ERC-20 standard to change allowed amount to 0 or from 0 (wait till transaction is mined and approved).
2 |
6 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_SEND/links_en.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_TX_ORIGIN/links_en.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_UNUSED_FUNCTION_SHOULD_BE_EXTERNAL/recommendation.html:
--------------------------------------------------------------------------------
1 | external в случае, когда функция не вызывается с помощью внутреннего вызова.
3 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_CONSTRUCTOR_RETURN/links_en.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_DO_WHILE_CONTINUE/description.html:
--------------------------------------------------------------------------------
1 | continue внутри цикла do-while: игнорируется условие внутри while.
3 |
5 |
11 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_EXACT_TIME/recommendation_en.html:
--------------------------------------------------------------------------------
1 |
6 | do {
7 | continue;
8 | } while(false);
9 |
10 | block.timestamp and now only in inequalities (>, <, >=, <=).
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_SHOULD_NOT_BE_VIEW/links_en.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_SHOULD_RETURN_STRUCT/recommendation.html:
--------------------------------------------------------------------------------
1 | internal функций, которые возвращают несколько переменных, если это улучшит читаемость кода.
3 |
2 |
6 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_DEPRECATED_CONSTRUCTIONS/description.html:
--------------------------------------------------------------------------------
1 | years, sha3, suicide, throw и constant функции.
3 | continue inside do-while loop incorrectly: it ignores while condition.
3 |
5 |
11 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_EXACT_TIME/recommendation.html:
--------------------------------------------------------------------------------
1 |
6 | do {
7 | continue;
8 | } while(false);
9 |
10 | block.timestamp и now только в неравенствах (>, <, >=, <=).
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_USING_INLINE_ASSEMBLY/links_en.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_VISIBILITY/links_en.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ADDRESS_HARDCODED/description_en.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ERC20_APPROVE/description.html:
--------------------------------------------------------------------------------
1 | approve стандарта ERC-20 является уязвимой. Средства могут быть потрачены до того, как изменится значение allowance.
3 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_UINT_CANT_BE_NEGATIVE/recommendation.html:
--------------------------------------------------------------------------------
1 | uint с 0 используйте строгое неравенство, либо операторы != и ==.
3 | assembly. Низкоуровневые команды затрудняют понимание кода, осложняют проведение аудита.
3 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_DELETE_ON_DYNAMIC_ARRAYS/recommendation_en.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_DEPRECATED_CONSTRUCTIONS/description_en.html:
--------------------------------------------------------------------------------
1 | years, sha3, suicide, throw and constant functions.
3 |
2 |
7 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_VAR/example.html:
--------------------------------------------------------------------------------
1 | var:
3 |
5 |
9 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_VAR/example_en.html:
--------------------------------------------------------------------------------
1 |
6 | for (var i = 0; i < array.length; i++) { /* ... */ }
7 |
8 | var is used:
3 |
5 |
9 |
--------------------------------------------------------------------------------
/tests_not_used_now/SOLIDITY_DEAD_CODE.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.5;
2 | contract Voting {
3 | function p1( uint x ){
4 | if ( x> 5){
5 | if ( x*x< 20){
6 | a=a+1;//dead code
7 | }
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/tests_not_used_now/SOLIDITY_LOOP_FUSION.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.5;
2 | contract Voting {
3 | function p5 ( uint x ) {
4 | uint m=0;
5 | uint v=0;
6 | for ( uint i = 0;i
6 | for (var i = 0; i < array.length; i++) { /* ... */ }
7 |
8 | approve function of ERC-20 is vulnerable. Using front-running attack one can spend approved tokens before change of allowance value.
3 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_SHOULD_RETURN_STRUCT/description_en.html:
--------------------------------------------------------------------------------
1 | internal or private functions. It can improve code readability.
3 |
2 |
--------------------------------------------------------------------------------
/tests_not_used_now/SOLIDITY_CONSTANT_STATE_VARIABLE.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.5;
2 | contract Voting {
3 | uint256 public batFund = 300 * 10**24;//если эта переменная не изменяется нигде далее в программе, должна быть объявлена константой
4 | }
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ADDRESS_HARDCODED/description.html:
--------------------------------------------------------------------------------
1 | delete или .length = 0 к динамическому массиву может требовать слишком большое количество газа и приводить к исключению.
3 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ERC20_FUNCTIONS_ALWAYS_RETURN_FALSE/links_en.html:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_GAS_LIMIT_IN_LOOPS/links_en.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_INCORRECT_BLOCKHASH/description.html:
--------------------------------------------------------------------------------
1 | blockhash возвращает ненулевое значение только для последних 256 блоков. Кроме того, blockhash(block.number) всегда равно 0.
3 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_REVERT_REQUIRE/recommendation_en.html:
--------------------------------------------------------------------------------
1 | require for better code readabilityif (condition) {revert();} is equivalent to require(!condition);.internal или private функция возвращает несколько параметров, рекомендуется использовать структуру. Это может улучшить читаемость кода.
3 |
2 |
6 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_REDUNDANT_FALLBACK_REJECT/links_en.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ERC20_FUNCTIONS_ALWAYS_RETURN_FALSE/description_en.html:
--------------------------------------------------------------------------------
1 | transfer, transferFrom or approve functions do not return true for any values of input parameters.
3 | return в конструкторе для лучшей читаемости кода. В целом, контракты, использующие assembly в конструкторе, не являются безопасными.
3 | require.if (condition) {revert();} равносильна конструкции require(!condition);.uint type variables with 0 use >, <, !=, or == operators.
3 | uint256 и int256 вместо uint или int.
3 | transfer, transferFrom или approve не возвращается true ни при каких значениях входных параметров.
3 | transfer (recommended), send, or call.value at least once.
3 | transfer.
3 | block.timestamp для генерации случайных чисел, создавайте контракты так, чтобы их логика не зависела от точного значения block.timestamp.
3 | var внутри for:
3 |
5 |
9 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_REDUNDANT_FALLBACK_REJECT/example.html:
--------------------------------------------------------------------------------
1 |
6 | for (var i = 0; i < array.length; i++) { /* ... */ }
7 |
8 |
3 |
10 |
--------------------------------------------------------------------------------
/src/main/java/ru/smartdec/smartcheck/app/Media.java:
--------------------------------------------------------------------------------
1 | package ru.smartdec.smartcheck.app;
2 |
3 | /**
4 | *
5 | */
6 | public interface Media {
7 |
8 | /**
9 | * @param info info
10 | */
11 | void accept(DirectoryAnalysis.Info info);
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/ru/smartdec/smartcheck/app/Report.java:
--------------------------------------------------------------------------------
1 | package ru.smartdec.smartcheck.app;
2 |
3 | /**
4 | *
5 | */
6 | public interface Report {
7 |
8 | /**
9 | * @throws Exception exception
10 | */
11 | void print() throws Exception;
12 | }
13 |
--------------------------------------------------------------------------------
/src/test/resources/rules/SOLIDITY_PRIVATE_MODIFIER_DOES_NOT_HIDE_DATA.sol:
--------------------------------------------------------------------------------
1 | pragma solidity 0.4.24;
2 |
3 | contract MarketPlace {
4 | //
4 | @public
5 | @payable
6 | def __default__():
7 | throw
8 |
9 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_REVERT_REQUIRE/links_en.html:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_VAR_IN_LOOP_FOR/example_en.html:
--------------------------------------------------------------------------------
1 | var is used inside of for:
3 |
5 |
9 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_REDUNDANT_FALLBACK_REJECT/example_en.html:
--------------------------------------------------------------------------------
1 |
6 | for (var i = 0; i < array.length; i++) { /* ... */ }
7 |
8 |
3 |
10 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_UNUSED_FUNCTION_SHOULD_BE_EXTERNAL/links_en.html:
--------------------------------------------------------------------------------
1 |
4 | @public
5 | @payable
6 | def __default__():
7 | throw
8 |
9 |
2 |
--------------------------------------------------------------------------------
/src/test/resources/rules/SOLIDITY_BYTE_ARRAY_INSTEAD_BYTES.sol:
--------------------------------------------------------------------------------
1 | pragma solidity 0.4.24;
2 | contract C {
3 |
4 | // blockhash function returns a non-zero value only for 256 last blocks. Besides, it always returns 0 for the current block, i.e. blockhash(block.number) always equals to 0.
3 | view-function:
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_EXTRA_GAS_IN_LOOPS/description_en.html:
--------------------------------------------------------------------------------
1 |
3 | contract C {
4 | function f(uint a, uint b) view returns (uint) {
5 | return a * (b + 42) + now;
6 | }
7 | }
8 | .balance, or .length of non-memory array is used in the condition of for or while loop. In this case, every iteration of loop consumes extra gas.
3 | transfer (рекомендуется), send или call.value как минимум один раз.
3 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_TRANSFER_IN_LOOP/description.html:
--------------------------------------------------------------------------------
1 | CALL family, which overwrites the input with the output.
3 | In case the arbitrary address is called return value may differ from expected one.
4 | SafeMath library for all arithmetic operations. It is good practice to use explicit checks where it is really needed, and to avoid extra checks where overflow/underflow is impossible.
3 | return. Из-за return процесс деплоя будет отличаться от интуитивного. Например, задеплоенный байткод может не содержать функций, реализованных в исходном коде.
3 | transfer.
3 | tx.origin is used for authorization.
3 | @payable decorator should implement a way to withdraw ETH, i.e. call send (recommended), raw_call, or selfdestruct function at least once.
3 | pure-function:
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_TIMESTAMP_DEPENDENCE/recommendation_en.html:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.16;
3 |
4 | contract C {
5 | function f(uint a, uint b) pure returns (uint) {
6 | return a * (b + 42) + now;
7 | }
8 | }
9 | block.timestamp variable should not be used for entropy or generating random numbers. Also, we recommend developing contracts so that their logic does not depend on precise value of block.timestamp variable.
3 | as_unitless_number() function allows applying arithmetic operations not allowed for this unit type. Use of this function may lead to errors and vulnerabilities. Therefore, try to avoid the use of this function or use it carefully.
3 | private не делает переменную невидимой. Майнеры имеют доступ ко всем кодам контрактов и данным. Разработчики должны учитывать отсутствие конфиденциальности в Ethereum.
3 | SafeMath для всех арифметических операций. Правильной практикой считается использовать явные проверки там, где они действительно нужны, и не использовать лишних проверок там, где переполнение невозможно.
3 | @payable, должны реализовывать способ снятия ETH, т.е. вызывать функции send (рекомендуется), raw_call или selfdestruct как минимум один раз.
3 |
2 |
5 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_REWRITE_ON_ASSEMBLY_CALL/description.html:
--------------------------------------------------------------------------------
1 | assembly инструкции семейства CALL: возвращаемые значения записываются поверх входных параметров.
3 | В случае, когда вызывается произвольный адрес, возвращаемое значение может отличаться от ожидаемого.
4 | block.timestamp. Майнеры могут изменять block.timestamp в некоторых пределах. При этом, если логика контракта полагается на точное значение этой переменной, то майнер может менять ее для получения выгоды.
3 | return in contract's constructor in order to increase code readability and transparency unless you clearly understand this vulnerability. Generally, it is not safe to use smart contracts that have assembly in the constructor.
3 | pure-функции:
3 |
12 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_TIMESTAMP_DEPENDENCE/description_en.html:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.16;
4 |
5 | contract C {
6 | function f(uint a, uint b) pure returns (uint) {
7 | return a * (b + 42) + now;
8 | }
9 | }
10 |
11 | block.timestamp variable is used in the contract. Miners have the ability to adjust block.timestamp slightly. It can be quite dangerous if smart contract's logic relies on the exact value of block.timestamp variable.
3 | send function is called inside checks instead of using transfer.
3 | addr.transfer(x), which automatically throws an exception if the transfer is unsuccessful.
6 | send function is used:
3 |
9 |
4 | if(!addr.send(42 ether)) {
5 | revert();
6 | }
7 |
8 |
11 |
15 |
--------------------------------------------------------------------------------
/src/main/java/ru/smartdec/smartcheck/Query.java:
--------------------------------------------------------------------------------
1 | package ru.smartdec.smartcheck;
2 |
3 | import org.w3c.dom.Node;
4 |
5 | import java.util.stream.Stream;
6 |
7 | /**
8 | *
9 | */
10 | public interface Query {
11 |
12 | /**
13 | * @param node node
14 | * @return nodes
15 | */
16 | Stream
12 | addr.transfer(42 ether);
13 |
14 | block.timestamp или now. Майнеры могут влиять на block.timestamp для получения выгоды. Таким образом, не следует рассчитывать, что block.timestamp примет (или не примет) какое-то конкретное значение.
3 | view-функции:
3 |
5 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_BALANCE_EQUALITY/description_en.html:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.16;
6 |
7 | contract C {
8 | function f(uint a, uint b) view returns (uint) {
9 | return a * (b + 42) + now;
10 | }
11 | }
12 |
13 | selfdestruct() function or by mining. Also, Ether can be sent to the precomputed contract's address.
6 | send:
3 |
5 |
11 |
6 | if(!addr.send(42 ether)) {
7 | revert();
8 | }
9 |
10 |
13 |
17 |
--------------------------------------------------------------------------------
/src/main/java/ru/smartdec/smartcheck/Rule.java:
--------------------------------------------------------------------------------
1 | package ru.smartdec.smartcheck;
2 |
3 | import java.util.stream.Stream;
4 |
5 | /**
6 | *
7 | */
8 | public interface Rule {
9 |
10 | /**
11 | * @return id
12 | */
13 | String id();
14 |
15 | /**
16 | * @return patterns
17 | */
18 | Stream
14 | addr.transfer(42 ether);
15 |
16 | for или while происходит обращение к storage контракта, .length массива, не находящегося в memory, либо к полю .balance. Таким образом, на каждом шаге цикла тратится большое количество газа на чтение.
3 | .balance, or .length is used several times, holding its value in a local variable is more gas efficient.
3 | If .length of calldata-array is placed into local variable, the optimisation will be less significant.
4 | uint type cannot be negative. Thus, comparing uint variable with zero (greater than or equal) is redundant. Also, it may lead to an underflow issue. Moreover, comparison with zero used in for-loop condition results in an infinite loop.
3 | send без проверки возвращаемого значения:
3 |
5 |
13 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ERC20_APPROVE/links_en.html:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_PRAGMAS_VERSION/example.html:
--------------------------------------------------------------------------------
1 |
6 | contract SolidityUncheckedSend {
7 | function unseatKing(address addr, uint value) {
8 | addr.send(value);
9 | }
10 | }
11 |
12 |
5 |
9 |
6 | pragma solidity ^0.4.17;
7 |
8 |
13 |
17 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_UNCHECKED_CALL/example_en.html:
--------------------------------------------------------------------------------
1 |
14 | pragma solidity 0.4.24;
15 |
16 | send function without checking return value is used:
3 |
5 |
13 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_BALANCE_EQUALITY/description.html:
--------------------------------------------------------------------------------
1 |
6 | contract SolidityUncheckedSend {
7 | function unseatKing(address addr, uint value) {
8 | addr.send(value);
9 | }
10 | }
11 |
12 |
5 |
9 |
6 | pragma solidity ^0.4.17;
7 |
8 |
13 |
17 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_VISIBILITY/example.html:
--------------------------------------------------------------------------------
1 |
14 | pragma solidity 0.4.24;
15 |
16 |
5 |
9 |
6 | function foo();
7 |
8 |
13 |
18 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_DIV_MUL/description_en.html:
--------------------------------------------------------------------------------
1 |
14 | function foo() public;
15 | function foo() private;
16 |
17 | send с проверкой возвращаемого значения вместо вызова transfer.
3 | addr.transfer(x), который автоматически генерирует исключение, если отправка эфира не удалась.
6 |
5 |
9 |
6 | function foo();
7 |
8 |
13 |
18 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_UNITLESS_NUMBER/description_en.html:
--------------------------------------------------------------------------------
1 |
14 | function foo() public;
15 | function foo() internal;
16 |
17 | uint256, int128, or decimal type. This feature is implemented to increase code readability and security. However, as_unitless_number() function is used in the contract. Use of this function can endanger contract security.
3 | as_unitless_number() позволяет произвдить операции, изначально запрещённые для данных единиц измерения. Использование этой функции может привести к ошибкам и уязвимостям. Поэтому мы рекомендуем не использовать данную функцию, а в случае, если это невозможно - использовать ее с предельной аккуратностью.
3 | currentBlockBlockhash всегда возвращает 0:
3 |
5 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_UINT_CANT_BE_NEGATIVE/description.html:
--------------------------------------------------------------------------------
1 |
6 | pragma solidity 0.4.25;
7 |
8 | contract MyContract {
9 |
10 | function currentBlockHash() public view returns(bytes32) {
11 | return blockhash(block.number);
12 | }
13 | }
14 |
15 | uint не могут быть отрицательными. В общем случае, нестрогое сравнение такой переменной с нулем является излишним. А в отдельных случаях ее использование может привести к ошибке переполнения (underflow). Кроме того, использование сравнения с нулем в условии цикла for приводит к бесконечному циклу.
3 | public, которая не вызывается из контракта с помощью внутреннего вызова. Изменение уровня видимости на external у такой функции повышает читаемость кода. Более того, в некоторых случаях внешний вызов функции с уровнем видимости external потребляет меньше газа.
3 | uint256, int128 и decimal. Эта возможность была создана для повышения читаемости кода и безопасности контракта. Однако, в контракте используется функция as_unitless_number(). Использование этой функции может снизить безопасность контракта.
3 | currentBlockBlockhash function always returns 0:
3 |
5 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_REDUNDANT_FALLBACK_REJECT/example_en.html:
--------------------------------------------------------------------------------
1 |
6 | pragma solidity 0.4.25;
7 |
8 | contract MyContract {
9 |
10 | function currentBlockHash() public view returns(bytes32) {
11 | return blockhash(block.number);
12 | }
13 | }
14 |
15 |
3 |
18 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_UNUSED_FUNCTION_SHOULD_BE_EXTERNAL/description_en.html:
--------------------------------------------------------------------------------
1 |
4 | pragma solidity 0.4.24;
5 |
6 | contract Сlock {
7 |
8 | function time() public returns(uint) {
9 | return now;
10 | }
11 |
12 | function() {
13 | revert();
14 | }
15 | }
16 |
17 | public visibility modifier that is not called internally. Changing visibility level to external increases code readability. Moreover, in many cases functions with external visibility modifier spend less gas comparing to functions with public visibility modifier.
3 | call function is used for ETH transfer:
3 |
6 |
19 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_CALL_WITHOUT_DATA/recommendation_en.html:
--------------------------------------------------------------------------------
1 |
7 | pragma solidity 0.4.24;
8 |
9 | contract MyContract {
10 |
11 | function withdraw() {
12 | if (msg.sender.call.value(1)()) {
13 | /*...*/
14 | }
15 | }
16 | }
17 |
18 | transfer or send function call is more secure. Another option is to implement the desired functionality in the separate public function of the target contract. Nevertheless, if use of call function is necessary due to the target contract design, gas limit should be added (.gas()).
3 |
3 |
18 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_TRANSFER_IN_LOOP/description_en.html:
--------------------------------------------------------------------------------
1 |
4 | pragma solidity 0.4.24;
5 |
6 | contract Сlock {
7 |
8 | function time() public returns(uint) {
9 | return now;
10 | }
11 |
12 | function() {
13 | revert();
14 | }
15 | }
16 |
17 | call для передачи ETH:
3 |
6 |
19 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_EXTRA_GAS_IN_LOOPS/recommendation.html:
--------------------------------------------------------------------------------
1 |
7 | pragma solidity 0.4.24;
8 |
9 | contract MyContract {
10 |
11 | function withdraw() public {
12 | if (msg.sender.call.value(1 ether)()) {
13 | /*...*/
14 | }
15 | }
16 | }
17 |
18 | storage контракта, а также поля .balance и .length, используются несколько раз, рекомендуется записывать их значения в локальные переменные.
3 | При этом в случае, когда происходит обращение к длине массива, находящегося в calldata, оптимизация будет менее значимой.
4 | limiter происходит на каждом шаге цикла:
3 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_LOCKED_MONEY/example_en.html:
--------------------------------------------------------------------------------
1 |
4 | pragma solidity 0.4.25;
5 |
6 | contract NewContract {
7 | uint limiter = 100;
8 |
9 | function longLoop() {
10 | for(uint i = 0; i < limiter; i++) {
11 | /* ... */
12 | }
13 | }
14 | }
15 |
16 | transfer, send, or call.value function:
3 |
5 |
15 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ARRAY_LENGTH_MANIPULATION/description_en.html:
--------------------------------------------------------------------------------
1 |
6 | pragma solidity 0.4.25;
7 |
8 | contract BadMarketPlace {
9 | function deposit() payable {
10 | require(msg.value > 0);
11 | }
12 | }
13 |
14 | internal функция возвращает несколько переменных:
3 |
5 |
18 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_CALL_WITHOUT_DATA/recommendation.html:
--------------------------------------------------------------------------------
1 |
6 | pragma solidity 0.4.24;
7 |
8 | contract TestContract {
9 |
10 | function test() internal returns(uint a, address b, bool c) {
11 | a = 1;
12 | b = msg.sender;
13 | c = true;
14 | }
15 | }
16 |
17 | transfer и send. Также, по возможности рекомендуется доработать целевой контракт и добавить в него функцию с желаемой функциональностью. Однако, если вызов функции call необходим (в силу дизайна целевого контракта), то рекомендуется добавлять ограничение на газ (.gas()).
3 | limiter variable is accessed on every for-loop iteration:
4 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_LOCKED_MONEY/example.html:
--------------------------------------------------------------------------------
1 |
5 | pragma solidity 0.4.25;
6 |
7 | contract NewContract {
8 | uint limiter = 100;
9 |
10 | function longLoop() {
11 | for(uint i = 0; i < limiter; i++) {
12 | /* ... */
13 | }
14 | }
15 | }
16 |
17 | transfer, send или call.value:
3 |
5 |
15 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_SHOULD_RETURN_STRUCT/example_en.html:
--------------------------------------------------------------------------------
1 |
6 | pragma solidity 0.4.25;
7 |
8 | contract BadMarketPlace {
9 | function deposit() payable {
10 | require(msg.value > 0);
11 | }
12 | }
13 |
14 | internal function returns several parameters:
3 |
5 |
18 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_FUNCTION_RETURNS_TYPE_AND_NO_RETURN/example.html:
--------------------------------------------------------------------------------
1 |
6 | pragma solidity 0.4.24;
7 |
8 | contract TestContract {
9 |
10 | function test() internal returns(uint a, address b, bool c) {
11 | a = 1;
12 | b = msg.sender;
13 | c = true;
14 | }
15 | }
16 |
17 | return:
3 |
--------------------------------------------------------------------------------
/src/test/resources/rules/SOLIDITY_SAFEMATH.sol:
--------------------------------------------------------------------------------
1 | pragma solidity 0.4.24;
2 |
3 | library SafeMath {
4 | function sub(uint256 a, uint256 b) internal pure returns (uint256) {
5 | assert(b <= a);
6 | return a - b;
7 | }
8 | }
9 |
10 | contract MyToken {
11 | //
4 | pragma solidity 0.4.25;
5 |
6 | contract NewContract {
7 | uint minimumBuy;
8 |
9 | function setMinimumBuy(uint256 newMinimumBuy) returns (bool){
10 | minimumBuy = newMinimumBuy;
11 | }
12 | }
13 |
14 |
5 |
11 |
6 | if (address(this).balance == 42 ether ) {
7 | /* ... */
8 | }
9 |
10 |
15 |
21 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_PRIVATE_MODIFIER_DOES_NOT_HIDE_DATA/description_en.html:
--------------------------------------------------------------------------------
1 |
16 | if (address(this).balance >= 42 ether ) {
17 | /* ... */
18 | }
19 |
20 | private modifier does not make a variable invisible. Miners have access to all contracts’ code and data. Developers must account for the lack of privacy in Ethereum.
3 | uint256 and int256 instead of uint or int.
3 |
5 |
11 |
6 | if (address(this).balance == 42 ether ) {
7 | /* ... */
8 | }
9 |
10 |
15 |
21 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ERC20_TRANSFER_SHOULD_THROW/description_en.html:
--------------------------------------------------------------------------------
1 |
16 | if (address(this).balance >= 42 ether ) {
17 | /* ... */
18 | }
19 |
20 |
5 |
8 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_BALANCE_EQUALITY/description_en.html:
--------------------------------------------------------------------------------
1 | transfer should throw if the _from account balance does not have enough tokens to spendtransferFrom should throw unless the _from account has deliberately authorized the sender of the message via some mechanismselfdestruct() or by mining.
6 |
3 |
12 |
4 | pragma solidity 0.4.24;
5 |
6 | contract C {
7 | byte[] someVariable;
8 | ...
9 | }
10 |
11 |
16 |
25 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_BYTE_ARRAY_INSTEAD_BYTES/example_en.html:
--------------------------------------------------------------------------------
1 |
17 | pragma solidity 0.4.24;
18 |
19 | contract C {
20 | bytes someVariable;
21 | ...
22 | }
23 |
24 |
3 |
12 |
4 | pragma solidity 0.4.24;
5 |
6 | contract C {
7 | byte[] someVariable;
8 | ...
9 | }
10 |
11 |
16 |
25 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_EXACT_TIME/description_en.html:
--------------------------------------------------------------------------------
1 |
17 | pragma solidity 0.4.24;
18 |
19 | contract C {
20 | bytes someVariable;
21 | ...
22 | }
23 |
24 | block.timestamp or now. Miners can affect block.timestamp for their benefits. Thus, one should not rely on the exact value of block.timestamp.
3 | public, in interfaces - external, state variable default visibility level is internal.
3 | In contracts, the fallback function can be external or public. In interfaces, all the functions should be declared as external. Explicitly define function visibility to prevent confusion.
4 | approve:
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ERC20_APPROVE/example_en.html:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.5;
3 | contract StandardToken is ERC20, BasicToken {
4 | ...
5 | function approve(address _spender, uint256 _value) public returns (bool) {
6 | allowed[msg.sender][_spender] = _value;
7 | Approval(msg.sender, _spender, _value);
8 | return true;
9 | }
10 | ...
11 | }
12 | approve is used:
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ERC20_TRANSFER_SHOULD_THROW/description.html:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.5;
3 | contract StandardToken is ERC20, BasicToken {
4 | ...
5 | function approve(address _spender, uint256 _value) public returns (bool) {
6 | allowed[msg.sender][_spender] = _value;
7 | Approval(msg.sender, _spender, _value);
8 | return true;
9 | }
10 | ...
11 | }
12 |
5 |
8 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_PRIVATE_MODIFIER_DONT_HIDE_DATA/description.html:
--------------------------------------------------------------------------------
1 | transfer должна бросать исключение, если адрес _from не имеет достаточно токенов для тратыtransferFrom должна бросать исключение, если адрес _from намеренно не авторизовал отправителя сообщения с помощью какого-либо механизмаpublic, являются недоступными для внешних контрактов и могут быть вызваны только из методов данного контракта. Вопреки распространенному заблуждению, значения этих переменных всё ещё остаются доступными пользователям. Разработчики должны учитывать отсутствие конфиденциальности в Ethereum. (На элементах структур происходит ложное срабатывание паттерна)
3 | return statement is used in contract's constructor. With return the process of deploy will differ from the intuitive one. For instance, deployed bytecode may not include functions implemented in the source.
3 |
8 |
12 |
9 | function () { revert(); }
10 |
11 | return statement:
3 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_REDUNDANT_FALLBACK_REJECT/description.html:
--------------------------------------------------------------------------------
1 |
4 | pragma solidity 0.4.25;
5 |
6 | contract NewContract {
7 | uint minimumBuy;
8 |
9 | function setMinimumBuy(uint256 newMinimumBuy) returns (bool){
10 | minimumBuy = newMinimumBuy;
11 | }
12 | }
13 |
14 |
7 |
11 |
8 | function () { revert(); }
9 |
10 | public, для функций в интерфейсах - external, для переменных - internal. Fallback функция в контрактах может иметь только external или public уровень видимости. Все функции в интерфейсах должны иметь external уровень видимости.
3 | Четко определяйте видимость для предотвращения неоднозначной ситуации.
4 |
5 |
16 |
6 | pragma solidity ^0.5.1;
7 | contract Signature {
8 | function callFoo(address addr, uint value) public returns (bool) {
9 | bytes memory data = abi.encodeWithSignature("foo(uint)", value);
10 | (bool status, ) = addr.call(data);
11 | return status;
12 | }
13 | }
14 |
15 | "foo(uint256)" instead.
18 | public function defaults to a private declaration and thus only accessible to methods within the same contract. Contrary to a popular misconception, values of these variables are still accessible for users. Developers must account for the lack of privacy in Ethereum.
3 | This rule reports all structure's fields in structure definition but it is not the issue (it is false positive).
4 |
5 |
10 |
6 | pragma solidity ^0.4.17; // bad: compiles w 0.4.17 and above
7 | pragma solidity 0.4.24; // good : compiles w 0.4.24 only
8 |
9 |
5 |
10 |
6 | pragma solidity ^0.4.17; // bad: compiles w 0.4.17 and above
7 | pragma solidity 0.4.24; // good : compiles w 0.4.24 only
8 |
9 | password используется для хранения пароля:
3 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_WRONG_SIGNATURE/example.html:
--------------------------------------------------------------------------------
1 |
4 | password: bytes32
5 | set: public(bool)
6 |
7 | @public
8 | def unlock(_password: bytes32):
9 | assert self.password == _password
10 | send(msg.sender, self.balance)
11 |
12 | @payable
13 | @public
14 | def lock(_password: bytes32):
15 | assert self.set == False
16 | self.password = _password
17 | self.set = True
18 |
19 |
5 |
16 |
6 | pragma solidity ^0.5.1;
7 | contract Signature {
8 | function callFoo(address addr, uint value) public returns (bool) {
9 | bytes memory data = abi.encodeWithSignature("foo(uint)", value);
10 | (bool status, ) = addr.call(data);
11 | return status;
12 | }
13 | }
14 |
15 | "foo(uint256)".
18 |
5 |
16 |
6 | pragma solidity 0.4.24;
7 |
8 | contract C {
9 | function f(uint a, uint b) pure returns (address) {
10 | address public multisig = 0xf64B584972FE6055a770477670208d737Fff282f;
11 | return multisig;
12 | }
13 | }
14 |
15 | 0xf64B584972FE6055a770477670208d737Fff282f на уязвимости.
19 | password state variable:
3 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_EXACT_TIME/example.html:
--------------------------------------------------------------------------------
1 |
4 | password: bytes32
5 | set: public(bool)
6 |
7 | @public
8 | def unlock(_password: bytes32):
9 | assert self.password == _password
10 | send(msg.sender, self.balance)
11 |
12 | @payable
13 | @public
14 | def lock(_password: bytes32):
15 | assert self.set == False
16 | self.password = _password
17 | self.set = True
18 |
19 | now и всегда выигрывать:
3 |
5 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_EXACT_TIME/example_en.html:
--------------------------------------------------------------------------------
1 |
6 | pragma solidity 0.4.25;
7 |
8 | contract Game {
9 |
10 | function oddOrEven(bool yourGuess) external payable {
11 | if (yourGuess == now % 2 > 0) {
12 | uint fee = msg.value / 10;
13 | msg.sender.transfer(msg.value * 2 - fee);
14 | }
15 | }
16 |
17 | function () external payable {}
18 | }
19 |
20 | now can be manipulated by the miner so that he/she will always win:
3 |
5 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_LOCKED_MONEY/example.html:
--------------------------------------------------------------------------------
1 |
6 | pragma solidity 0.4.25;
7 |
8 | contract Game {
9 |
10 | function oddOrEven(bool yourGuess) external payable {
11 | if (yourGuess == now % 2 > 0) {
12 | uint fee = msg.value / 10;
13 | msg.sender.transfer(msg.value * 2 - fee);
14 | }
15 | }
16 |
17 | function () external payable {}
18 | }
19 |
20 | @payable функция:
3 |
5 |
18 |
6 | funders: {sender: address, value: wei_value}[int128]
7 | nextFunderIndex: int128
8 |
9 |
10 | @public
11 | @payable
12 | def participate(i: int128):
13 | nfi: int128 = self.nextFunderIndex
14 | self.funders[nfi] = {sender: msg.sender, value: msg.value}
15 | self.nextFunderIndex = nfi + 1
16 |
17 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_BALANCE_EQUALITY/example.html:
--------------------------------------------------------------------------------
1 | keccak256 instead of sha3.
4 | selfdestruct instead of suicide.
7 | revert() instead of throw.
10 | view instead of constant for functions.
13 | days instead of years.
16 |
5 |
13 |
6 | @public
7 | def func_1(user: address):
8 | if (user.balance == as_wei_value(10, "ether")):
9 | # do some stuff
10 | pass
11 |
12 |
17 |
25 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_BALANCE_EQUALITY/example_en.html:
--------------------------------------------------------------------------------
1 |
18 | @public
19 | def func_1(user: address):
20 | if (user.balance >= as_wei_value(10, "ether")):
21 | # do some stuff
22 | pass
23 |
24 |
5 |
13 |
6 | @public
7 | def func_1(user: address):
8 | if (user.balance == as_wei_value(10, "ether")):
9 | # do some stuff
10 | pass
11 |
12 |
17 |
25 |
--------------------------------------------------------------------------------
/src/main/java/ru/smartdec/smartcheck/Rules.java:
--------------------------------------------------------------------------------
1 | package ru.smartdec.smartcheck;
2 |
3 | import java.util.stream.Stream;
4 |
5 | /**
6 | *
7 | */
8 | public interface Rules {
9 |
10 | /**
11 | * @return rules
12 | * @throws Exception exception
13 | */
14 | Stream
18 | @public
19 | def func_1(user: address):
20 | if (user.balance >= as_wei_value(10, "ether")):
21 | # do some stuff
22 | pass
23 |
24 | amount variable is divided by DELIMITER and then multiplied by BONUS. Thus, a rounding error appears (consider amount = 9000):
3 |
5 |
19 |
--------------------------------------------------------------------------------
/src/main/java/ru/smartdec/smartcheck/ParseTree.java:
--------------------------------------------------------------------------------
1 | package ru.smartdec.smartcheck;
2 |
3 | import org.antlr.v4.runtime.tree.RuleNode;
4 |
5 | /**
6 | *
7 | */
8 | public interface ParseTree {
9 |
10 | /**
11 | * @return root
12 | * @throws Exception exception
13 | */
14 | RuleNode root() throws Exception;
15 |
16 | /**
17 | * @return root
18 | */
19 | default RuleNode rootUnchecked() {
20 | try {
21 | return this.root();
22 | } catch (Exception ex) {
23 | throw new RuntimeException(ex);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_DEPRECATED_CONSTRUCTIONS/recommendation.html:
--------------------------------------------------------------------------------
1 |
6 | pragma solidity 0.4.25;
7 |
8 | contract MyContract {
9 |
10 | uint constant BONUS = 500;
11 | uint constant DELIMITER = 10000;
12 |
13 | function calculateBonus(uint amount) returns (uint) {
14 | return amount/DELIMITER*BONUS;
15 | }
16 | }
17 |
18 |
2 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_ERC20_APPROVE/example.html:
--------------------------------------------------------------------------------
1 | keccak256 вместо sha3.
4 | selfdestruct вместо suicide.
7 | revert() вместо throw.
10 | view вместо constant для функций.
13 | days вместо years.
16 | approve
3 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ADDRESS_HARDCODED/example_en.html:
--------------------------------------------------------------------------------
1 |
4 | Approval: event({_owner: indexed(address), _spender: indexed(address), _value: uint256(wei)})
5 |
6 |
7 | allowances: (uint256(wei)[address])[address]
8 |
9 |
10 | @public
11 | def approve(_spender : address, _value : uint256(wei)) -> bool:
12 | _sender: address = msg.sender
13 | self.allowances[_sender][_spender] = _value
14 | # Fire approval event
15 | log.Approval(_sender, _spender, _value)
16 | return True
17 |
18 |
4 |
15 |
5 | pragma solidity 0.4.24;
6 |
7 | contract C {
8 | function f(uint a, uint b) pure returns (address) {
9 | address public multisig = 0xf64B584972FE6055a770477670208d737Fff282f;
10 | return multisig;
11 | }
12 | }
13 |
14 | 0xf64B584972FE6055a770477670208d737Fff282f for vulnerabilities.
17 | amount делится на DELIMITER нацело и только потом умножается на BONUS. Таким образом, возникает погрешность (например, при amount = 9000):
3 |
5 |
19 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_ERC20_APPROVE/example_en.html:
--------------------------------------------------------------------------------
1 |
6 | pragma solidity 0.4.25;
7 |
8 | contract MyContract {
9 |
10 | uint constant BONUS = 500;
11 | uint constant DELIMITER = 10000;
12 |
13 | function calculateBonus(uint amount) returns (uint) {
14 | return amount/DELIMITER*BONUS;
15 | }
16 | }
17 |
18 | approve function is used
3 |
--------------------------------------------------------------------------------
/tests_not_used_now/SOLIDITY_REFACTOR_CONFUSING_PRECONDITION.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.5;
2 | contract Voting {
3 | function finalize() external {
4 | if (!isFunding) throw;
5 | if (msg.sender != ethFundDeposit) throw; // this locks finalize to the ultimate ETH owner
6 | if ((block.number <= fundingEndBlock ||//лучше разделить эти if
7 | totalSupply < tokenCreationMin) &&
8 | totalSupply < tokenCreationCap) throw;
9 | // move to operational
10 | isFunding = false;
11 | if(!ethFundDeposit.send(this.balance)) throw; // send the eth to Brave International
12 | }
13 | }
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_LOCKED_MONEY/example_en.html:
--------------------------------------------------------------------------------
1 |
4 | Approval: event({_owner: indexed(address), _spender: indexed(address), _value: uint256(wei)})
5 |
6 |
7 | allowances: (uint256(wei)[address])[address]
8 |
9 |
10 | @public
11 | def approve(_spender : address, _value : uint256(wei)) -> bool:
12 | _sender: address = msg.sender
13 | self.allowances[_sender][_spender] = _value
14 | # Fire approval event
15 | log.Approval(_sender, _spender, _value)
16 | return True
17 |
18 | @payable decorator:
3 |
5 |
18 |
6 | funders: {sender: address, value: wei_value}[int128]
7 | nextFunderIndex: int128
8 |
9 |
10 | @public
11 | @payable
12 | def participate(i: int128):
13 | nfi: int128 = self.nextFunderIndex
14 | self.funders[nfi] = {sender: msg.sender, value: msg.value}
15 | self.nextFunderIndex = nfi + 1
16 |
17 | if используется revert():
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_UNITLESS_NUMBER/example.html:
--------------------------------------------------------------------------------
1 |
3 | contract Holder {
4 | uint public holdUntil;
5 | address public holder;
6 |
7 | function Holder(uint period) public payable {
8 | holdUntil = now + period;
9 | holder = msg.sender;
10 | }
11 |
12 | function withdraw (uint a, uint b) external {
13 | if (now < holdUntil){
14 | revert();
15 | }
16 | holder.transfer(this.balance);
17 | }
18 | }
19 |
20 | as_unitless_number(), что приводит к ошибке:
3 |
5 |
20 |
--------------------------------------------------------------------------------
/tests_not_used_now/SOLIDITY_CROSS_FUNCTION_RACE_CONDITION.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.11;
2 |
3 | contract PullPayment {
4 | mapping (address => uint) private userBalances;
5 |
6 | function transfer(address to, uint amount) {
7 | if (userBalances[msg.sender] >= amount) {
8 | userBalances[to] += amount;
9 | userBalances[msg.sender] -= amount;
10 | }
11 | }
12 |
13 | function withdrawBalance() public {
14 | uint amountToWithdraw = userBalances[msg.sender];
15 | if (!(msg.sender.call.value(amountToWithdraw)())) { throw; } // At this point, the caller's code is executed, and can call transfer()
16 | userBalances[msg.sender] = 0;
17 | }
18 | }
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_UNITLESS_NUMBER/example_en.html:
--------------------------------------------------------------------------------
1 |
6 | units: {day: "days"}
7 |
8 | price: public(uint256(wei/day))
9 | start: public(timestamp[address])
10 |
11 | @public
12 | @payable
13 | def payment():
14 | total_price: uint256(wei)
15 | total_price = as_wei_value(as_unitless_number(self.price) *
16 | (as_unitless_number(block.timestamp) - as_unitless_number(self.start[msg.sender])), "wei")
17 | assert(msg.value >= total_price)
18 |
19 | as_unitless_number() function leads to the mistake:
3 |
5 |
20 |
--------------------------------------------------------------------------------
/src/test/resources/rules/SOLIDITY_VAR.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.11;
2 |
3 | contract SolidityVarZero {
4 | function foo1() {
5 | //
6 | units: {day: "days"}
7 |
8 | price: public(uint256(wei/day))
9 | start: public(timestamp[address])
10 |
11 | @public
12 | @payable
13 | def payment():
14 | total_price: uint256(wei)
15 | total_price = as_wei_value(as_unitless_number(self.price) *
16 | (as_unitless_number(block.timestamp) - as_unitless_number(self.start[msg.sender])), "wei")
17 | assert(msg.value >= total_price)
18 |
19 | view.
The following statements are considered modifying the state:
3 |selfdestruct;view or pure;In the following example, in the body of if conditional operator revert() function is used:
3 |
4 | contract Holder {
5 | uint public holdUntil;
6 | address public holder;
7 |
8 | function Holder(uint period) public payable {
9 | holdUntil = now + period;
10 | holder = msg.sender;
11 | }
12 |
13 | function withdraw (uint a, uint b) external {
14 | if (now < holdUntil){
15 | revert();
16 | }
17 | holder.transfer(this.balance);
18 | }
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/rule_descriptions/VYPER_TIMESTAMP_DEPENDENCE/example.html:
--------------------------------------------------------------------------------
1 |
2 | В данном примере логика контракта опирается на точное значение переменной block.timestamp:
3 |
5 |
6 | investor_money: puiblic(uint256[address])
7 | lucky_time: public(timestamp)
8 |
9 | @public
10 | def init(_lucky_time: timestamp):
11 | self.lucky_time = _lucky_time
12 |
13 | @payable
14 | @public
15 | def add_investor():
16 | if block.timestamp == self.lucky_time:
17 | self.investor_money[msg.sender] = 2 * msg.value
18 | else:
19 | self.investor_money[msg.sender] = msg.value / 2
20 |
21 |
22 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_UINT_CANT_BE_NEGATIVE/example.html:
--------------------------------------------------------------------------------
1 | 2 | Далее приведен пример бесконечного цикла: 3 |
4 |
5 |
6 | pragma solidity 0.4.24;
7 |
8 | contract GreaterOrEqualToZero {
9 |
10 | function infiniteLoop(uint border) returns(uint ans) {
11 |
12 | for (uint i = border; i >= 0; i--) {
13 | ans += i;
14 | }
15 | }
16 | }
17 |
18 |
19 |
20 | В данном случае, условие i >= 0 будет всегда выполнено. Следующим после 0 значением переменной i будет 2**256-1. Таким образом, цикл будет бесконечным.
21 |
2 | This contract includes several functions callable only from one address: 3 |
4 | 5 |
6 |
7 | pragma solidity 0.4.25;
8 |
9 | contract Crowdsale {
10 |
11 | address public owner;
12 |
13 | uint rate;
14 | uint cap;
15 |
16 | constructor() {
17 | owner = msg.sender;
18 | }
19 |
20 | function setRate(_rate) public onlyOwner {
21 | rate = _rate;
22 | }
23 |
24 | function setCap(_cap) public {
25 | require (msg.sender == owner);
26 | cap = _cap;
27 | }
28 | }
29 |
30 |
31 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_UINT_CANT_BE_NEGATIVE/example_en.html:
--------------------------------------------------------------------------------
1 | 2 | The following example includes an infinite loop: 3 |
4 |
5 |
6 | pragma solidity 0.4.24;
7 |
8 | contract GreaterOrEqualToZero {
9 |
10 | function infiniteLoop(uint border) returns(uint ans) {
11 |
12 | for (uint i = border; i >= 0; i--) {
13 | ans += i;
14 | }
15 | }
16 | }
17 |
18 |
19 |
20 | In this case, i >= 0 condition will always evaluate to true. The next value of i variable after 0 will be 2**256-1. Thus, the loop will be infinite.
21 |
2 | In the following example, the contract's logic depends on the exact value of block.timestamp variable:
3 |
5 |
6 | investor_money: puiblic(uint256[address])
7 | lucky_time: public(timestamp)
8 |
9 | @public
10 | def init(_lucky_time: timestamp):
11 | self.lucky_time = _lucky_time
12 |
13 | @payable
14 | @public
15 | def add_investor():
16 | if block.timestamp == self.lucky_time:
17 | self.investor_money[msg.sender] = 2 * msg.value
18 | else:
19 | self.investor_money[msg.sender] = msg.value / 2
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/test/resources/rules/SOLIDITY_REDUNDANT_FALLBACK_REJECT.sol:
--------------------------------------------------------------------------------
1 | pragma solidity 0.4.24;
2 |
3 | contract C1 {
4 | // 2 | В следующем примере происходит отправка ETH в цикле: 3 |
4 |
5 |
6 | pragma solidity 0.4.25;
7 |
8 | contract MyContract {
9 |
10 | address[] public users;
11 | uint internal id;
12 |
13 | function transferBatch(address[] users) public {
14 | uint amount = address(this).balance / users.length;
15 | for (uint i = 0; i < users.length; i++) {
16 | users[i].transfer(amount);
17 | }
18 | }
19 |
20 | function () public payable {
21 | users[id] = msg.sender;
22 | id++;
23 | }
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_OVERPOWERED_ROLE/example.html:
--------------------------------------------------------------------------------
1 | 2 | В этом контракте есть несколько функций, которые могут быть вызваны только с одного адреса: 3 |
4 | 5 |
6 |
7 | pragma solidity 0.4.25;
8 |
9 | contract Crowdsale {
10 |
11 | address public owner;
12 |
13 | uint rate;
14 | uint cap;
15 |
16 | constructor() {
17 | owner = msg.sender;
18 | }
19 |
20 | function setRate(_rate) public onlyOwner {
21 | rate = _rate;
22 | }
23 |
24 | function setCap(_cap) public {
25 | require (msg.sender == owner);
26 | cap = _cap;
27 | }
28 | }
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/test/resources/rules/SOLIDITY_EXACT_TIME.sol:
--------------------------------------------------------------------------------
1 | pragma solidity 0.4.24;
2 |
3 | contract TimestampDependence {
4 |
5 | function doSomething() {
6 | uint startTime = now;
7 | // 2 | Данный контракт не будет компилироваться компилятором версии 0.5.0: 3 |
4 |
5 |
6 | contract Token {
7 | uint totalSupply;
8 |
9 | function Token() {
10 | totalSupply = +1e18;
11 | }
12 |
13 | function () payable {}
14 | }
15 |
16 |
17 |
18 | 19 | Один из вариантов обновления контракта: 20 |
21 |
22 |
23 | contract Token {
24 | uint public totalSupply;
25 |
26 | constructor() public {
27 | totalSupply = 1e18;
28 | }
29 |
30 | function () external payable {}
31 | }
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/test/resources/rules/VYPER_UNITLESS_NUMBER.vy:
--------------------------------------------------------------------------------
1 | numberas: public(uint256)
2 |
3 | @public
4 | def __init__(deadline: timestamp, goal: wei_value, timelimit: timedelta) -> uint256:
5 | # 2 | In the following example, ETH is transferred in a loop: 3 |
4 | 5 |
6 |
7 | pragma solidity 0.4.25;
8 |
9 | contract MyContract {
10 |
11 | address[] public users;
12 | uint internal id;
13 |
14 | function transferBatch(address[] users) public {
15 | uint amount = address(this).balance / users.length;
16 | for (uint i = 0; i < users.length; i++) {
17 | users[i].transfer(amount);
18 | }
19 | }
20 |
21 | function () public payable {
22 | users[id] = msg.sender;
23 | id++;
24 | }
25 | }
26 |
27 |
28 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_UPGRADE_TO_050/example_en.html:
--------------------------------------------------------------------------------
1 | 2 | The following contract will not compile with compiler version 0.5.0: 3 |
4 |
5 |
6 | contract Token {
7 | uint totalSupply;
8 |
9 | function Token() {
10 | totalSupply = +1e18;
11 | }
12 |
13 | function () payable {}
14 | }
15 |
16 |
17 |
18 | 19 | One of the possible ways of contract update: 20 |
21 |
22 |
23 | contract Token {
24 | uint public totalSupply;
25 |
26 | constructor() public {
27 | totalSupply = 1e18;
28 | }
29 |
30 | function () external payable {}
31 | }
32 |
33 |
34 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ERC20_INDEXED/example_en.html:
--------------------------------------------------------------------------------
1 | In the following contract Transfer event's arguments are unindexed:
3 | pragma solidity ^0.5.0;
4 |
5 | contract StandardToken is ERC20 {
6 | ...
7 |
8 | event Transfer(address _from, address _to, uint256 _value);
9 |
10 | function transfer(address to, uint256 value) public returns (bool) {
11 | require(value <= balances[msg.sender]);
12 | balances[msg.sender] -= value; // we've checked for underflow
13 | balances[to] += value; // no overflow because of limited supply
14 | emit Transfer(msg.sender, to, value);
15 | return true;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ARRAY_LENGTH_MANIPULATION/recommendation.html:
--------------------------------------------------------------------------------
1 | 2 | По возможности не работайте с длиной динамического массива напрямую. 3 |
4 |uint[] storage arrayName = new uint[](7) для создания динамического массива нужной длины.
7 | delete arrayName для очистки динамического массива.
9 | .push() (вместо .length++) для записи в конец массива.
11 | .pop() (вместо .length--) для удаления последнего элемента массива.
13 | В следующем контракте используются неиндексированные параметры события Transfer:
3 | pragma solidity ^0.5.0;
4 |
5 | contract StandardToken is ERC20 {
6 | ...
7 |
8 | event Transfer(address _from, address _to, uint256 _value);
9 |
10 | function transfer(address to, uint256 value) public returns (bool) {
11 | require(value <= balances[msg.sender]);
12 | balances[msg.sender] -= value; // we've checked for underflow
13 | balances[to] += value; // no overflow because of limited supply
14 | emit Transfer(msg.sender, to, value);
15 | return true;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ARRAY_LENGTH_MANIPULATION/recommendation_en.html:
--------------------------------------------------------------------------------
1 | 2 | If possible, avoid changing the length of the dynamic array directly. 3 |
4 |uint[] storage arrayName = new uint[](7) to create a dynamic array of the desired length.
7 | delete arrayName to clear a dynamic array.
9 | .push() (instead of .length++) to write to the end of the dynamic array.
11 | .pop() (instead of .length--) to delete the last element of the dynamic array.
13 |
2 | Solidity поддерживает неявные типы: тип i в var i = 42; — это наименьший целочисленный тип, достаточный для хранения значения в правой части выражения (uint8). Рассмотрим общий шаблон для цикла:
3 |
5 |
6 | for (var i = 0; i < array.length; i++) { /* ... */ }
7 |
8 |
9 |
10 | Тип i приводится к uint8. Если array.length больше 255, произойдет переполнение. Явно определяйте тип при объявлении целочисленных переменных:
11 |
13 |
14 | for (uint256 i = 0; i < array.length; i++) { /* ... */ }
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/test/resources/rules/SOLIDITY_USING_INLINE_ASSEMBLY.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.18;
2 | library GetCode {
3 | function at( address _addr) returns (bytes o_code) {
4 | //
2 | Solidity supports type inference: the type of i in var i = 42; is the smallest integer type sufficient to store the right-hand side value (uint8). Consider a common for-loop pattern:
3 |
5 |
6 | for (var i = 0; i < array.length; i++) { /* ... */ }
7 |
8 |
9 |
10 | The type of i is inferred to uint8. If array.length is bigger than 255, an
11 | overflow will occur. Explicitly define the type when declaring integer variables:
12 |
14 |
15 | for (uint256 i = 0; i < array.length; i++) { /* ... */ }
16 |
17 |
18 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_SHOULD_NOT_BE_VIEW/recommendation.html:
--------------------------------------------------------------------------------
1 | Не обозначайте функции, которые изменяют состояние, как view.
Изменением состояния считается следующее:
3 |event);selfdestruct;view или pure;assembler, содержащих код определенных операций.
2 | Solidity поддерживает неявные типы: тип i в var i = 42; — это наименьший целочисленный тип, достаточный для хранения значения в правой части выражения (uint8). Рассмотрим общий шаблон для цикла:
3 |
5 |
6 | for (var i = 0; i < array.length; i++) { /* ... */ }
7 |
8 |
9 |
10 | Тип i приводится к uint8. Если array.length больше 255, произойдет переполнение. Явно определяйте тип при объявлении целочисленных переменных:
11 |
13 |
14 | for (uint256 i = 0; i < array.length; i++) { /* ... */ }
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/java/ru/smartdec/smartcheck/app/ReportDefault.java:
--------------------------------------------------------------------------------
1 | package ru.smartdec.smartcheck.app;
2 |
3 | /**
4 | *
5 | */
6 | public final class ReportDefault implements Report {
7 |
8 | /**
9 | *
10 | */
11 | private final DirectoryAnalysis analysis;
12 | /**
13 | *
14 | */
15 | private final Media media;
16 |
17 | /**
18 | * @param da directory analysis
19 | * @param md media
20 | */
21 | public ReportDefault(final DirectoryAnalysis da, final Media md) {
22 | this.analysis = da;
23 | this.media = md;
24 | }
25 |
26 | @Override
27 | public void print() throws Exception {
28 | this.analysis.stream().forEach(this.media::accept);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_VAR_IN_LOOP_FOR/description_en.html:
--------------------------------------------------------------------------------
1 |
2 | Solidity supports type inference: the type of i in var i = 42; is the smallest integer type sufficient to store the right-hand side value (uint8). Consider a common for-loop pattern:
3 |
5 |
6 | for (var i = 0; i < array.length; i++) { /* ... */ }
7 |
8 |
9 |
10 | The type of i is inferred to uint8. If array.length is bigger than 255, an
11 | overflow will occur. Explicitly define the type when declaring integer variables:
12 |
14 |
15 | for (uint256 i = 0; i < array.length; i++) { /* ... */ }
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/main/java/ru/smartdec/smartcheck/app/DirectoryAnalysis.java:
--------------------------------------------------------------------------------
1 | package ru.smartdec.smartcheck.app;
2 |
3 | import ru.smartdec.smartcheck.TreeAnalysis;
4 |
5 | import java.nio.file.Path;
6 | import java.util.stream.Stream;
7 |
8 | /**
9 | *
10 | */
11 | public interface DirectoryAnalysis {
12 |
13 | /**
14 | * @return info
15 | * @throws Exception exception
16 | */
17 | StreamВ следующем примере приведена функция transferFrom, которая не возвращает true:
3 |
4 | pragma Solidity 0.4.24;
5 |
6 | contract StandardToken is ERC20, BasicToken {
7 |
8 | function transferFrom(address _from, address _to, uint _value) returns (bool) {
9 | uint _allowance = allowed[_from][msg.sender];
10 | require(_allowance >= _value);
11 | balances[_to] = balances[_to].add(_value);
12 | balances[_from] = balances[_from].sub(_value);
13 | allowed[_from][msg.sender] = _allowance.sub(_value);
14 | emit Transfer(_from, _to, _value);
15 | }
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/rule_descriptions/SOLIDITY_ERC20_FUNCTIONS_ALWAYS_RETURN_FALSE/example_en.html:
--------------------------------------------------------------------------------
1 | The following example shows the function transferFrom, which does not return false:
3 |
4 | pragma Solidity 0.4.24;
5 |
6 | contract StandardToken is ERC20, BasicToken {
7 |
8 | function transferFrom(address _from, address _to, uint _value) returns (bool) {
9 | uint _allowance = allowed[_from][msg.sender];
10 | require(_allowance >= _value);
11 | balances[_to] = balances[_to].add(_value);
12 | balances[_from] = balances[_from].sub(_value);
13 | allowed[_from][msg.sender] = _allowance.sub(_value);
14 | emit Transfer(_from, _to, _value);
15 | }
16 | }
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/main/java/ru/smartdec/smartcheck/SearchableTreeDefault.java:
--------------------------------------------------------------------------------
1 | package ru.smartdec.smartcheck;
2 |
3 | import org.antlr.v4.runtime.tree.Tree;
4 |
5 | import java.util.stream.Stream;
6 |
7 | /**
8 | *
9 | */
10 | public final class SearchableTreeDefault implements SearchableTree {
11 |
12 | /**
13 | *
14 | */
15 | private final DocumentTree tree;
16 |
17 | /**
18 | * @param dt tree
19 | */
20 | public SearchableTreeDefault(final DocumentTree dt) {
21 | this.tree = dt;
22 | }
23 |
24 | @Override
25 | public Stream
2 | Ethereum - среда с ограниченными ресурсами. Цены на расчетный шаг на порядок выше, чем у централизованных поставщиков. Более того, майнеры Ethereum налагают ограничение на общее количество газа, потребляемого в блоке. Если значение array.length достаточно велико, функция превышает предел блока газа, и транзакции, вызывающие его, никогда не будут подтверждены:
3 |
5 | for (uint256 i = 0; i < array.length ; i++) {
6 | cosltyFunc();
7 | }
8 |
9 |
10 | Это становится проблемой безопасности, если внешний субъект влияет на array.length. Например, если в массиве перечислены все зарегистрированные адреса, злоумышленник может зарегистрировать много адресов, вызывая проблему, описанную выше.
11 |
The following example shows the transfer function, which does not throw as recommended by ERC-20 Standard:
3 | pragma Solidity 0.4.24;
4 |
5 | contract SomeToken {
6 | mapping(address => uint256) balances;
7 | event Transfer(address indexed _from, address indexed _to, uint256 _value);
8 |
9 | function transfer(address _to, uint _value) public returns (bool) {
10 | if (_value > balances[msg.sender] || _value > balances[_to] + _value) {
11 | return false;
12 | }
13 | balances[msg.sender] = balances[msg.sender] - _value;
14 | balances[_to] = balances[_to] + _value;
15 | emit Transfer(msg.sender, _to, _value);
16 | return true;
17 | }
18 | }
19 |
20 |
21 |
--------------------------------------------------------------------------------