_Follow along with this video:_ --- ### Introducing Aderyn: A Rust Based Static Analysis Tool The second powerful tool we'll be using in this course is a Rust-based analyzer, [**Aderyn**](https://github.com/Cyfrin/aderyn). This tool was created by the smart contract developer legend [**Alex Roan**](https://github.com/alexroan). ### Installation of Aderyn Before we can use `Aderyn`, we'll need to first install `Rust`. Like `Slither`, we won't go over the specifics of installation, but you can find a guide with installation options available to you [**here**](https://www.rust-lang.org/tools/install). > Remember: If you have issues with installation, AI is great at helping with this, you can also leverage the communities on Stack Overflow! Once `Rust` has been installed, you can run the command `cargo install Aderyn`. This will install our tool. ::image{src='/security-section-4/5-tooling-aderyn/tooling-aderyn1.png' style='width: 75%; height: auto;'} > **Note:** If you've already installed Aderyn, this command will also update you to the current version. Your terminal will advise if the tool is already installed. ### Running Aderyn To run Aderyn, the command is `Aderyn [OPTIONS] <root>`. Since we're already in the root directory of our project, we can just run: ```bash aderyn . ``` Running this command will compile our contracts, our terminal will display the usual compilation warnings - at the bottom of the output however, we can see _`Detectors run, printing report. Report printed to ./report.md`_ We should see this fine in our IDE explorer. If we open it up... <details closed> <summary>Puppy Raffle Aderyn Report</summary> # Aderyn Analysis Report This report was generated by [Aderyn](https://github.com/Cyfrin/aderyn), a static analysis tool built by [Cyfrin](https://cyfrin.io), a blockchain security company. This report is not a substitute for manual audit or security review. It should not be relied upon for any purpose other than to assist in the identification of potential security vulnerabilities. # Table of Contents - [Aderyn Analysis Report](#aderyn-analysis-report) - [Table of Contents](#table-of-contents) - [Summary](#summary) - [Files Summary](#files-summary) - [Files Details](#files-details) - [Issue Summary](#issue-summary) - [Medium Issues](#medium-issues) - [M-1: Centralization Risk for trusted owners](#m-1-centralization-risk-for-trusted-owners) - [Low Issues](#low-issues) - [L-1: `abi.encodePacked()` should not be used with dynamic types when passing the result to a hash function such as `keccak256()`](#l-1-abiencodepacked-should-not-be-used-with-dynamic-types-when-passing-the-result-to-a-hash-function-such-as-keccak256) - [L-2: Solidity pragma should be specific, not wide](#l-2-solidity-pragma-should-be-specific-not-wide) - [L-3: Conditional storage checks are not consistent](#l-3-conditional-storage-checks-are-not-consistent) - [NC Issues](#nc-issues) - [NC-1: Missing checks for `address(0)` when assigning values to address state variables](#nc-1-missing-checks-for-address0-when-assigning-values-to-address-state-variables) - [NC-2: Functions not used internally could be marked external](#nc-2-functions-not-used-internally-could-be-marked-external) - [NC-3: Constants should be defined and used instead of literals](#nc-3-constants-should-be-defined-and-used-instead-of-literals) - [NC-4: Event is missing `indexed` fields](#nc-4-event-is-missing-indexed-fields) - [Wrap Up](#wrap-up) # Summary ## Files Summary | Key | Value | | ----------- | ----- | | .sol Files | 1 | | Total nSLOC | 143 | ## Files Details | Filepath | nSLOC | | ------------------- | ------- | | src/PuppyRaffle.sol | 143 | | **Total** | **143** | ## Issue Summary | Category | No. of Issues | | -------- | ------------- | | Critical | 0 | | High | 0 | | Medium | 1 | | Low | 3 | | NC | 4 | # Medium Issues ## M-1: Centralization Risk for trusted owners Contracts have owners with privileged rights to perform admin tasks and need to be trusted to not perform malicious updates or drain funds. - Found in src/PuppyRaffle.sol [Line: 18](src/PuppyRaffle.sol#L18) ```solidity contract PuppyRaffle is ERC721, Ownable { ``` - Found in src/PuppyRaffle.sol [Line: 167](src/PuppyRaffle.sol#L167) ```solidity function changeFeeAddress(address newFeeAddress) external onlyOwner { ``` # Low Issues ## L-1: `abi.encodePacked()` should not be used with dynamic types when passing the result to a hash function such as `keccak256()` Use `abi.encode()` instead which will pad items to 32 bytes, which will [prevent hash collisions](https://docs.soliditylang.org/en/v0.8.13/abi-spec.html#non-standard-packed-mode) (e.g. `abi.encodePacked(0x123,0x456)` => `0x123456` => `abi.encodePacked(0x1,0x23456)`, but `abi.encode(0x123,0x456)` => `0x0...1230...456`). Unless there is a compelling reason, `abi.encode` should be preferred. If there is only one argument to `abi.encodePacked()` it can often be cast to `bytes()` or `bytes32()` [instead](https://ethereum.stackexchange.com/questions/30912/how-to-compare-strings-in-solidity#answer-82739). If all arguments are strings and or bytes, `bytes.concat()` should be used instead. - Found in src/PuppyRaffle.sol [Line: 197](src/PuppyRaffle.sol#L197) ```solidity abi.encodePacked( ``` - Found in src/PuppyRaffle.sol [Line: 201](src/PuppyRaffle.sol#L201) ```solidity abi.encodePacked( ``` ## L-2: Solidity pragma should be specific, not wide Consider using a specific version of Solidity in your contracts instead of a wide version. For example, instead of `pragma solidity ^0.8.0;`, use `pragma solidity 0.8.0;` - Found in src/PuppyRaffle.sol [Line: 2](src/PuppyRaffle.sol#L2) ```solidity pragma solidity ^0.7.6; ``` ## L-3: Conditional storage checks are not consistent When writing `require` or `if` conditionals that check storage values, it is important to be consistent to prevent off-by-one errors. There are instances found where the same storage variable is checked multiple times, but the conditionals are not consistent. - Found in src/PuppyRaffle.sol [Line: 140](src/PuppyRaffle.sol#L140) ```solidity if (rarity <= COMMON_RARITY) { ``` - Found in src/PuppyRaffle.sol [Line: 142](src/PuppyRaffle.sol#L142) ```solidity } else if (rarity <= COMMON_RARITY + RARE_RARITY) { ``` # NC Issues ## NC-1: Missing checks for `address(0)` when assigning values to address state variables Assigning values to address state variables without checking for `address(0)`. - Found in src/PuppyRaffle.sol [Line: 62](src/PuppyRaffle.sol#L62) ```solidity feeAddress = _feeAddress; ``` - Found in src/PuppyRaffle.sol [Line: 150](src/PuppyRaffle.sol#L150) ```solidity previousWinner = winner; ``` - Found in src/PuppyRaffle.sol [Line: 168](src/PuppyRaffle.sol#L168) ```solidity feeAddress = newFeeAddress; ``` ## NC-2: Functions not used internally could be marked external - Found in src/PuppyRaffle.sol [Line: 79](src/PuppyRaffle.sol#L79) ```solidity function enterRaffle(address[] memory newPlayers) public payable { ``` - Found in src/PuppyRaffle.sol [Line: 96](src/PuppyRaffle.sol#L96) ```solidity function refund(uint256 playerIndex) public { ``` - Found in src/PuppyRaffle.sol [Line: 189](src/PuppyRaffle.sol#L189) ```solidity function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { ``` ## NC-3: Constants should be defined and used instead of literals - Found in src/PuppyRaffle.sol [Line: 86](src/PuppyRaffle.sol#L86) ```solidity for (uint256 i = 0; i < players.length - 1; i++) { ``` - Found in src/PuppyRaffle.sol [Line: 87](src/PuppyRaffle.sol#L87) ```solidity for (uint256 j = i + 1; j < players.length; j++) { ``` - Found in src/PuppyRaffle.sol [Line: 127](src/PuppyRaffle.sol#L127) ```solidity require(players.length >= 4, "PuppyRaffle: Need at least 4 players"); ``` - Found in src/PuppyRaffle.sol [Line: 132](src/PuppyRaffle.sol#L132) ```solidity uint256 prizePool = (totalAmountCollected * 80) / 100; ``` - Found in src/PuppyRaffle.sol [Line: 133](src/PuppyRaffle.sol#L133) ```solidity uint256 fee = (totalAmountCollected * 20) / 100; ``` - Found in src/PuppyRaffle.sol [Line: 139](src/PuppyRaffle.sol#L139) ```solidity uint256 rarity = uint256(keccak256(abi.encodePacked(msg.sender, block.difficulty))) % 100; ``` ## NC-4: Event is missing `indexed` fields Index event fields make the field more quickly accessible to off-chain tools that parse events. However, note that each index field costs extra gas during emission, so it's not necessarily best to index the maximum allowed per event (three fields). Each event should use three indexed fields if there are three or more fields, and gas usage is not particularly of concern for the events in question. If there are fewer than three fields, all of the fields should be indexed. - Found in src/PuppyRaffle.sol [Line: 53](src/PuppyRaffle.sol#L53) ```solidity event RaffleEnter(address[] newPlayers); ``` - Found in src/PuppyRaffle.sol [Line: 54](src/PuppyRaffle.sol#L54) ```solidity event RaffleRefunded(address player); ``` - Found in src/PuppyRaffle.sol [Line: 55](src/PuppyRaffle.sol#L55) ```solidity event FeeAddressChanged(address newFeeAddress); ``` </details> _**WOW!**_ We have a report of vulnerabilities already gorgeously formatted and ready to be added to our audit report. ### Wrap Up Fast, and efficient, [**Aderyn**](https://github.com/Cyfrin/aderyn) offers a swift vulnerability report of your smart contracts which is almost ready to be presented. Aesthetically neat and structurally organized, the tool is a quick starter for anyone performing security reviews. We'll be leveraging the power of Aderyn throughout the course!. Let's look at one more tool briefly in the next lesson.
Introducing Aderyn: a static analysis tool for smart contracts, built with Rust by Alex Roan.
Previous lesson
Previous
Next lesson
Next
Give us feedback
Solidity Developer
Smart Contract SecurityDuration: 25min
Duration: 1h 18min
Duration: 35min
Duration: 2h 28min
Duration: 5h 03min
Duration: 5h 22min
Duration: 4h 33min
Duration: 2h 01min
Duration: 1h 40min
Testimonials
Read what our students have to say about this course.
Chainlink
Chainlink
Gustavo Gonzalez
Solutions Engineer at OpenZeppelin
Francesco Andreoli
Lead Devrel at Metamask
Albert Hu
DeForm Founding Engineer
Radek
Senior Developer Advocate at Ceramic
Boidushya
WalletConnect
Idris
Developer Relations Engineer at Axelar