pragma solidity ^0.4.12;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
function mul(uint256 a, uint256 b) internal constant returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
assert(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal constant returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint256 a, uint256 b) internal constant returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
pragma solidity ^0.4.12;
import './safeMath.sol';
contract ColdStaking {
using SafeMath for uint256;
event StartStaking(address addr, uint256 value, uint256 weight, uint256 init_block);
event WithdrawStake(address staker, uint256 weight);
event Claim(address staker, uint256 reward);
event FirstStakeDonation(address _address, uint256 value);
/*struct Staker
// Commented out due to error in solidity compiler
{
uint256 weight;
uint256 init_block;
}*/
uint256 public staking_pool;
uint256 public staking_threshold = 0 ether;
//uint256 public round_interval = 172800; // approx. 1 month in blocks
//uint256 public max_delay = 172800 * 12; // approx. 1 year in blocks
/// TESTING VALUES
uint256 public round_interval = 200; // approx. 1 month in blocks
uint256 public max_delay = 7 * 6000; // approx. 1 year in blocks
mapping(address => uint256) staker_weight;
mapping(address => uint256) staker_init_block;
mapping(address => bool) private muted;
function() public payable
{
// No donations accepted to fallback!
// Consider value deposit is an attempt to become staker.
start_staking();
}
function start_staking() public payable
{
assert(msg.value >= staking_threshold);
staking_pool = staking_pool.add(msg.value);
staker_weight[msg.sender] = staker_weight[msg.sender].add(msg.value);
staker_init_block[msg.sender] = block.number;
/*StartStaking(
msg.sender,
msg.value,
staker[msg.sender].weight,
staker[msg.sender].init_block
);*/
}
function First_Stake_donation() public payable {
FirstStakeDonation(msg.sender, msg.value);
}
function claim_and_withdraw() public
{
claim();
withdraw_stake();
}
function withdraw_stake() public only_staker mutex(msg.sender)
{
msg.sender.transfer(staker[msg.sender].weight);
staking_pool = staking_pool.sub(staker_weight[msg.sender]);
staker_weight[msg.sender] = staker_weight[msg.sender].sub(staker_weight[msg.sender]);
WithdrawStake(msg.sender, staker_weight[msg.sender]);
}
function claim() public only_staker mutex(msg.sender)
{
require(block.number >= staker_init_block[msg.sender].add(round_interval));
uint256 _reward = stake_reward(msg.sender);
msg.sender.transfer(_reward);
staker_init_block[msg.sender] = block.number;
Claim(msg.sender, _reward);
}
function stake_reward(address _addr) public constant returns (uint256 _reward)
{
return (reward() * stakerTimeStake(_addr) * stakerWeightStake(_addr));
}
function stakerTimeStake(address _addr) public constant returns (uint256 _time)
{
return ((block.number - staker_init_block[_addr]) / round_interval);
//return 1;
}
function stakerWeightStake(address _addr) public constant returns (uint256 _stake)
{
return (staker_weight[_addr] / (staking_pool + staker_weight[_addr] * (stakerTimeStake(_addr) - 1)));
//return 0;
}
function report_abuse(address _addr) public only_staker mutex(_addr)
{
assert(staker[_addr].weight > 0);
assert(block.number > staker_init_block[_addr].add(max_delay));
_addr.transfer(staker_weight[msg.sender]);
staker_weight[_addr] = 0;
}
function reward() public constant returns (uint256)
{
return address(this).balance.sub(staking_pool);
}
modifier only_staker
{
assert(staker_weight[msg.sender] > 0);
_;
}
modifier mutex(address _target)
{
if (muted[_target])
{
revert();
}
muted[_target] = true;
_;
muted[_target] = false;
}
////////////// DEBUGGING /////////////////////////////////////////////////////////////
function test() public constant returns (string)
{
return "success!";
}
function infoOfStaker(address _addr) constant returns (uint256 weight, uint256 init, uint256 stake_time, uint256 _reward)
{
if (staker[_addr].init_block == 0)
{
return (staker_weight[_addr],staker_init_block[_addr],0,stake_reward(_addr));
}
return (staker_weight[_addr],staker_init_block[_addr],block.number - staker_init_block[_addr],stake_reward(_addr));
}
function info_WEIGHT(address _addr) constant returns (uint256)
{
return staker_weight[_addr];
}
function info_INIT(address _addr) constant returns (uint256)
{
return staker[_addr].init_block;
}
}
Internal exception in StandardCompiler::compileInternal: /src/libsolidity/ast/ASTJsonConverter.cpp(791): Throw in function string dev::solidity::ASTJsonConverter::functionCallKind(dev::solidity::FunctionCallKind)
Dynamic exception type: N5boost16exception_detail10clone_implIN3dev8solidity21InternalCompilerErrorEEE
std::exception::what: std::exception
[PN3dev11tag_commentE] = Unknown kind of function call .