Skip to content

Commit 80893ad

Browse files
authored
Merge pull request #10 from energywebfoundation/feat/reward_contract
Blockreward contracts
2 parents aa46493 + 795057c commit 80893ad

File tree

13 files changed

+1406
-396
lines changed

13 files changed

+1406
-396
lines changed

.solcover.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
module.exports = {
2-
skipFiles: ['interfaces','libs']
2+
skipFiles: ['interfaces','libs', 'misc/Ownable.sol'],
3+
compileCommand: 'npx truffle compile',
4+
testCommand: 'npx truffle test --network coverage'
35
}

contracts/reward/BlockReward.sol

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
pragma solidity ^0.5.4;
2+
3+
import "../interfaces/IBlockReward.sol";
4+
import "./SCurveProvider.sol";
5+
6+
import "../libs/SafeMath.sol";
7+
8+
9+
/// @title Block reward contract
10+
/// @notice Performs payouts at each new created block. Block authors
11+
/// are rewarded according to an S-curve, while there is a constant payout for
12+
/// a community fund for a certain period of time.
13+
/// @dev Contract is used by the Parity client and its address is
14+
/// specified in the chainspec
15+
contract BlockReward is SCurveProvider, IBlockReward {
16+
using SafeMath for uint256;
17+
18+
// storage variables for logging reward statistics
19+
uint256 public mintedTotally;
20+
uint256 public mintedForCommunity;
21+
mapping(address => uint256) public mintedForCommunityForAccount;
22+
mapping(address => uint256) public mintedForAccount;
23+
mapping(uint256 => uint256) public mintedInBlock;
24+
mapping(address => mapping(uint256 => uint256)) public mintedForAccountInBlock;
25+
26+
// solhint-disable var-name-mixedcase
27+
/// Parity client SYSTEM_ADDRESS: 2^160 - 2
28+
/// This is a constant, but changed only for tests
29+
address internal SYSTEM_ADDRESS = 0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE;
30+
/// The constant amount that gets sent to the
31+
/// community fund with each new block
32+
uint256 public communityFundAmount;
33+
/// Address of the community fund. Preferably a multisig wallet
34+
address public communityFund;
35+
/// Mapping of addresses and their payout addresses where rewards are minted
36+
mapping(address => address) public payoutAddresses;
37+
/// Stores reward amounts
38+
mapping(bytes32 => uint256) private uintStorage;
39+
// solhint-enable var-name-mixedcase
40+
41+
constructor(address _communityFundAddress, uint256 _communityFundAmount)
42+
public
43+
{
44+
communityFund = _communityFundAddress;
45+
communityFundAmount = _communityFundAmount;
46+
}
47+
48+
/// @notice Sets community fund address. Ideally
49+
/// it is a multisig wallet address
50+
/// @param _newFund New community fund address
51+
function setCommunityFund(address _newFund)
52+
external
53+
{
54+
require(
55+
msg.sender == communityFund,
56+
"Caller is not the community fund"
57+
);
58+
communityFund = _newFund;
59+
}
60+
61+
/// @notice Sets payout address. Every sender can only set its own
62+
/// payout address. The contract only rewards block authors, but it
63+
/// is not checking who sets an address for itself. The community fund
64+
/// can set a payout address too, if desired.
65+
/// @param _newPayoutAddress The payout address belonging to the sender
66+
function setPayoutAddress(address _newPayoutAddress)
67+
external
68+
{
69+
payoutAddresses[msg.sender] = _newPayoutAddress;
70+
}
71+
72+
/// @notice Resets the payout address. If a payout address is reseted/not set,
73+
/// the minted amounts get sent to the original one. The sender resets its own
74+
/// payout address
75+
function resetPayoutAddress()
76+
external
77+
{
78+
delete payoutAddresses[msg.sender];
79+
}
80+
81+
/// @notice The function that is called by the client to issue rewards at a new block. The rewards are
82+
/// minted: the balances of the corresponing addresses are simply increased with the amount
83+
/// @dev It is a service transaction invoked by system, which doesn't cost anyhting but still can
84+
/// modify state. Cannot emit events.
85+
/// @param benefactors List of addresses that can be rewarded
86+
/// @param kind List of type codes belonging to the benefactors. They determine the category
87+
/// an address belongs to. 0 is for block authors which we are only interested in
88+
/// @return List of addreses to be rewarded, and list of corresponding reward amounts in wei
89+
function reward(address[] calldata benefactors, uint16[] calldata kind)
90+
external
91+
returns (address[] memory, uint256[] memory)
92+
{
93+
require(msg.sender == SYSTEM_ADDRESS, "Caller is not the system");
94+
require(benefactors.length == kind.length, "Benefactors/types list length differs");
95+
require(benefactors.length == 1, "Benefactors list length is not 1");
96+
require(kind[0] == 0, "Benefactor is not the block author");
97+
98+
if (benefactors[0] == address(0) || _checkRewardPeriodEnded(block.number)) {
99+
return (new address[](0), new uint256[](0));
100+
}
101+
102+
address[] memory receivers = new address[](2);
103+
uint256[] memory rewards = new uint256[](receivers.length);
104+
105+
receivers[0] = _getPayoutAddress(benefactors[0]);
106+
rewards[0] = getBlockReward(block.number);
107+
108+
receivers[1] = _getPayoutAddress(communityFund);
109+
rewards[1] = communityFundAmount;
110+
111+
_logMinted(receivers[0], rewards[0]);
112+
_logCommunityMinted(receivers[1], rewards[1]);
113+
114+
return (receivers, rewards);
115+
}
116+
117+
/// @dev Retrieves the payout address of an account if there is any. If not specified
118+
/// or resetted, returns the original account
119+
/// @param _somebody An account address we retrieve the payout address for
120+
/// @return The payout address
121+
function _getPayoutAddress(address _somebody)
122+
private
123+
view
124+
returns (address)
125+
{
126+
address _payoutAddress = payoutAddresses[_somebody];
127+
if (_payoutAddress == address(0)) {
128+
return _somebody;
129+
}
130+
return _payoutAddress;
131+
}
132+
133+
/// @dev Logs a community-mint event. Calls `_logMinted` after setting the
134+
/// community specific metrics
135+
/// @param _account The account address where the tokens are minted
136+
/// @param _amount The minted amount in wei
137+
function _logCommunityMinted(address _account, uint256 _amount)
138+
private
139+
{
140+
mintedForCommunity = mintedForCommunity.add(_amount);
141+
142+
mintedForCommunityForAccount[_account] = mintedForCommunityForAccount[_account].add(_amount);
143+
144+
_logMinted(_account, _amount);
145+
}
146+
147+
/// @dev Logs a mint event, and stores related metrics (counters).
148+
/// @param _account The account address where the tokens are minted
149+
/// @param _amount The minted amount in wei
150+
function _logMinted(address _account, uint256 _amount)
151+
private
152+
{
153+
mintedForAccountInBlock[_account][block.number] = mintedForAccountInBlock[_account][block.number].add(_amount);
154+
155+
mintedForAccount[_account] = mintedForAccount[_account].add(_amount);
156+
157+
mintedInBlock[block.number] = mintedInBlock[block.number].add(_amount);
158+
159+
mintedTotally = mintedTotally.add(_amount);
160+
}
161+
}

contracts/reward/RewardFoo.sol

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
pragma solidity ^0.5.4;
2+
3+
4+
/// @title S Curve Reward provider
5+
/// @notice Provides the appropriate block author rewards
6+
/// based on points of a discrete, inverse S curve
7+
contract SCurveProvider {
8+
9+
/// Discrete points of the curve
10+
uint256[] public sCurve;
11+
/// Discrete step size
12+
uint256 public blockStepSize;
13+
/// End of the reward period (both block- and community reward)
14+
/// expressed in block number
15+
uint256 public rewardPeriodEnd;
16+
17+
constructor()
18+
public
19+
{
20+
_initCurve();
21+
}
22+
23+
/// @notice Returns the block reward amount based on the block number
24+
/// and points of the S curve
25+
/// @param _currentBlock The block number to calculate the reward to
26+
/// @return The block reward amount in wei
27+
function getBlockReward(uint256 _currentBlock)
28+
public
29+
view
30+
returns (uint256)
31+
{
32+
if (_checkRewardPeriodEnded(_currentBlock)) {
33+
return 0;
34+
}
35+
return sCurve[_currentBlock / blockStepSize];
36+
}
37+
38+
/// @notice Checks whether the reward period is over or not (block and community)
39+
/// @return True if the reward period has ended, false otherwise
40+
function checkRewardPeriodEnded()
41+
public
42+
view
43+
returns (bool)
44+
{
45+
return _checkRewardPeriodEnded(block.number);
46+
}
47+
48+
/// @notice Checks whether the block reward period is over or not
49+
/// @param _currentBlock The block number to check on
50+
/// @return True if the block reward period has ended, false otherwise
51+
function _checkRewardPeriodEnded(uint256 _currentBlock)
52+
internal
53+
view
54+
returns (bool)
55+
{
56+
return (_currentBlock >= rewardPeriodEnd);
57+
}
58+
59+
// solhint-disable function-max-lines
60+
/// @dev Inits the S curve. Values are hardcoded,
61+
/// everyhting is calculated beforehand
62+
function _initCurve()
63+
private
64+
{
65+
sCurve = [
66+
uint256(304418979390926464),
67+
304418979390926464,
68+
304418979390926464,
69+
304418979390926464,
70+
304418979390926464,
71+
304418979390926464,
72+
304418979390926464,
73+
304369560376526464,
74+
304221303333326464,
75+
303974208261326464,
76+
303628275160526464,
77+
303183504030926464,
78+
302639894872526464,
79+
301997447685326464,
80+
301256162469326464,
81+
300416039224526464,
82+
299477077950926464,
83+
298439278648526464,
84+
297302641317326464,
85+
296067165957326464,
86+
294732852568526464,
87+
293299701150926464,
88+
291767711704526464,
89+
290136884229326464,
90+
288407218725326464,
91+
286578715192526464,
92+
284651373630926464,
93+
282625194040526464,
94+
280500176421326464,
95+
278276320773326464,
96+
275953627096526464,
97+
273532095390926464,
98+
271011725656526464,
99+
268392517893326464,
100+
265674472101326464,
101+
262857588280526464,
102+
259941866430926464,
103+
256927306552526464,
104+
253813908645326464,
105+
250601672709326464,
106+
247290598744526464,
107+
243880686750926464,
108+
240371936728526464,
109+
236764348677326464,
110+
233057922597326464,
111+
229252658488526464,
112+
225348556350926464,
113+
221345616184526464,
114+
217243837989326464,
115+
213043221765326464,
116+
208743767512526464,
117+
204345475230926464,
118+
199848344920526464,
119+
195252376581326464,
120+
190557570213326464,
121+
185763925816526464,
122+
180871443390926464,
123+
175880122936526464,
124+
170789964453326464,
125+
165600967941326464,
126+
160117606656000000,
127+
154824830213760000,
128+
149621007997440000,
129+
144506140007040000,
130+
139480226242560000,
131+
134543266704000000,
132+
129695261391360000,
133+
124936210304640000,
134+
120266113443840000,
135+
115684970808960000,
136+
111192782400000000,
137+
106789548216960000,
138+
102475268259840000,
139+
98249942528640000,
140+
94113571023360000,
141+
90066153744000000,
142+
86107690690560000,
143+
82238181863040000,
144+
78457627261440000,
145+
74766026885760000,
146+
71163380736000000,
147+
67649688812160000,
148+
64224951114240000,
149+
60889167642240000,
150+
57642338396160000,
151+
54484463376000000,
152+
51415542581760000,
153+
48435576013440000,
154+
45544563671040000,
155+
42742505554560000,
156+
40029401664000000,
157+
37405251999360000,
158+
34870056560640000,
159+
32423815347840000,
160+
30066528360960000,
161+
27798195600000000,
162+
25618817064960000,
163+
23528392755840000,
164+
21526922672640000,
165+
19614406815360000,
166+
17790845184000000,
167+
16056237778560000,
168+
14410584599040000,
169+
12853885645440000,
170+
11386140917760000,
171+
10007350416000000,
172+
8717514140160000,
173+
7516632090240000,
174+
6404704266240000,
175+
5381730668160000,
176+
4447711296000000,
177+
3602646149760000,
178+
2846535229440000,
179+
2179378535040000,
180+
1601176066560000,
181+
1111927824000000,
182+
711633807360000,
183+
400294016640000,
184+
177908451840000,
185+
44477112960000
186+
];
187+
// roughly 1 month with a 5 sec step size
188+
blockStepSize = 525600;
189+
//roughly 10 years with a 5 sec step size
190+
rewardPeriodEnd = blockStepSize * sCurve.length;
191+
}
192+
// solhint-enable function-max-lines
193+
}

0 commit comments

Comments
 (0)