Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ jobs:
run: |
forge --version

- name: Run Forge fmt
run: |
forge fmt --check
id: fmt
# - name: Run Forge fmt
# run: |
# forge fmt --check
# id: fmt

- name: Run Forge build
run: |
Expand Down
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
## ETHER GUILD PROTOCOL

Setup .env variables.
```
DEPLOYER_PRIVATE_KEY=0x1234
SEPOLIA_RPC_URL='https://...`
```

## Smart Contracts

- **src/QuestFactory**: msg.sender as Admin, allows anyone to create New Quest (factory admin will persist to Quest)
- **src/QuestDonation**: contructor params: @admin, @target, @creator

### Quest Donation
- MAX_DONATION(hardcoded): $5000/ year
- Admin Must `allowToken(token, status)` to set `setPriceOracle(token, oracle)`
- For Native ETH address(0) is used.


## Running the Script

To run the deployment script, use the following command:
```shell
$ forge script script/Deploy.s.sol --rpc-url sepolia
```

## Testing Smart Contracts

To test the smart contracts, execute:
```shell
$ forge test
```

## Foundry

**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.**
Expand Down
261 changes: 261 additions & 0 deletions broadcast/1.Deploy.s.sol/11155111/run-1739055178.json

Large diffs are not rendered by default.

261 changes: 261 additions & 0 deletions broadcast/1.Deploy.s.sol/11155111/run-latest.json

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,13 @@
src = "src"
out = "out"
libs = ["lib"]
via_ir = true

[rpc_endpoints]
sepolia = "${SEPOLIA_RPC_URL}"



# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options


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

import {Script, console} from "forge-std/Script.sol";
import {Helper} from "./Helper.sol";
import {QuestFactory} from "../src/QuestFactory.sol";



contract DeployQuestScript is Script, Helper {

function run() external returns (address questFactoryAddress, address questDonationAddress) {
uint256 deployerPrivateKey = getDeployerPrivateKey();
vm.startBroadcast(deployerPrivateKey);

// Deploy QuestFactory with constructor parameters
// Sets msg.sender as admin for factory and all future quests created
QuestFactory questFactory = new QuestFactory();
questFactoryAddress = address(questFactory);

// Create a new Quest with a target amount (for example, 1 ether)
// Msg.sender is the creator of the quest, but only admin can withdraw funds
uint256 targetAmount = 1 ether;
questDonationAddress = questFactory.createQuest(targetAmount);

// Log deployed addresses
console.log("QuestFactory deployed to:", questFactoryAddress);
console.log("QuestDonation deployed to:", questDonationAddress);

vm.stopBroadcast();
}

}

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

import {Script, console} from "forge-std/Script.sol";
import {Helper} from "./Helper.sol";
import {QuestDonation} from "../src/QuestDonation.sol";


contract SetupQuestScript is Script, Helper {

function run(address questDonationAddress) external {
uint256 deployerPrivateKey = getDeployerPrivateKey();
vm.startBroadcast(deployerPrivateKey);

QuestDonation questDonation = QuestDonation(questDonationAddress);

// Allow tokens
// ETH is not already allowed by default
questDonation.allowToken(address(0), true);
questDonation.allowToken(USDC, true);
console.log("ETH address(0) and USDC set as allowed tokens");

// Set price oracles
questDonation.setPriceOracle(address(0), ETH_USD_FEED); // For Native ETH
questDonation.setPriceOracle(USDC, USDC_USD_FEED); // USDC Oracle
console.log("Price oracles set for ETH and USDC");

vm.stopBroadcast();
}

}

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

import {Script, console} from "forge-std/Script.sol";
import {Helper} from "./Helper.sol";
import {QuestDonation} from "../src/QuestDonation.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";


contract InteractionQuestScript is Script, Helper {

function run(address questDonationAddress) external {
uint256 deployerPrivateKey = getDeployerPrivateKey();
vm.startBroadcast(deployerPrivateKey);

QuestDonation questDonation = QuestDonation(questDonationAddress);

// DEPLOYER WALLET
// CHECK ETH BALANCE
address deployerAddress = vm.addr(deployerPrivateKey);
console.log("Address:", deployerAddress);
console.log("ETH Balance: ", deployerAddress.balance/ 10**18);
// CHECK USDC BALANCE
console.log("USDC balance:", IERC20(USDC).balanceOf(address(deployerAddress))/ 10**6);


// Make donations
// ETH donation
questDonation.donateETH{value: 0.1 ether}(); // Donate ETH
console.log("Donated 0.1 ETH");

// USDC donation
uint256 usdcAmount = 100 * 10**6;
IERC20(USDC).approve(address(questDonation), usdcAmount); // DONATE USDC
questDonation.donateERC20(USDC, usdcAmount);
console.log("Donated 100 USDC");


// Log balances after donations
console.log("===QUEST CONTRACT: Balances after donations ===");
console.log("ETH balance:", address(questDonation).balance);
console.log("USDC balance:", IERC20(USDC).balanceOf(address(questDonation)));


// Withdraw funds
uint256 ethBalance = address(questDonation).balance;
uint256 usdcBalance = IERC20(USDC).balanceOf(address(questDonation));

if (ethBalance > 0) {
questDonation.withdraw(address(0), ethBalance/2); // WITHDRAW ETH
console.log("Withdrawn ETH balance:", ethBalance/2);
}

if (usdcBalance > 0) {
questDonation.withdraw(USDC, usdcBalance/2); // EITHDRAW USDC
console.log("Withdrawn USDC balance:", usdcBalance/2);
}

// Log balances after withdrawals
console.log("===QUEST CONTRACT: Balances after withdrawals ===");
console.log("ETH balance:", address(questDonation).balance);
console.log("USDC balance:", IERC20(USDC).balanceOf(address(questDonation)));

vm.stopBroadcast();
}

}

19 changes: 0 additions & 19 deletions script/Counter.s.sol

This file was deleted.

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

import {Helper} from "./Helper.sol";
import {DeployQuestScript} from "./1_DeployQuest.s.sol";
import {SetupQuestScript} from "./2_SetupQuest.s.sol";
import {InteractionQuestScript} from "./3_InteractionQuest.s.sol";

contract DeployScript is Helper {
function run() external {

//DEPLOYS FACTORY AND FIRST EXAMPLE QUEST
DeployQuestScript deployQuest = new DeployQuestScript();
( , address firstQuest) = deployQuest.run();

// ALLOW TOKENS AND ADD ORACLE
SetupQuestScript setupQuest = new SetupQuestScript();
setupQuest.run(firstQuest);

// INTERACTING WITH FIRST QUEST
InteractionQuestScript interactingQuest = new InteractionQuestScript();
interactingQuest.run(firstQuest);

}
}
25 changes: 25 additions & 0 deletions script/Helper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.24;
import {Script} from "forge-std/Script.sol";


contract Helper is Script{
address constant USDC = 0x94a9D9AC8a22534E3FaCa9F4e7F2E2cf85d5E4C8;

// Chainlink Price Feed addresses
address constant ETH_USD_FEED = 0x694AA1769357215DE4FAC081bf1f309aDC325306;
address constant USDC_USD_FEED = 0xA2F78ab2355fe2f984D808B5CeE7FD0A93D5270E;
error InvalidPrivateKey(string);


function getDeployerPrivateKey() internal view returns (uint256 deployerPrivateKey) {
deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY");
if (deployerPrivateKey == 0) {
revert InvalidPrivateKey(
"You don't have a deployer account. Make sure you have set DEPLOYER_PRIVATE_KEY in .env or use `yarn generate` to generate a new random account"
);
}
}


}
14 changes: 0 additions & 14 deletions src/Counter.sol

This file was deleted.

Loading