From 7defbcdac61e4a0cd006c21eb87203835fd93065 Mon Sep 17 00:00:00 2001 From: Tobias Leinss Date: Sun, 9 Feb 2025 06:36:14 +0000 Subject: [PATCH] Format contracts aligned with fmt --- .github/workflows/test.yml | 8 +++--- script/1_DeployQuest.s.sol | 7 +----- script/2_SetupQuest.s.sol | 6 +---- script/3_InteractionQuest.s.sol | 29 +++++++++------------- script/Deploy.s.sol | 6 ++--- script/Helper.sol | 12 ++++----- src/QuestDonation.sol | 32 +++++++++++------------- src/QuestFactory.sol | 44 +++++++++------------------------ test/QuestDonation.t.sol | 39 ++++++++++++++--------------- test/mocks/MockERC20.sol | 2 +- test/mocks/MockV3Aggregator.sol | 18 +++----------- 11 files changed, 73 insertions(+), 130 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ca11881..34a4a52 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -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: | diff --git a/script/1_DeployQuest.s.sol b/script/1_DeployQuest.s.sol index 0650569..b1dd98f 100644 --- a/script/1_DeployQuest.s.sol +++ b/script/1_DeployQuest.s.sol @@ -5,10 +5,7 @@ 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); @@ -16,7 +13,7 @@ contract DeployQuestScript is Script, Helper { // Deploy QuestFactory with constructor parameters // Sets msg.sender as admin for factory and all future quests created QuestFactory questFactory = new QuestFactory(); - questFactoryAddress = address(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 @@ -29,6 +26,4 @@ contract DeployQuestScript is Script, Helper { vm.stopBroadcast(); } - } - \ No newline at end of file diff --git a/script/2_SetupQuest.s.sol b/script/2_SetupQuest.s.sol index 008932f..803d382 100644 --- a/script/2_SetupQuest.s.sol +++ b/script/2_SetupQuest.s.sol @@ -5,9 +5,7 @@ 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); @@ -22,11 +20,9 @@ contract SetupQuestScript is Script, Helper { // Set price oracles questDonation.setPriceOracle(address(0), ETH_USD_FEED); // For Native ETH - questDonation.setPriceOracle(USDC, USDC_USD_FEED); // USDC Oracle + questDonation.setPriceOracle(USDC, USDC_USD_FEED); // USDC Oracle console.log("Price oracles set for ETH and USDC"); vm.stopBroadcast(); } - } - \ No newline at end of file diff --git a/script/3_InteractionQuest.s.sol b/script/3_InteractionQuest.s.sol index 9038699..026be2a 100644 --- a/script/3_InteractionQuest.s.sol +++ b/script/3_InteractionQuest.s.sol @@ -6,9 +6,7 @@ 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); @@ -19,41 +17,38 @@ contract InteractionQuestScript is Script, Helper { // CHECK ETH BALANCE address deployerAddress = vm.addr(deployerPrivateKey); console.log("Address:", deployerAddress); - console.log("ETH Balance: ", deployerAddress.balance/ 10**18); + console.log("ETH Balance: ", deployerAddress.balance / 10 ** 18); // CHECK USDC BALANCE - console.log("USDC balance:", IERC20(USDC).balanceOf(address(deployerAddress))/ 10**6); - + console.log("USDC balance:", IERC20(USDC).balanceOf(address(deployerAddress)) / 10 ** 6); // Make donations // ETH donation - questDonation.donateETH{value: 0.1 ether}(); // Donate ETH + questDonation.donateETH{value: 0.1 ether}(); // Donate ETH console.log("Donated 0.1 ETH"); // USDC donation - uint256 usdcAmount = 100 * 10**6; + 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)); + 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); + 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); + questDonation.withdraw(USDC, usdcBalance / 2); // EITHDRAW USDC + console.log("Withdrawn USDC balance:", usdcBalance / 2); } // Log balances after withdrawals @@ -63,6 +58,4 @@ contract InteractionQuestScript is Script, Helper { vm.stopBroadcast(); } - } - \ No newline at end of file diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index 909b753..be69ff1 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -8,10 +8,9 @@ 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(); + (, address firstQuest) = deployQuest.run(); // ALLOW TOKENS AND ADD ORACLE SetupQuestScript setupQuest = new SetupQuestScript(); @@ -20,6 +19,5 @@ contract DeployScript is Helper { // INTERACTING WITH FIRST QUEST InteractionQuestScript interactingQuest = new InteractionQuestScript(); interactingQuest.run(firstQuest); - } -} \ No newline at end of file +} diff --git a/script/Helper.sol b/script/Helper.sol index 239bdde..b8b8df9 100644 --- a/script/Helper.sol +++ b/script/Helper.sol @@ -1,16 +1,16 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.24; -import {Script} from "forge-std/Script.sol"; +import {Script} from "forge-std/Script.sol"; -contract Helper is Script{ +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); + error InvalidPrivateKey(string); function getDeployerPrivateKey() internal view returns (uint256 deployerPrivateKey) { deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY"); @@ -20,6 +20,4 @@ contract Helper is Script{ ); } } - - -} \ No newline at end of file +} diff --git a/src/QuestDonation.sol b/src/QuestDonation.sol index e7a91ed..a54e489 100644 --- a/src/QuestDonation.sol +++ b/src/QuestDonation.sol @@ -26,29 +26,24 @@ contract QuestDonation is Ownable { event FundsWithdrawn(address indexed token, uint256 amount); event PriceOracleSet(address indexed token, address indexed oracle); - constructor( - address _admin, - uint256 _targetAmount, - address _creator - ) Ownable(_admin) { + constructor(address _admin, uint256 _targetAmount, address _creator) Ownable(_admin) { require(_admin != address(0), "Invalid admin address"); require(_creator != address(0), "Invalid creator address"); require(_targetAmount > 0, "Invalid target amount"); - + admin = _admin; targetAmount = _targetAmount; creator = _creator; } - modifier withinDonationLimit(address token, uint256 amount) { require(address(priceOracles[token]) != address(0), "No price oracle set for token"); AggregatorV3Interface priceFeed = priceOracles[token]; - (, int256 price, , , ) = priceFeed.latestRoundData(); + (, int256 price,,,) = priceFeed.latestRoundData(); uint8 priceDecimals = priceFeed.decimals(); - + require(price > 0, "Invalid price"); - + uint256 usdValue; if (token == address(0)) { // Native token (ETH) has 18 decimals @@ -59,23 +54,25 @@ contract QuestDonation is Ownable { // Adjust the calculation based on token decimals usdValue = (amount * uint256(price)) / (10 ** tokenDecimals) / (10 ** priceDecimals); } - + uint256 lastYear = lastDonationTimestamp[msg.sender]; if (block.timestamp - lastYear > YEAR) { yearlyDonations[msg.sender] = 0; lastDonationTimestamp[msg.sender] = block.timestamp; } - require(yearlyDonations[msg.sender] + usdValue <= MAX_DONATION, "Donation exceeds $5000/year. Contact info@etherguild.xyz"); - + require( + yearlyDonations[msg.sender] + usdValue <= MAX_DONATION, + "Donation exceeds $5000/year. Contact info@etherguild.xyz" + ); + yearlyDonations[msg.sender] += usdValue; _; } function donateETH() external payable withinDonationLimit(address(0), msg.value) { - require(msg.value > 0, "Donation amount must be greater than 0"); AggregatorV3Interface priceFeed = priceOracles[address(0)]; - (, int256 price, , , ) = priceFeed.latestRoundData(); + (, int256 price,,,) = priceFeed.latestRoundData(); uint8 priceDecimals = priceFeed.decimals(); emit DonationReceived(msg.sender, address(0), msg.value, msg.value * uint256(price) / (10 ** priceDecimals)); } @@ -84,7 +81,7 @@ contract QuestDonation is Ownable { require(allowedTokens[token], "Token not allowed"); IERC20(token).safeTransferFrom(msg.sender, address(this), amount); AggregatorV3Interface priceFeed = priceOracles[token]; - (, int256 price, , , ) = priceFeed.latestRoundData(); + (, int256 price,,,) = priceFeed.latestRoundData(); uint8 priceDecimals = priceFeed.decimals(); emit DonationReceived(msg.sender, token, amount, amount * uint256(price) / (10 ** priceDecimals)); } @@ -100,12 +97,11 @@ contract QuestDonation is Ownable { function setPriceOracle(address token, address oracle) external onlyOwner { require(allowedTokens[token], "Token not allowed"); require(oracle != address(0), "Invalid oracle address"); - + priceOracles[token] = AggregatorV3Interface(oracle); emit PriceOracleSet(token, oracle); } - function withdraw(address token, uint256 amount) external { require(msg.sender == admin, "Only admin can withdraw"); if (token == address(0)) { diff --git a/src/QuestFactory.sol b/src/QuestFactory.sol index 4e4ad67..863f011 100644 --- a/src/QuestFactory.sol +++ b/src/QuestFactory.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import "./QuestDonation.sol"; +import "./QuestDonation.sol"; contract QuestFactory { address public admin; constructor() { - admin = msg.sender; // Set contract deployer as admin + admin = msg.sender; // Set contract deployer as admin } // Structure to store quest details @@ -22,22 +22,12 @@ contract QuestFactory { Quest[] public quests; // Event emitted when new quest is created - event QuestCreated( - address indexed questContract, - address indexed creator, - uint256 timestamp - ); + event QuestCreated(address indexed questContract, address indexed creator, uint256 timestamp); // Function to create new quest - function createQuest( - uint256 _targetAmount - ) external returns (address) { + function createQuest(uint256 _targetAmount) external returns (address) { // Deploy new QuestDonation contract - QuestDonation newQuest = new QuestDonation( - admin, - _targetAmount, - msg.sender - ); + QuestDonation newQuest = new QuestDonation(admin, _targetAmount, msg.sender); // Store quest details quests.push( @@ -50,11 +40,7 @@ contract QuestFactory { ); // Emit event - emit QuestCreated( - address(newQuest), - msg.sender, - block.timestamp - ); + emit QuestCreated(address(newQuest), msg.sender, block.timestamp); return address(newQuest); } @@ -65,19 +51,13 @@ contract QuestFactory { } // Get quest by index - function getQuestByIndex(uint256 _index) external view returns ( - address questContract, - uint256 targetAmount, - address creator, - uint256 timestamp - ) { + function getQuestByIndex(uint256 _index) + external + view + returns (address questContract, uint256 targetAmount, address creator, uint256 timestamp) + { require(_index < quests.length, "Quest index out of bounds"); Quest memory quest = quests[_index]; - return ( - quest.questContract, - quest.targetAmount, - quest.creator, - quest.timestamp - ); + return (quest.questContract, quest.targetAmount, quest.creator, quest.timestamp); } } diff --git a/test/QuestDonation.t.sol b/test/QuestDonation.t.sol index 8f66836..92b9f0b 100644 --- a/test/QuestDonation.t.sol +++ b/test/QuestDonation.t.sol @@ -8,7 +8,6 @@ import {MockERC20} from "./mocks/MockERC20.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - contract QuestDonationTest is Test { QuestDonation public questDonation; MockV3Aggregator public mockPriceFeedETH; @@ -18,7 +17,7 @@ contract QuestDonationTest is Test { address public donor1; address public donor2; address public questReceiver; - + // ETH price of $2000 int256 constant INITIAL_ETH_PRICE = 2000 * 1e8; int256 constant INITIAL_USDC_PRICE = 1 * 1e8; @@ -31,17 +30,17 @@ contract QuestDonationTest is Test { donor1 = makeAddr("donor1"); donor2 = makeAddr("donor2"); questReceiver = makeAddr("questReceiver"); - + // Deploy and initialize mock price feed mockPriceFeedETH = new MockV3Aggregator(8, INITIAL_ETH_PRICE); mockPriceFeedUSDC = new MockV3Aggregator(8, INITIAL_USDC_PRICE); - + // Deploy mock USDC token mockUSDC = new MockERC20("Mock USDC", "USDC", 6); - + // Deploy QuestDonation contract with mock params questDonation = new QuestDonation(owner, targetAmount, owner); - + // Allow ETH, USDC and set oracle questDonation.allowToken(address(0), true); // Replace address(0) with the actual token address if needed questDonation.setPriceOracle(address(0), address(mockPriceFeedETH)); // Assuming setPriceOracle is a function in QuestDonation @@ -52,7 +51,7 @@ contract QuestDonationTest is Test { // Fund test addresses with ETH vm.deal(donor1, 10 ether); vm.deal(donor2, 10 ether); - + // Fund donor1 with mock USDC vm.prank(owner); mockUSDC.mint(donor1, 1000 * 1e6); @@ -64,11 +63,11 @@ contract QuestDonationTest is Test { function testDonation() public { uint256 donationAmount = 1 ether; - + // Test donation from donor1 vm.prank(donor1); questDonation.donateETH{value: donationAmount}(); - + // Assert donation was recorded correctly assertEq(address(questDonation).balance, donationAmount); } @@ -76,30 +75,30 @@ contract QuestDonationTest is Test { function testMultipleDonations() public { uint256 donation1 = 1 ether; uint256 donation2 = 2 ether; - + // First donation vm.prank(donor1); questDonation.donateETH{value: donation1}(); - + // Second donation vm.prank(donor2); questDonation.donateETH{value: donation2}(); - + // Assert total donations assertEq(address(questDonation).balance, donation1 + donation2); } function testWithdrawal() public { uint256 donationAmount = 1 ether; - + // Make donation vm.prank(donor1); questDonation.donateETH{value: donationAmount}(); - + // Withdraw as owner vm.prank(owner); questDonation.withdraw(address(0), donationAmount); - + // Assert withdrawal was successful assertEq(address(questDonation).balance, 0); } @@ -118,28 +117,28 @@ contract QuestDonationTest is Test { function testDonationWithUSDC() public { uint256 donationAmount = 500 * 1e6; // 1000 USDC - + // Simulate USDC transfer to QuestDonation contract vm.prank(donor1); // mockUSDC.approve(address(questDonation), donationAmount); questDonation.donateERC20(address(mockUSDC), donationAmount); - + // Assert donation was recorded correctly assertEq(IERC20(mockUSDC).balanceOf(address(questDonation)), donationAmount); } function testWithdrawalWithUSDC() public { uint256 donationAmount = 200 * 1e6; - + // Simulate USDC transfer to QuestDonation contract vm.prank(donor1); // mockUSDC.approve(address(questDonation), donationAmount); questDonation.donateERC20(address(mockUSDC), donationAmount); - + // Withdraw as owner vm.prank(owner); questDonation.withdraw(address(mockUSDC), donationAmount); - + // Assert withdrawal was successful assertEq(mockUSDC.balanceOf(address(questDonation)), 0); } diff --git a/test/mocks/MockERC20.sol b/test/mocks/MockERC20.sol index 6358b83..2ff6d6d 100644 --- a/test/mocks/MockERC20.sol +++ b/test/mocks/MockERC20.sol @@ -11,4 +11,4 @@ contract MockERC20 is ERC20 { function mint(address to, uint256 amount) external { _mint(to, amount); } -} \ No newline at end of file +} diff --git a/test/mocks/MockV3Aggregator.sol b/test/mocks/MockV3Aggregator.sol index a6371e0..d2ddfd1 100644 --- a/test/mocks/MockV3Aggregator.sol +++ b/test/mocks/MockV3Aggregator.sol @@ -21,20 +21,8 @@ contract MockV3Aggregator { function latestRoundData() external view - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) { - return ( - uint80(latestRound), - latestAnswer, - latestTimestamp, - latestTimestamp, - uint80(latestRound) - ); + return (uint80(latestRound), latestAnswer, latestTimestamp, latestTimestamp, uint80(latestRound)); } -} \ No newline at end of file +}