-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStyx.sol
More file actions
107 lines (90 loc) · 3.54 KB
/
Styx.sol
File metadata and controls
107 lines (90 loc) · 3.54 KB
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
pragma solidity ^0.4.19;
/*
Maximum evil version of the Hellhole scheme. Has the following modifications:
- No minimum contribution.
- 10% of the pool is awarded to the last 100 bidders equally.
- The remainder is distributed among the investors who gave the last 10% of the pot's total wealth.
- Their distribution is proportional to the amount they gave.
- (UNIMPLEMENTED) Every ether also returns up to 1000 ethers on any investment they've held in the past.
-For example, if you invested 1000 ether and give 1 ether in the last 10%, you will receive 1000 ether back before getting your share of the pot.
- The time extension is based on an exponentially weighted moving average of the time interval between bids.
- It has a minimum of 15 minutes.
*/
contract Styx {
//Absolute end time for the contract, after which winners can collect payout.
uint public end_time;
//Total pot kept by the contract.
uint public pot = 0;
//Initialization
function Styx() public payable {
end_time = now + 24 hours;
//Summon Moloch with a sacrifice of money
pot += msg.value;
}
//Book keeping for payouts
struct Sacrifice {
address sender;
uint amount;
uint potSize;
bool paid;
}
Sacrifice[] sacrifices;
//Insert money here
function sacrifice() public payable {
require(now <= end_time);
uint new_end_time = now + time_extension();
if(new_end_time > end_time){
end_time = new_end_time;
}
pot += msg.value;
sacrifices.push(Sacrifice({
sender: msg.sender,
amount: msg.value,
potSize: pot,
paid: false
}));
}
//Track and calculate time extension
//An exponentially weighted moving average of time between sacrifices (in seconds)
uint public interval_moving_average = 1 hours;
//The timestamp of the last payment
uint public last_pay_time = now;
function time_extension() private returns (uint) {
//Update the moving average estimate
uint memory_portion = interval_moving_average * 19 / 20;
uint new_portion = (now - last_pay_time) * 1 / 20;
interval_moving_average = memory_portion + new_portion;
last_pay_time = now;
//Calculate the time extension period.
uint period = interval_moving_average * 30;
if(period < 15 minutes){
return 15 minutes;
} else {
return period;
}
}
//Withdrawals!
function withdraw(uint sacrificeIndex) public {
require(now > end_time);
require(sacrificeIndex >= 0);
require(sacrificeIndex < sacrifices.length);
Sacrifice storage withdrawal = sacrifices[sacrificeIndex];
require(withdrawal.sender == msg.sender);
require(withdrawal.paid == false);
withdrawal.paid = true;
uint last100Payout = 0;
if(sacrifices.length - sacrificeIndex < 100){
uint last100Pot = pot * 1 / 10;
last100Payout += last100Pot * 1 / 100;
}
uint last10Percent = pot * 1 / 10;
uint last10PercentPayout = 0;
if(withdrawal.potSize > pot - last10Percent){
uint last10PercentPot = pot * 9 / 10;
uint payoutPerWei = last10PercentPot / last10Percent;
last10PercentPayout = withdrawal.amount * payoutPerWei;
}
uint winnings = last100Payout + last10PercentPayout;
msg.sender.transfer(winnings);
}
}