// SPDX-License-Identifier: MIT pragma solidity 0.8.20; // Do not change the solidity version as it negatively impacts submission grading import "hardhat/console.sol"; import "./FundingRecipient.sol"; contract CrowdFund { ///////////////// /// Errors ////// ///////////////// // Errors go here... error NotOpenToWithdraw(); error WithdrawTransferFailed(address to, uint256 amount); error TooEarly(uint256 deadline, uint256 currentTimestamp); error AlreadyCompleted(); ////////////////////// /// State Variables // ////////////////////// FundingRecipient public fundingRecipient; mapping(address => uint256) public balances; bool public openToWithdraw; uint256 public deadline = block.timestamp + 2 hours; uint256 public constant threshold = 1 ether; //////////////// /// Events ///// //////////////// // Events go here... event Contribution(address, uint256); /////////////////// /// Modifiers ///// /////////////////// modifier notCompleted() { _; if (block.timestamp >= deadline) revert AlreadyCompleted(); } /////////////////// /// Constructor /// /////////////////// constructor(address fundingRecipientAddress) { fundingRecipient = FundingRecipient(fundingRecipientAddress); } /////////////////// /// Functions ///// /////////////////// function contribute() public payable { balances[msg.sender] += msg.value; emit Contribution(msg.sender, msg.value); } function withdraw() public { if (!openToWithdraw) revert NotOpenToWithdraw(); uint256 amount = balances[msg.sender]; balances[msg.sender] = 0; (bool success,) = msg.sender.call{value: amount}(""); if (!success) revert WithdrawTransferFailed(msg.sender, amount); } function execute() public { if (block.timestamp < deadline) revert TooEarly(deadline, block.timestamp); uint256 balance = address(this).balance; if (balance >= threshold) { fundingRecipient.complete{value: balance}(); } else { openToWithdraw = true; } } receive() external payable { contribute(); } //////////////////////// /// View Functions ///// //////////////////////// function timeLeft() public view returns (uint256) { if (block.timestamp >= deadline) return 0; return deadline - block.timestamp; } }