-
Notifications
You must be signed in to change notification settings - Fork 0
/
Crowdfund.sol
232 lines (186 loc) · 7.46 KB
/
Crowdfund.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
/// @title GameVault Token (GMV)
/// @dev ERC20 token with 18 decimals, burnable functionality, and a fixed total supply of 10 million tokens.
contract GameVaultToken is ERC20, ERC20Burnable {
uint256 public constant TOTAL_SUPPLY = 10_000_000 * 10 ** 18;
/// @notice Constructor for GameVault Token (GMV)
/// @dev Mints the total supply of tokens to the deployer's address.
constructor() ERC20("GameVault Token", "GMV") {
_mint(msg.sender, TOTAL_SUPPLY);
}
}
struct GoFund {
uint id_;
string title;
string description;
uint256 fundingGoal;
address owner;
uint startTime;
uint256 durationTime;
bool isActive;
uint256 fundingBalance;
address[] contributors;
bytes32[] proposals;
mapping(bytes32 => uint256) proposalVotes;
}
struct Contributors {
address contributor;
uint balance;
uint time;
}
contract Gamefund {
GameVaultToken gameVaultToken; // Address of gameVault Token
uint public id;
uint public num = 5;
uint public denum = 100; // uint256 public conversionRate = (points * 5 ) / 100; // Points to token Conversion (1 point = 0.005 token)
address admin = 0xfed257209796EeC486f2A1c0AF1B330857E463c4;
mapping(uint => GoFund) public funder;
mapping(address => mapping(uint => Contributors)) public contributors_;
mapping(uint => mapping(address => uint)) public contribute;
mapping(uint => mapping(address => bool)) public hasContributed;
mapping(uint => mapping(address => uint256)) public votingPower;
uint[] public activeCampaignsIds;
error InsufficientInput();
error NotActive();
error NotActiveCause();
error ExceededFundingGoal();
error NotInDuration();
error NotOwner();
error TimeNotReached();
error InvalidProposal();
error NoVotingPower();
event CreateGofundme(
uint id,
string _title,
uint256 _fundingGoal,
uint256 _durationTime
);
event ContributeEth(
uint indexed _ID,
uint _fundingBalance,
address contributor,
uint amount
);
event GetContributedFunds(uint indexed _ID, bool isActive);
event ProposalCreated(uint indexed _ID, bytes32 proposal);
event VoteCast(uint indexed _ID, bytes32 proposal, uint256 votingPower);
event TokensTransferred(address indexed recipient, uint256 points, uint256 tokenAmount);
modifier onlyOwner() {
require(msg.sender == admin, "Only contract creator");
_;
}
constructor(address _gameVaultToken) {
gameVaultToken = GameVaultToken(_gameVaultToken);
}
function createGofundme(
address creator,
string memory _title,
string memory _description,
uint256 _fundingGoal,
uint256 _durationTime
) external returns (uint _id) {
id++;
_id = id;
GoFund storage newFund = funder[_id];
newFund.id_ = _id;
newFund.title = _title;
newFund.description = _description;
newFund.fundingGoal = _fundingGoal;
newFund.owner = creator;
newFund.startTime = block.timestamp;
newFund.durationTime = _durationTime + block.timestamp;
newFund.isActive = true;
// push to the active campaign
activeCampaignsIds.push(_id);
emit CreateGofundme(_id, _title, _fundingGoal, _durationTime);
}
function contributeEth(uint _ID) external payable {
if (msg.value <= 0.001 ether) revert InsufficientInput();
GoFund storage fund = funder[_ID];
if (!fund.isActive) revert NotActive();
if (fund.fundingBalance + msg.value > fund.fundingGoal)
revert ExceededFundingGoal();
if (block.timestamp > fund.durationTime) revert NotInDuration();
Contributors storage contributorInfo = contributors_[msg.sender][_ID];
contributorInfo.time = block.timestamp;
fund.fundingBalance += msg.value;
contribute[_ID][msg.sender] += msg.value;
if (!hasContributed[_ID][msg.sender]) {
fund.contributors.push(msg.sender);
hasContributed[_ID][msg.sender] = true;
}
// Calculate voting power
uint256 totalRaised = fund.fundingBalance;
uint256 contribution = contribute[_ID][msg.sender];
votingPower[_ID][msg.sender] = (totalRaised * 10) / contribution;
emit ContributeEth(_ID, fund.fundingBalance, msg.sender, msg.value);
}
function createProposal(uint _ID, bytes32 proposal) external {
GoFund storage fund = funder[_ID];
if (msg.sender != fund.owner) revert NotOwner();
fund.proposals.push(proposal);
emit ProposalCreated(_ID, proposal);
}
function voteOnProposal(uint _ID, bytes32 proposal) external {
GoFund storage fund = funder[_ID];
if (votingPower[_ID][msg.sender] == 0) revert NoVotingPower();
bool validProposal = false;
for (uint i = 0; i < fund.proposals.length; i++) {
if (fund.proposals[i] == proposal) {
validProposal = true;
break;
}
}
if (!validProposal) revert InvalidProposal();
// Cast vote based on voting power
fund.proposalVotes[proposal] += votingPower[_ID][msg.sender];
emit VoteCast(_ID, proposal, votingPower[_ID][msg.sender]);
}
function getContributedFunds(uint _ID) external {
GoFund storage fund = funder[_ID];
if (!fund.isActive) revert NotActiveCause();
if (msg.sender != fund.owner) revert NotOwner();
if (fund.durationTime > block.timestamp) revert TimeNotReached();
uint _bal = fund.fundingBalance;
fund.fundingBalance = 0;
fund.isActive = false;
payable(fund.owner).transfer(_bal);
emit GetContributedFunds(_ID, false);
}
function getContributors(uint _ID) external view returns (Contributors[] memory _contributors) {
GoFund storage fund = funder[_ID];
uint total = fund.contributors.length;
_contributors = new Contributors[](total);
for (uint i = 0; i < total; i++) {
address contributor = fund.contributors[i];
uint amount = contribute[_ID][contributor];
uint time = contributors_[contributor][_ID].time;
_contributors[i] = Contributors(contributor, amount, time);
}
}
function getAllCampaignsCount() external view returns (uint) {
return id;
}
function getCampaigns() external view returns (uint[] memory) {
return activeCampaignsIds;
}
function getStatus(uint _ID) external view returns (bool) {
return funder[_ID].isActive;
}
function convertPointandTransfer(address player, uint points) external onlyOwner {
require (points > 20, "Points must be greater than zero");
// calculate the token amount based on the conversion rate
uint256 conversionRate = (points * num) / denum;
// setting the token amount to the conversion rate
uint256 tokenAmount = conversionRate;
// Transfer the calculated token amount based on the conversion rate
require(gameVaultToken.transfer(player, tokenAmount), "Token Transfer failed");
emit TokensTransferred(player, points, tokenAmount);
}
function updateNum(uint256 newNum) external onlyOwner {
num = newNum;
}
}