-
Notifications
You must be signed in to change notification settings - Fork 4
/
crowdfund.rb
131 lines (102 loc) · 4.28 KB
/
crowdfund.rb
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
# SPDX-License-Identifier: public domain
class CrowdFund < Contract
event :Launch, id: UInt,
creator: Address, # indexed
goal: UInt,
startAt: Timestamp,
endAt: Timestamp
event :Cancel, id: UInt
event :Pledge, id: UInt, # indexed,
caller: Address, # indexed
amount: UInt
event :Unpledge, id: UInt, # indexed
caller: Address, # indexed
amount: UInt
event :Claim, id: UInt
event :Refund, id: UInt,
caller: Address, # indexed
amount: UInt
struct :Campaign, creator: Address, # Creator of campaign
goal: UInt, # Amount of tokens to raise
pledged: UInt, # Total amount pledged
startAt: Timestamp, # Timestamp of start of campaign
endAt: Timestamp, # Timestamp of end of campaign
claimed: Bool # True if goal was reached and creator has claimed the tokens
storage token: Address, # IERC20 immutable
count: UInt, # Total count of campaigns created. It is also used to generate id for new campaigns.
campaigns: mapping( UInt, Campaign ), # Mapping from id to Campaign
pledgedAmount: mapping( UInt, mapping( Address, UInt )) # Mapping from campaign id => pledger => amount pledged
sig [Address]
def constructor( token: )
@token = token
end
sig [UInt, Timestamp, Timestamp]
def launch( goal:, startAt:, endAt: )
assert startAt >= block.timestamp, "start at < now"
assert endAt >= startAt, "end at < start at"
assert endAt <= block.timestamp + 90.days, "end at > max duration"
@count += 1;
@campaigns[@count] = Campaign.new(
creator: msg.sender,
goal: goal,
pledged: 0,
startAt: startAt,
endAt: endAt,
claimed: false
)
log Launch, @count, msg.sender, goal, startAt, endAt
end
sig [UInt]
def cancel( id: )
campaign = @campaigns[ id ]
assert campaign.creator == msg.sender, "not creator"
assert block.timestamp < campaign.startAt, "started"
campaigns.delete( id )
log Cancel, id
end
sig [UInt, UInt]
def pledge( id:, amount: )
campaign = @campaigns[ id ]
assert block.timestamp >= campaign.startAt, "not started"
assert block.timestamp <= campaign.endAt, "ended"
campaign.pledged += amount
@pledgedAmount[id][msg.sender] += amount
IERC20(@token).transferFrom( msg.sender, address(this), amount)
log Pledge, id, msg.sender, amount
end
sig [UInt, UInt]
def unpledge( id:, amount: )
campaign = @campaigns[ id]
assert block.timestamp <= campaign.endAt, "ended"
campaign.pledged -= amount
@pledgedAmount[id][msg.sender] -= amount
IERC20(@token).transfer( msg.sender, amount )
log Unpledge, id, msg.sender, amount
end
sig [UInt]
def claim( id: )
campaign = @campaigns[ id ]
assert campaign.creator == msg.sender, "not creator"
assert block.timestamp > campaign.endAt, "not ended"
assert campaign.pledged >= campaign.goal, "pledged < goal"
assert !campaign.claimed, "claimed"
campaign.claimed = true;
IERC20(token).transfer( campaign.creator, campaign.pledged )
log Claim, id
end
sig [UInt]
def refund( id: )
campaign = @campaigns[ id ]
assert block.timestamp > campaign.endAt, "not ended"
assert campaign.pledged < campaign.goal, "pledged >= goal"
bal = @pledgedAmount[id][msg.sender]
@pledgedAmount[id][msg.sender] = 0
IERC20(token).transfer( msg.sender, bal )
log Refund, id, msg.sender, bal
end
end
__END__
interface IERC20 {
function transfer(address, uint) external returns (bool);
function transferFrom(address, address, uint) external returns (bool);
}