Skip to content

Commit

Permalink
smart contract lottery
Browse files Browse the repository at this point in the history
  • Loading branch information
sergipastor committed Aug 29, 2024
1 parent cf693ba commit d0e25f5
Show file tree
Hide file tree
Showing 18 changed files with 836 additions and 113 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ out/
!/broadcast
/broadcast/*/31337/
/broadcast/**/dry-run/
/broadcast/

# Docs
docs/

# Dotenv file
.env
misc/
9 changes: 9 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "lib/chainlink-brownie-contracts"]
path = lib/chainlink-brownie-contracts
url = https://github.com/smartcontractkit/chainlink-brownie-contracts
[submodule "lib/solmate"]
path = lib/solmate
url = https://github.com/transmissions11/solmate
[submodule "lib/foundry-devops"]
path = lib/foundry-devops
url = https://github.com/cyfrin/foundry-devops
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-include .env

.PHONY: all test deploy

build :; forge build

test:; forge test

install :; forge install cyfrin/[email protected] --no-commit && forge install smartcontractkit/[email protected] --no-commit && forge install foundry-rs/[email protected] --no-commit && forge install transmissions11/solmate@v6 --no-commit

deploy-sepolia:
@forge script ./script/DeployRaffle.s.sol:DeployRaffle --rpc-url $(SEPOLIA_RPC_URL) --account sepolia --broadcast --verify --etherscan-api-key $(ETHERSCAN_API_KEY) -vvvv
79 changes: 25 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,66 +1,37 @@
## Foundry
# Smart Contract Lottery

**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.**
This project is a decentralized lottery/raffle application implemented using Solidity and Foundry. This project was developed following the Cyfrin Updraft online course.
Cyfrin repo: https://github.com/Cyfrin/foundry-smart-contract-lottery-cu

Foundry consists of:
## How It Works

- **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.
1. Users enter the lottery by sending ETH to the smart contract, paying a predefined minimum entry fee.
2. After a specified amount of time, a winner is selected randomly from the list of participants.
3. The winner receives the entire accumulated prize pool.

## Documentation
## Setup and Installation

https://book.getfoundry.sh/
1. **Clone the Repository:**

## Usage
```bash
git clone https://github.com/sergipastor/smart-contract-lottery-cyfrin.git
cd smart-contract-lottery-cyfrin
```

### Build
2. **Install Dependencies:**

```shell
$ forge build
```
```bash
make install
```

### Test
3. **Compile Contracts:**

```shell
$ forge test
```
```bash
make build
```

### Format
4. **Run Tests:**

```shell
$ forge fmt
```

### Gas Snapshots

```shell
$ forge snapshot
```

### 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
```
```bash
make test
```
7 changes: 6 additions & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,10 @@
src = "src"
out = "out"
libs = ["lib"]
remappings = [
"@chainlink/contracts/=lib/chainlink-brownie-contracts/contracts/",
"@solmate=lib/solmate/src/",
]

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
[fuzz]
runs = 256 # sets the number of runs in fuzz tests
1 change: 1 addition & 0 deletions lib/chainlink-brownie-contracts
1 change: 1 addition & 0 deletions lib/foundry-devops
Submodule foundry-devops added at df9f90
1 change: 1 addition & 0 deletions lib/solmate
Submodule solmate added at a9e3ea
19 changes: 0 additions & 19 deletions script/Counter.s.sol

This file was deleted.

45 changes: 45 additions & 0 deletions script/DeployRaffle.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {Script} from "forge-std/Script.sol";
import {Raffle} from "../src/Raffle.sol";
import {HelperConfig} from "../script/HelperConfig.s.sol";
import {CreateSubscription, FundSubscription, AddConsumer} from "script/Interactions.s.sol";

contract DeployRaffle is Script {
function run() public {
deployContract();
}

function deployContract() public returns (Raffle, HelperConfig) {
HelperConfig helperConfig = new HelperConfig();

HelperConfig.NetworkConfig memory config = helperConfig.getConfig();

if (config.subscriptionId == 0) {
CreateSubscription createSubscription = new CreateSubscription();
// updates subscriptionId & vrfCoordinator in config
(config.subscriptionId, config.vrfCoordinator) =
createSubscription.createSubscription(config.vrfCoordinator, config.account);

FundSubscription fundSubscription = new FundSubscription();
fundSubscription.fundSubscription(config.vrfCoordinator, config.subscriptionId, config.link, config.account);
}

vm.startBroadcast(config.account);
Raffle raffle = new Raffle(
config.entranceFee,
config.interval,
config.vrfCoordinator,
config.gasLane,
config.subscriptionId,
config.callbackGasLimit
);
vm.stopBroadcast();

AddConsumer addConsumer = new AddConsumer();
// it's broadcasted inside addConsumer
addConsumer.addConsumer(address(raffle), config.vrfCoordinator, config.subscriptionId, config.account);
return (raffle, helperConfig);
}
}
101 changes: 101 additions & 0 deletions script/HelperConfig.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {Script} from "forge-std/Script.sol";
import {VRFCoordinatorV2_5Mock} from "@chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol";
import {LinkToken} from "test/mocks/LinkToken.sol";

abstract contract CodeConstants {
uint96 public MOCK_BASE_FEE = 0.25 ether;
uint96 public MOCK_GAS_PRICE_LINK = 1e9;
// LINK / ETH price
int256 public MOCK_WEI_PER_UINT_LINK = 4e15;

address public FOUNDRY_DEFAULT_SENDER =
0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38;

uint256 public constant ETH_SEPOLIA_CHAIN_ID = 11155111;
uint256 public constant LOCAL_CHAIN_ID = 31337;
}

contract HelperConfig is CodeConstants, Script {
error HelperConfig__InvalidChainId();

struct NetworkConfig {
uint256 entranceFee;
uint256 interval;
address vrfCoordinator;
bytes32 gasLane;
uint32 callbackGasLimit;
uint256 subscriptionId;
address link;
address account;
}

NetworkConfig public localNetworkConfig;
mapping(uint256 chainId => NetworkConfig) public networkConfigs;

constructor() {
networkConfigs[ETH_SEPOLIA_CHAIN_ID] = getSepoliaEthConfig();
}

function getConfigByChainId(
uint256 chainId
) public returns (NetworkConfig memory) {
if (networkConfigs[chainId].vrfCoordinator != address(0)) {
return networkConfigs[chainId];
} else if (chainId == LOCAL_CHAIN_ID) {
return getOrCreateAnvilEthConfig();
} else {
revert HelperConfig__InvalidChainId();
}
}

function getConfig() public returns (NetworkConfig memory) {
return getConfigByChainId(block.chainid);
}

function getSepoliaEthConfig()
public
pure
returns (NetworkConfig memory sepoliaNetworkConfig)
{
sepoliaNetworkConfig = NetworkConfig({
entranceFee: 0.01 ether,
interval: 30,
vrfCoordinator: 0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B,
gasLane: 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae,
callbackGasLimit: 500000,
subscriptionId: 51047831189129265369038141528057349675397396091678916226248283722260792977383, // If left as 0, our scripts will create one!
link: 0x779877A7B0D9E8603169DdbD7836e478b4624789,
account: 0x0B5eE21c72F06E74AE02b34F6478eC27E1937FC1
});
}

function getOrCreateAnvilEthConfig() public returns (NetworkConfig memory) {
if (localNetworkConfig.vrfCoordinator != address(0)) {
return localNetworkConfig;
}

vm.startBroadcast();
VRFCoordinatorV2_5Mock vrfCoordinatorV2_5Mock = new VRFCoordinatorV2_5Mock(
MOCK_BASE_FEE,
MOCK_GAS_PRICE_LINK,
MOCK_WEI_PER_UINT_LINK
);
LinkToken linkToken = new LinkToken();
vm.stopBroadcast();

localNetworkConfig = NetworkConfig({
entranceFee: 0.01 ether,
interval: 30,
vrfCoordinator: address(vrfCoordinatorV2_5Mock),
gasLane: 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae,
callbackGasLimit: 500000,
subscriptionId: 0, // If left as 0, our scripts will create one!
link: address(linkToken),
account: FOUNDRY_DEFAULT_SENDER
});
return localNetworkConfig;
}
}
Loading

0 comments on commit d0e25f5

Please sign in to comment.