# KickStarter
The contract represents a traditional KickStarter campaign. One is allowed to contribute ethereum to the campaign, and can become the lead contributor by beating the initial donation. Each campaign has a target amount, and once it is reached, no one can withdraw their donations. If the campaign has still not reached its target amount, only certain people can initiate withdrawal. (check withdraw function)
One thing to note here is the interesting way the KickStarter is set up: if anyone initiates withdrawal, every contributor receives their donation back!
You will beat this level if you are able to prevent everyone from withdrawing their money, even the owner!
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;
contract KickStarter {
address payable public lead_contributor;
address payable public owner;
uint public highest_contribution;
uint public target_amount;
uint public current_amount;
bool public fulfilled;
struct Contribution {
address contributor;
uint256 amount;
}
Contribution[] public contributions;
constructor() payable {
owner = payable(msg.sender);
lead_contributor = payable(msg.sender);
highest_contribution = msg.value;
target_amount = 10000;
fulfilled = false;
current_amount = 0;
}
function contribute() external payable {
require(!isContract(msg.sender), "Only EOAs allowed to contribute!!");
current_amount += msg.value;
if (current_amount >= target_amount) {
fulfilled = true;
}
if (msg.value > highest_contribution) {
lead_contributor = payable(msg.sender);
highest_contribution = msg.value;
}
Contribution memory c = Contribution(msg.sender, msg.value);
contributions.push(c);
}
function withdraw() external {
require(lead_contributor == msg.sender || lead_contributor == owner, "Only lead contributor/owner can initiate withdraw");
require(!fulfilled, "withdrawal only when target amount not reached");
for (uint i = 0; i < contributions.length; i++) {
payable(contributions[i].contributor).transfer(contributions[i].amount);
current_amount -= contributions[i].amount;
}
delete contributions;
}
function isContract(address _account) internal view returns(bool) {
uint256 size;
assembly {
size := extcodesize(_account)
}
return size > 0;
}
}