-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
801 additions
and
108 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,53 @@ | ||
## Foundry | ||
# NFT Auction Smart Contract | ||
|
||
**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** | ||
A decentralized NFT auction platform built on Ethereum that allows users to create auctions for their NFTs and accept bids from other users. | ||
|
||
Foundry consists of: | ||
## Features | ||
|
||
- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). | ||
- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. | ||
- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. | ||
- **Chisel**: Fast, utilitarian, and verbose solidity REPL. | ||
- NFT owners can create auctions with custom reserve prices and durations | ||
- Bidders can place bids on active auctions | ||
- Automatic refund of outbid amounts | ||
- Sellers can end auctions early if reserve price is met | ||
- Built-in security with reentrancy protection | ||
- Fully tested with Foundry | ||
|
||
## Documentation | ||
## Contract Details | ||
|
||
https://book.getfoundry.sh/ | ||
The main contract `AuctionContract.sol` implements the following key functionality: | ||
|
||
## Usage | ||
- `depositNft()`: Create a new auction by depositing an NFT | ||
- `bid()`: Place a bid on an active auction | ||
- `finishAuction()`: Complete an auction after time expires | ||
- `sellerEndAuction()`: Allow seller to end auction early if reserve met | ||
- `withdraw()`: Withdraw refunded bid amounts | ||
- `getActiveAuctions()`: View all currently active auctions | ||
|
||
### Build | ||
## Technical Specifications | ||
|
||
```shell | ||
$ forge build | ||
``` | ||
- Solidity version: 0.8.20 | ||
- Built with OpenZeppelin contracts | ||
- Implements ERC721 receiver interface | ||
- Uses ReentrancyGuard for security | ||
- Comprehensive test suite in Foundry | ||
|
||
### Test | ||
## Security Features | ||
|
||
```shell | ||
$ forge test | ||
``` | ||
- Reentrancy protection on critical functions | ||
- Checks-Effects-Interactions pattern | ||
- Access control via Ownable | ||
- Minimum auction duration enforcement | ||
- Safe transfer handling | ||
|
||
### Format | ||
## Testing | ||
|
||
```shell | ||
$ forge fmt | ||
``` | ||
The contract includes extensive tests covering: | ||
|
||
### Gas Snapshots | ||
- NFT deposits | ||
- Bidding functionality | ||
- Auction completion | ||
- Withdrawal mechanics | ||
- Edge cases and security scenarios | ||
|
||
```shell | ||
$ forge snapshot | ||
``` | ||
Run tests with: | ||
`forge test` | ||
|
||
### Anvil | ||
|
||
```shell | ||
$ anvil | ||
``` | ||
|
||
### Deploy | ||
|
||
```shell | ||
$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key> | ||
``` | ||
|
||
### Cast | ||
|
||
```shell | ||
$ cast <subcommand> | ||
``` | ||
|
||
### Help | ||
|
||
```shell | ||
$ forge --help | ||
$ anvil --help | ||
$ cast --help | ||
``` |
Submodule openzeppelin-contracts
added at
dac63c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/ | ||
ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/ | ||
erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/ | ||
forge-std/=lib/forge-std/src/ | ||
halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/ | ||
openzeppelin-contracts/=lib/openzeppelin-contracts/ | ||
openzepplin-contracts/=lib/openzepplin-contracts/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
# 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 | ||
|
||
- [Summary](#summary) | ||
- [Files Summary](#files-summary) | ||
- [Files Details](#files-details) | ||
- [Issue Summary](#issue-summary) | ||
- [High Issues](#high-issues) | ||
- [H-1: Uninitialized State Variables](#h-1-uninitialized-state-variables) | ||
- [H-2: Sending native Eth is not protected from these functions.](#h-2-sending-native-eth-is-not-protected-from-these-functions) | ||
- [Low Issues](#low-issues) | ||
- [L-1: Centralization Risk for trusted owners](#l-1-centralization-risk-for-trusted-owners) | ||
- [L-2: Unsafe ERC20 Operations should not be used](#l-2-unsafe-erc20-operations-should-not-be-used) | ||
- [L-3: `public` functions not used internally could be marked `external`](#l-3-public-functions-not-used-internally-could-be-marked-external) | ||
- [L-4: Event is missing `indexed` fields](#l-4-event-is-missing-indexed-fields) | ||
- [L-5: PUSH0 is not supported by all chains](#l-5-push0-is-not-supported-by-all-chains) | ||
|
||
|
||
# Summary | ||
|
||
## Files Summary | ||
|
||
| Key | Value | | ||
| --- | --- | | ||
| .sol Files | 2 | | ||
| Total nSLOC | 186 | | ||
|
||
|
||
## Files Details | ||
|
||
| Filepath | nSLOC | | ||
| --- | --- | | ||
| src/AuctionContract.sol | 168 | | ||
| src/SellerNft.sol | 18 | | ||
| **Total** | **186** | | ||
|
||
|
||
## Issue Summary | ||
|
||
| Category | No. of Issues | | ||
| --- | --- | | ||
| High | 2 | | ||
| Low | 5 | | ||
|
||
|
||
# High Issues | ||
|
||
## H-1: Uninitialized State Variables | ||
|
||
Solidity does initialize variables by default when you declare them, however it's good practice to explicitly declare an initial value. For example, if you transfer money to an address we must make sure that the address has been initialized. | ||
|
||
<details><summary>1 Found Instances</summary> | ||
|
||
|
||
- Found in src/SellerNft.sol [Line: 11](src/SellerNft.sol#L11) | ||
|
||
```solidity | ||
uint256 private tokenCounter; | ||
``` | ||
|
||
</details> | ||
|
||
|
||
|
||
## H-2: Sending native Eth is not protected from these functions. | ||
|
||
Introduce checks for `msg.sender` in the function | ||
|
||
<details><summary>1 Found Instances</summary> | ||
|
||
|
||
- Found in src/AuctionContract.sol [Line: 198](src/AuctionContract.sol#L198) | ||
|
||
```solidity | ||
function withdraw() public { | ||
``` | ||
|
||
</details> | ||
|
||
|
||
|
||
# Low Issues | ||
|
||
## L-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. | ||
|
||
<details><summary>3 Found Instances</summary> | ||
|
||
|
||
- Found in src/AuctionContract.sol [Line: 12](src/AuctionContract.sol#L12) | ||
|
||
```solidity | ||
contract AuctionContract is Ownable, ReentrancyGuard, IERC721Receiver { | ||
``` | ||
|
||
- Found in src/SellerNft.sol [Line: 10](src/SellerNft.sol#L10) | ||
|
||
```solidity | ||
contract SellerNFT is ERC721, Ownable { | ||
``` | ||
|
||
- Found in src/SellerNft.sol [Line: 22](src/SellerNft.sol#L22) | ||
|
||
```solidity | ||
function approveToAuction(address auctionContract, uint256 tokenId) external onlyOwner{ | ||
``` | ||
|
||
</details> | ||
|
||
|
||
|
||
## L-2: Unsafe ERC20 Operations should not be used | ||
|
||
ERC20 functions may not behave as expected. For example: return values are not always meaningful. It is recommended to use OpenZeppelin's SafeERC20 library. | ||
|
||
<details><summary>2 Found Instances</summary> | ||
|
||
|
||
- Found in src/AuctionContract.sol [Line: 112](src/AuctionContract.sol#L112) | ||
|
||
```solidity | ||
nft.transferFrom(msg.sender, address(this), tokenId); | ||
``` | ||
|
||
- Found in src/AuctionContract.sol [Line: 175](src/AuctionContract.sol#L175) | ||
|
||
```solidity | ||
payable(auction.seller).transfer(sellerEth); | ||
``` | ||
|
||
</details> | ||
|
||
|
||
|
||
## L-3: `public` functions not used internally could be marked `external` | ||
|
||
Instead of marking a function as `public`, consider marking it as `external` if it is not used internally. | ||
|
||
<details><summary>5 Found Instances</summary> | ||
|
||
|
||
- Found in src/AuctionContract.sol [Line: 133](src/AuctionContract.sol#L133) | ||
|
||
```solidity | ||
function bid( | ||
``` | ||
|
||
- Found in src/AuctionContract.sol [Line: 162](src/AuctionContract.sol#L162) | ||
|
||
```solidity | ||
function sellerEndAuction(uint256 auctionId) public nonReentrant { | ||
``` | ||
|
||
- Found in src/AuctionContract.sol [Line: 186](src/AuctionContract.sol#L186) | ||
|
||
```solidity | ||
function getActiveAuctions() public view returns (uint256[] memory) { | ||
``` | ||
|
||
- Found in src/AuctionContract.sol [Line: 198](src/AuctionContract.sol#L198) | ||
|
||
```solidity | ||
function withdraw() public { | ||
``` | ||
|
||
- Found in src/AuctionContract.sol [Line: 210](src/AuctionContract.sol#L210) | ||
|
||
```solidity | ||
function onERC721Received( | ||
``` | ||
|
||
</details> | ||
|
||
|
||
|
||
## L-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. | ||
|
||
<details><summary>4 Found Instances</summary> | ||
|
||
|
||
- Found in src/AuctionContract.sol [Line: 27](src/AuctionContract.sol#L27) | ||
|
||
```solidity | ||
event NFTDeposited( | ||
``` | ||
|
||
- Found in src/AuctionContract.sol [Line: 32](src/AuctionContract.sol#L32) | ||
|
||
```solidity | ||
event BidPlaced( | ||
``` | ||
|
||
- Found in src/AuctionContract.sol [Line: 37](src/AuctionContract.sol#L37) | ||
|
||
```solidity | ||
event AuctionEnded( | ||
``` | ||
|
||
- Found in src/AuctionContract.sol [Line: 42](src/AuctionContract.sol#L42) | ||
|
||
```solidity | ||
event bidRefunded( | ||
``` | ||
|
||
</details> | ||
|
||
|
||
|
||
## L-5: PUSH0 is not supported by all chains | ||
|
||
Solc compiler version 0.8.20 switches the default target EVM version to Shanghai, which means that the generated bytecode will include PUSH0 opcodes. Be sure to select the appropriate EVM version in case you intend to deploy on a chain other than mainnet like L2 chains that may not support PUSH0, otherwise deployment of your contracts will fail. | ||
|
||
<details><summary>2 Found Instances</summary> | ||
|
||
|
||
- Found in src/AuctionContract.sol [Line: 3](src/AuctionContract.sol#L3) | ||
|
||
```solidity | ||
pragma solidity 0.8.20; | ||
``` | ||
|
||
- Found in src/SellerNft.sol [Line: 3](src/SellerNft.sol#L3) | ||
|
||
```solidity | ||
pragma solidity 0.8.20; | ||
``` | ||
|
||
</details> | ||
|
||
|
||
|
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.20; | ||
|
||
import {Script} from "forge-std/Script.sol"; | ||
import {AuctionContract} from "../src/AuctionContract.sol"; | ||
|
||
contract DeployAuctionContract is Script { | ||
AuctionContract private auctionContract; | ||
|
||
function run() public returns (AuctionContract) { | ||
vm.startBroadcast(); | ||
auctionContract = new AuctionContract(); | ||
vm.stopBroadcast(); | ||
return auctionContract; | ||
} | ||
} |
Oops, something went wrong.