-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathCampaign.sol
183 lines (154 loc) · 3.94 KB
/
Campaign.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
pragma solidity ^0.4.18;
import "./math/SafeMath.sol";
import "./traits/Ownable.sol";
import "./referral/TieredPayoff.sol";
import "./referral/Referral.sol";
import "./Share.sol";
/**
* A {Campaign} represents an advertising campaign.
*/
contract Campaign is Ownable {
using SafeMath for uint;
using Referral for Referral.Tree;
using TieredPayoff for Referral.Tree;
/// The referral tree (k-ary tree)
Referral.Tree vyralTree;
/// Token in use
Share public token;
/// Budget of the campaign
uint public budget;
/// Tokens spent
uint public cost;
/*
* Modifiers
*/
modifier onlyNonZeroAddress(address _a) {
require(_a != 0);
_;
}
modifier onlyNonSelfReferral(address _referrer, address _invitee) {
require(_referrer != _invitee);
_;
}
modifier onlyOnReferral(address _invitee) {
require(getReferrer(_invitee) != 0x0);
_;
}
modifier onlyIfFundsAvailable() {
require(getAvailableBalance() >= 0);
_;
}
/*
* Events
*/
/// A new campaign was created
event LogCampaignCreated(address campaign);
/// Reward allocated
event LogRewardAllocated(address referrer, uint inviteeShares, uint referralReward);
/**
* Create a new campaign.
*/
function Campaign(
address _token,
uint256 _budgetAmount
)
public
{
token = Share(_token);
budget = _budgetAmount;
}
/**
* @dev Accept invitation and join contract. If referrer address is non-zero,
* calculate reward and transfer tokens to referrer. Referrer address will be
* zero if referrer is not found in the referral tree. Don't throw in such a
* scenario.
*/
function join(
address _referrer,
address _invitee,
uint _shares
)
public
onlyOwner
onlyNonZeroAddress(_invitee)
onlyNonSelfReferral(_referrer, _invitee)
onlyIfFundsAvailable()
returns(uint reward)
{
Referral.Node memory referrerNode = vyralTree.nodes[_referrer];
// Referrer was not found, add referrer as a new node
if(referrerNode.exists == false) {
vyralTree.addInvitee(owner, _referrer, 0);
}
// Add invitee to the tree
vyralTree.addInvitee(_referrer, _invitee, _shares);
// Calculate referrer's reward
reward = vyralTree.payoff(_referrer);
// Log event
LogRewardAllocated(_referrer, _shares, reward);
}
/**
* VyralSale (owner) transfers rewards on behalf of this contract.
*/
function sendReward(address _who, uint _amount)
onlyOwner //(ie, VyralSale)
external returns (bool)
{
if(getAvailableBalance() >= _amount) {
token.transferReward(_who, _amount);
cost = cost.add(_amount);
return true;
} else {
return false;
}
}
/**
* Return referral key of caller.
*/
function getReferrer(
address _invitee
)
public
constant
returns (address _referrer)
{
_referrer = vyralTree.getReferrer(_invitee);
}
/**
* @dev Returns the size of the Referral Tree.
*/
function getTreeSize()
public
constant
returns (uint _size)
{
_size = vyralTree.getTreeSize();
}
/**
* @dev Returns the budget as a tuple, (token address, amount)
*/
function getBudget()
public
constant
returns (address _token, uint _amount)
{
_token = token;
_amount = budget;
}
/**
* @dev Return (budget - cost)
*/
function getAvailableBalance()
public
constant
returns (uint _balance)
{
_balance = (budget - cost);
}
/**
* Fallback. Don't send ETH to a campaign.
*/
function() public {
revert();
}
}