Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrating #7

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0647251
On-chainVoting
FurkanSezal Oct 24, 2022
eb9e262
uptaded erc20
FurkanSezal Oct 26, 2022
9c4aed1
Add tests
FurkanSezal Oct 28, 2022
64bd7d7
add tests v1.1
FurkanSezal Oct 28, 2022
c6f35b2
add test v1.1
FurkanSezal Oct 28, 2022
7b0be87
Add tests v1.2
FurkanSezal Oct 28, 2022
15038d9
Add submit
FurkanSezal Oct 31, 2022
6220217
Funding contract
FurkanSezal Nov 4, 2022
db68871
Funding Contract
FurkanSezal Nov 4, 2022
a7a4d7f
Fixed submit_and_propose and testing
FurkanSezal Nov 5, 2022
ea4432c
add more test
FurkanSezal Nov 6, 2022
a658f31
Add more testing before chainlink keepers
FurkanSezal Nov 6, 2022
74473f4
fix test
FurkanSezal Nov 7, 2022
15bd11e
Add chainlink automation without testing.
FurkanSezal Nov 8, 2022
b38e711
Add chainlink automation without testing V2.
FurkanSezal Nov 8, 2022
9aa568a
Add chainlink automation without testing V3.
FurkanSezal Nov 8, 2022
0a4c984
Add chainlink automation without testing V3.
FurkanSezal Nov 8, 2022
eb6206b
Add chainlink automation without testing V4.
FurkanSezal Nov 8, 2022
5ee5a40
Add chainlink automation Fix big bug. Add tests V1
FurkanSezal Nov 10, 2022
b400b6d
Add chainlink automation Fix big bug. Add tests V2
FurkanSezal Nov 10, 2022
1e4c63e
Add chainlink automation Fix big bug. Add tests V3
FurkanSezal Nov 10, 2022
b2981e4
Add chainlink automation Fix big bug. Add tests V4
FurkanSezal Nov 10, 2022
35bdfab
Fix bugs update code v1.
FurkanSezal Nov 13, 2022
82cfbdb
Fix bugs update code v2
FurkanSezal Nov 13, 2022
54c2dcb
deployed mumbai testnet
FurkanSezal Nov 17, 2022
505a2f9
deployed mumbai testnet v2
FurkanSezal Nov 17, 2022
fd54f69
deployed mumbai testnet v2
FurkanSezal Nov 18, 2022
327bbd8
deployed mumbai testnet v3
FurkanSezal Nov 18, 2022
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
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,12 @@
artifacts
cache
node_modules
propose.js
queue-and-execute.js
submit.js
05-deploy-fundProject.js
readOnlyMe.md
coverage
deployments
queue-and-execute.js
propose.js
23 changes: 0 additions & 23 deletions contracts/Box.sol

This file was deleted.

283 changes: 283 additions & 0 deletions contracts/FundProject.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@chainlink/contracts/src/v0.8/AutomationCompatible.sol";
import "hardhat/console.sol";

error FundProject__NotApporovedByDao();
error FundProject__UpkeepNeeded();
error FundProject__TransferFailed(uint256 _projectId);
error FundProject__NotEnoughPayment();
error FundProject__withdrawFund();
error FundProject__WithdrawTransferFailed();
error FundProject__EnteranceFeeNeeded();

contract FundProject is Ownable, AutomationCompatibleInterface {
enum ProjectFundingStatus {
ONPROGRESS,
SUCCESS,
FAILED,
CANCELED
}

uint256 public projectId = 1;

uint public lastTimeStamp;
uint256 public daoPercentage;
uint256 public enteranceFee;

mapping(uint256 => bool) public _isFunding;
mapping(uint256 => mapping(uint256 => uint256)) public projectToTime; // projectId => projectFundingTime => timestamp of add
mapping(uint256 => uint256) public time;

mapping(string => uint256) public hashToProjectId;
mapping(uint256 => string) public idToHash;
mapping(uint256 => mapping(address => uint256)) public funders; // projectId => funderAddress => funderBalance
mapping(uint256 => uint256) public projectFunds;
mapping(uint256 => uint256) public projectFundingGoalAmount;
mapping(uint256 => bool) public _isApporovedByDao;
mapping(uint256 => address) public projectOwnerAddress;
mapping(uint256 => ProjectFundingStatus) public _ProjectFundingStatus;
mapping(address => bool) public _isEnteranceFeePaid;
mapping(address => uint256[]) public investedProjects; // investor address => investedProjects
mapping(uint256 => address) public projectOwnerAddressIndex;

event projectSuccessfullyFunded(uint256 indexed _projectId);
event projectFundingFailed(uint256 indexed _projectId);
event enteranceFeePaid(address indexed _projectOwner);
event projectGoesToFunding(uint256 indexed _projectId);
event withdrawFundSuccessfully(
address indexed __investor,
uint256 indexed __projectId
);

modifier isApporovedByDao(uint256 _projecID) {
if (!_isApporovedByDao[_projecID])
revert FundProject__NotApporovedByDao();
_;
}

constructor(uint256 _enteranceFee, uint256 _daoPercentage) {
lastTimeStamp = block.timestamp;
daoPercentage = _daoPercentage;
enteranceFee = _enteranceFee;
}

function fund(uint256 _projecID)
public
payable
isApporovedByDao(_projecID)
{
funders[_projecID][msg.sender] += msg.value;
projectFunds[_projecID] += msg.value;
investedProjects[msg.sender] = [_projecID]; // need testing
}

function apporoveFundingByDao(
string memory _ipfsHash,
uint256 _fundingGoalAmount,
uint256 _time,
uint256 _projectOwnerAddressIndex
) external onlyOwner {
// only dao can call it
if (
!_isEnteranceFeePaid[
projectOwnerAddressIndex[_projectOwnerAddressIndex]
]
) {
revert FundProject__EnteranceFeeNeeded();
} else {
projectToTime[projectId][_time] = block.timestamp;
_ProjectFundingStatus[projectId] = ProjectFundingStatus.ONPROGRESS;
time[projectId] = _time;
projectFundingGoalAmount[projectId] = _fundingGoalAmount;
hashToProjectId[_ipfsHash] = projectId;
idToHash[projectId] = _ipfsHash;
projectOwnerAddress[projectId] = projectOwnerAddressIndex[
_projectOwnerAddressIndex
];
_isApporovedByDao[projectId] = true;
_isFunding[projectId] = true;
emit projectGoesToFunding(projectId);
projectId++;
}
}

function cancelApporovelFundingByDao(uint256 _projecID) external onlyOwner {
// only dao can call it
_isApporovedByDao[_projecID] = false;
_isFunding[_projecID] = false;
_ProjectFundingStatus[_projecID] = ProjectFundingStatus.CANCELED;
}

function checkUpkeep(
bytes memory /* checkData */
)
public
view
override
returns (bool upkeepNeeded, bytes memory performData)
{
for (uint projectIndex = 1; projectIndex <= projectId; projectIndex++) {
if (_isFunding[projectIndex]) {
bool timePassed = (block.timestamp -
(projectToTime[projectIndex][time[projectIndex]])) >
time[projectIndex];
upkeepNeeded = (timePassed);
if (upkeepNeeded) {
performData = abi.encodePacked(projectIndex);
break;
}
}
}
}

function performUpkeep(bytes calldata performData) external override {
(bool upkeepNeeded, ) = checkUpkeep("");
if (!upkeepNeeded) {
revert FundProject__UpkeepNeeded();
}

uint256 ProjectId = uint256(bytes32(performData));
_isFunding[ProjectId] = false;
_isApporovedByDao[ProjectId] = false;

if (projectFunds[ProjectId] > projectFundingGoalAmount[ProjectId]) {
_ProjectFundingStatus[ProjectId] = ProjectFundingStatus.SUCCESS;
uint256 fundsToSent = (projectFunds[ProjectId] *
(100 - daoPercentage)) / 100;
projectFunds[ProjectId] = 0;
(bool success, ) = (projectOwnerAddress[ProjectId]).call{
value: fundsToSent
}("");
if (!success) {
revert FundProject__TransferFailed(projectFunds[ProjectId]);
}

emit projectSuccessfullyFunded(ProjectId);
} else {
_ProjectFundingStatus[ProjectId] = ProjectFundingStatus.FAILED;
emit projectFundingFailed(ProjectId);
}
}

function paySubmitFee() public payable {
if (msg.value < enteranceFee) {
revert FundProject__NotEnoughPayment();
} else {
_isEnteranceFeePaid[msg.sender] = true;
projectOwnerAddressIndex[projectId] = msg.sender;
emit enteranceFeePaid(msg.sender);
}
}

function withdrawFund(uint256 _projectID) public {
if (_ProjectFundingStatus[_projectID] == ProjectFundingStatus.FAILED) {
uint256 fundToSent = funders[_projectID][msg.sender];
funders[_projectID][msg.sender] = 0;
(bool success, ) = (payable(msg.sender)).call{value: fundToSent}(
""
);
if (!success) {
revert FundProject__WithdrawTransferFailed();
}
emit withdrawFundSuccessfully(msg.sender, projectId);
} else {
revert FundProject__withdrawFund();
}
}

function _isApporoveFundingByDao(uint256 _projecID)
external
view
returns (bool)
{
return _isApporovedByDao[_projecID];
}

function _getHashOfProjectData(uint256 _projecID)
public
view
returns (string memory)
{
return idToHash[_projecID];
}

function _getProjectId(string memory _ipfsHash)
public
view
returns (uint256)
{
return hashToProjectId[_ipfsHash];
}

function _getBalanceOfProject(uint256 _projecID)
public
view
returns (uint256)
{
return projectFunds[_projecID];
}

function _getFundingGoalAmount(uint256 _projecID)
public
view
returns (uint256)
{
return projectFundingGoalAmount[_projecID];
}

function is_funding(uint256 _projectID) public view returns (bool) {
return _isFunding[_projectID];
}

function _getProjectStatus(uint256 _projectID)
public
view
returns (ProjectFundingStatus)
{
return _ProjectFundingStatus[_projectID];
}

function getEnteranceFee() public view returns (uint256) {
return enteranceFee;
}

function isEnteranceFeePaid(address account) public view returns (bool) {
return _isEnteranceFeePaid[account];
}

function getFunderBalance(uint256 _projectID)
public
view
returns (uint256)
{
return funders[_projectID][msg.sender];
}

function getInvestedProjects(address investor)
public
view
returns (uint256[] memory)
{
return investedProjects[investor]; // need testing
}

function getDaoPercentage() public view returns (uint256) {
return daoPercentage;
}

function getTimeleft(uint256 _projectID)
public
view
returns (uint256 a, uint256 b)
{
a = block.timestamp - projectToTime[_projectID][time[_projectID]];
b = time[_projectID];
}

function getCurrentProjectId() public view returns (uint256) {
return projectId;
}
}
32 changes: 26 additions & 6 deletions contracts/GovernanceToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,22 @@
pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract GovernanceToken is ERC20Votes {
uint256 public s_maxSupply = 1000000000000000000000000;
contract GovernanceToken is ERC20Votes, Ownable {
uint256 public s_initialSupply = 1000000e18;

event TokenTransfer(
address indexed _from,
address indexed _to,
uint256 _amount
);

constructor()
ERC20("GovernanceToken", "GT")
ERC20Permit("GovernanceToken")
ERC20("QuickfundDAOToken", "QFD")
ERC20Permit("QuickfundDAOToken")
{
_mint(msg.sender, s_maxSupply);
_mint(msg.sender, s_initialSupply);
}

function _afterTokenTransfer(
Expand All @@ -19,12 +26,25 @@ contract GovernanceToken is ERC20Votes {
uint256 amount
) internal override(ERC20Votes) {
super._afterTokenTransfer(from, to, amount);
emit TokenTransfer(from, to, amount);
}

function _mint(address to, uint256 amount) internal override(ERC20Votes) {
function _mint(address to, uint256 amount)
internal
override(ERC20Votes)
onlyOwner
{
super._mint(to, amount);
}

function mintToken(address to, uint256 amount) external {
_mint(to, amount);
}

function burnToken(address account, uint256 amount) external {
_burn(account, amount);
}

function _burn(address account, uint256 amount)
internal
override(ERC20Votes)
Expand Down
Loading