95 lines
2.4 KiB
Solidity
95 lines
2.4 KiB
Solidity
// 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;
|
|
}
|
|
}
|