Skip to content

Commit 3678dae

Browse files
authored
chore: merge PR #68 from aji70/diamond-std
feat: integrate Diamond std
2 parents 8de0f87 + de979d0 commit 3678dae

85 files changed

Lines changed: 3860 additions & 543 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@ node_modules
1515

1616
# Hardhat Ignition default folder for deployments against a local node
1717
ignition/deployments/chain-31337
18+
19+
/lib
20+
/forge-std

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[submodule "lib/forge-std"]
22
path = lib/forge-std
33
url = https://github.com/foundry-rs/forge-std
4+
[submodule "lib/openzeppelin-contracts"]
5+
path = lib/openzeppelin-contracts
6+
url = https://github.com/OpenZeppelin/openzeppelin-contracts

PULL_REQUEST_TEMPLATE.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<!-- Thank you for your interest in contributing to BlockHeaderWeb3! -->
22

3+
Assignment 1 link [here](https://github.com/BlockheaderWeb3-Community/cohort-6/blob/main/assignments/Assignment1.md)
4+
5+
Assignment 2 link [here](https://github.com/BlockheaderWeb3-Community/cohort-6/blob/main/assignments/Assignment2.md)
36

47
<!-- Describe the changes introduced in this pull request. -->
58
<!-- Include any context necessary for understanding the PR's purpose. -->
@@ -12,4 +15,3 @@
1215

1316
- [ ] Tests
1417
- [ ] Documentation
15-

README.md

Lines changed: 2 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,2 @@
1-
## Foundry
2-
3-
**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.**
4-
5-
Foundry consists of:
6-
7-
- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools).
8-
- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data.
9-
- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network.
10-
- **Chisel**: Fast, utilitarian, and verbose solidity REPL.
11-
12-
## Documentation
13-
14-
https://book.getfoundry.sh/
15-
16-
## Usage
17-
18-
### Build
19-
20-
```shell
21-
$ forge build
22-
```
23-
24-
### Test
25-
26-
```shell
27-
$ forge test
28-
```
29-
30-
### Format
31-
32-
```shell
33-
$ forge fmt
34-
```
35-
36-
### Gas Snapshots
37-
38-
```shell
39-
$ forge snapshot
40-
```
41-
42-
### Anvil
43-
44-
```shell
45-
$ anvil
46-
```
47-
48-
### Deploy
49-
50-
```shell
51-
$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key>
52-
```
53-
54-
### Cast
55-
56-
```shell
57-
$ cast <subcommand>
58-
```
59-
60-
### Help
61-
62-
```shell
63-
$ forge --help
64-
$ anvil --help
65-
$ cast --help
66-
```
1+
# Introduction to Foundry
2+
Master the concepts to develop, test and deploy EVM contracts with Foundry
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.24;
3+
import {console} from "forge-std/Test.sol";
4+
import "@chainlink/contracts/src/v0.7/interfaces/AggregatorV3Interface.sol";
5+
import "../../contracts/with-foundry/RewardToken.sol";
6+
import "../../contracts/with-foundry/RewardNft.sol";
7+
8+
contract CrowdfundingV2 {
9+
address public Owner;
10+
uint public constant FUNDING_GOAL_IN_USD = 50000;
11+
uint public constant NFT_THRESHOLD = 1000;
12+
uint256 public totalFundsRaised;
13+
bool public isFundingComplete;
14+
15+
RewardToken public rewardToken;
16+
RewardNft public rewardNFT;
17+
uint256 public tokenRewardRate;
18+
19+
// Contribution tracking
20+
mapping(address => uint256) public contributions;
21+
mapping(address => bool) public hasReceivedNFT;
22+
23+
// Chainlink PriceFeed
24+
AggregatorV3Interface priceFeed;
25+
address public constant ETH_USD_ADDR = 0x694AA1769357215DE4FAC081bf1f309aDC325306;
26+
// Events
27+
event ContributionReceived(address indexed contributor, uint256 amount);
28+
event TokenRewardSent(address indexed contributor, uint256 amount);
29+
event NFTRewardSent(address indexed contributor, uint256 tokenId);
30+
event FundsWithdrawn(address indexed projectOwner, uint256 amount);
31+
32+
constructor(uint256 _tokenRewardRate, address _rewardToken, address _rewardNft) {
33+
/**
34+
* Network: Sepolia
35+
* Data Feed: ETH/USD
36+
* Address: 0x694AA1769357215DE4FAC081bf1f309aDC325306
37+
*/
38+
priceFeed = AggregatorV3Interface(ETH_USD_ADDR);
39+
Owner = msg.sender;
40+
rewardToken = RewardToken(_rewardToken);
41+
rewardNFT = RewardNft(_rewardNft);
42+
tokenRewardRate = _tokenRewardRate;
43+
}
44+
45+
// function to retrieve ETH price in USD with Chainlink priceFeed
46+
function getLatestPrice() public view returns (int256) {
47+
(
48+
,
49+
// uint80 roundID
50+
int256 answer, // uint256 startedAt
51+
,
52+
,
53+
54+
) = // uint256 updatedAt
55+
priceFeed.latestRoundData();
56+
57+
return answer; // Price has 8 decimals, e.g., 3000.00000000
58+
}
59+
60+
function contribute() external payable returns (bool) {
61+
require(msg.value > 0, "Contribution must be greater than 0");
62+
require(!isFundingComplete, "Funding goal already reached");
63+
64+
// Calculate contribution amount and process any refunds
65+
66+
uint256 refundableAmount = _determineIfAmountIsRefundable(msg.value);
67+
uint256 actualContribution = msg.value - refundableAmount;
68+
69+
// check if refundable amount is > 0
70+
if (refundableAmount > 0) {
71+
transferRefundableAmount(refundableAmount, msg.sender);
72+
}
73+
74+
// Update contribution record
75+
// uint256 contributionsValue = msg.value - refundableAmount;
76+
contributions[msg.sender] += actualContribution;
77+
totalFundsRaised += actualContribution;
78+
79+
// Check if funding goal is reached
80+
if (totalFundsRaised >= FUNDING_GOAL_IN_USD) {
81+
isFundingComplete = true;
82+
}
83+
84+
// Calculate token reward
85+
uint256 tokenReward = calculateReward(actualContribution);
86+
87+
if (tokenReward > 0) {
88+
bool isTransfered = sendRewardToken(tokenReward, msg.sender);
89+
require(isTransfered, "Token transfer failed");
90+
91+
// Check for NFT eligibility
92+
if (checkNftEligibility(msg.sender)) {
93+
mintNft(msg.sender);
94+
}
95+
96+
emit ContributionReceived(msg.sender, actualContribution);
97+
return true;
98+
} else {
99+
return false;
100+
}
101+
}
102+
103+
function checkNftEligibility(address _address) private view returns (bool) {
104+
return contributions[_address] >= NFT_THRESHOLD && !hasReceivedNFT[_address];
105+
}
106+
107+
function mintNft(address _contributor) private returns (bool) {
108+
// require(checkNftEligibilty(_contributor), "Not eligible for NFT reward");
109+
uint256 tokenId = rewardNFT.mintNFT(_contributor);
110+
hasReceivedNFT[_contributor] = true;
111+
emit NFTRewardSent(_contributor, tokenId);
112+
return true;
113+
}
114+
115+
function calculateReward(uint256 _value) private view returns (uint256) {
116+
uint256 tokenReward = (_value * tokenRewardRate) / 1 ether;
117+
return tokenReward;
118+
}
119+
120+
function sendRewardToken(uint256 _tokenReward, address _recipient) private returns (bool) {
121+
bool success = rewardToken.transfer(_recipient, _tokenReward);
122+
require(success, "Token transfer failed");
123+
emit TokenRewardSent(msg.sender, _tokenReward);
124+
125+
return true;
126+
}
127+
128+
function _determineIfAmountIsRefundable(uint256 _contributionAmount) private view returns (uint256) {
129+
// Calculate the remaining amount needed to complete the funding goal
130+
uint256 amountToReachThreshold = FUNDING_GOAL_IN_USD - totalFundsRaised;
131+
if (_contributionAmount >= amountToReachThreshold) {
132+
// return the excess amount
133+
uint256 refundAmount = _contributionAmount - amountToReachThreshold;
134+
return refundAmount;
135+
}
136+
return 0;
137+
}
138+
139+
function transferRefundableAmount(uint256 _amount, address _contributor) private {
140+
// uint256 refundable = _determineIfAmountIsRefundable(_amount);
141+
uint256 refundable = _amount;
142+
if (refundable > 0) {
143+
(bool success, ) = _contributor.call{value: refundable}("");
144+
require(success, "Transfer failed");
145+
}
146+
}
147+
148+
function withdrawFunds() external {
149+
require(msg.sender == Owner, "Only project owner can withdraw");
150+
require(isFundingComplete, "Funding goal not yet reached");
151+
require(address(this).balance > 0, "No funds to withdraw");
152+
153+
uint256 amount = address(this).balance;
154+
payable(Owner).transfer(amount);
155+
156+
emit FundsWithdrawn(Owner, amount);
157+
}
158+
159+
function getContribution(address contributor) external view returns (uint256) {
160+
return contributions[contributor];
161+
}
162+
}

contracts/counter_alex.sol

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity >=0.5.0 <0.9.0;
3+
4+
/**
5+
* @title Counter Contract
6+
* @notice A simple counter contract that supports incrementing and decrementing operations.
7+
* @dev Provides functions to increment, decrement and adjust the counter by a specified value.
8+
*/
9+
10+
contract Counter {
11+
/**
12+
* @notice The current count value.
13+
* @dev Public state variable initialized to zero.
14+
*/
15+
uint public countVal = 0;
16+
17+
/**
18+
* @notice Retrieves the current count value.
19+
* @return The current counter value.
20+
*/
21+
function getCount() public view returns (uint) {
22+
return countVal;
23+
}
24+
25+
/**
26+
* @notice Increments the counter by one.
27+
* @dev Ensures that the counter does not exceed the maximum value defined by runner().
28+
*/
29+
function increment() public {
30+
uint maxValue = runner();
31+
require(countVal < maxValue);
32+
countVal++;
33+
}
34+
35+
/**
36+
* @notice Decrements the counter by one.
37+
* @dev Prevents the counter from decrementing below zero.
38+
*/
39+
function decrement() public {
40+
require(countVal > 0, "Counter cannot be negative");
41+
countVal--;
42+
}
43+
44+
/**
45+
* @notice Increments the counter by a specified positive value.
46+
* @param _val The value to add to the current count.
47+
* @dev Validates that _val is greater than zero and that the resulting count does not exceed the maximum value.
48+
*/
49+
function incrementByVal(uint _val) public {
50+
uint maxValue = runner();
51+
require(_val > 0, "Must be greater than zero");
52+
require(countVal + _val <= maxValue, "Counter cannot be negative");
53+
countVal += _val;
54+
}
55+
56+
/**
57+
* @notice Decrements the counter by a specified positive value.
58+
* @param _val The value to subtract from the current count.
59+
* @dev Validates that _val is greater than zero and that the current count is sufficient to subtract _val without underflow.
60+
*/
61+
function decrementByVal(uint _val) public {
62+
require(_val > 0, "Must be greater than zero");
63+
require(countVal >= _val, "Underflow: Cannot decrement below zero"); // Prevent underflow
64+
65+
countVal -= _val;
66+
}
67+
68+
/**
69+
* @notice Computes the maximum value for a uint256.
70+
* @return The maximum possible value of a uint256.
71+
* @dev Uses unchecked arithmetic to derive the maximum uint256 value.
72+
*/
73+
function runner() public pure returns (uint) {
74+
unchecked {
75+
return uint256(0) - 1;
76+
}
77+
}
78+
}

contracts/crowdfunding_alex.sol

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.24;
3+
4+
import "./reward_token.sol";
5+
import "./reward_nft_alex.sol";
6+
contract CrowdFund {}

contracts/reward_nft_alex.sol

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.24;
3+
4+
contract RewardNFT {
5+
// ...
6+
}

contracts/reward_token_alex.sol

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.24;
3+
4+
contract RewardToken {
5+
// ...
6+
}

0 commit comments

Comments
 (0)