Contract Name:
LightFundsRegistry
Contract Source Code:
File 1 of 1 : LightFundsRegistry
pragma solidity ^0.4.13;
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
assert(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure 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 pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
contract ReentrancyGuard {
/**
* @dev We use a single lock for the whole contract.
*/
bool private rentrancy_lock = false;
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* @notice If you mark a function `nonReentrant`, you should also
* mark it `external`. Calling one nonReentrant function from
* another is not supported. Instead, you can implement a
* `private` function doing the actual work, and a `external`
* wrapper marked as `nonReentrant`.
*/
modifier nonReentrant() {
require(!rentrancy_lock);
rentrancy_lock = true;
_;
rentrancy_lock = false;
}
}
contract ArgumentsChecker {
/// @dev check which prevents short address attack
modifier payloadSizeIs(uint size) {
require(msg.data.length == size + 4 /* function selector */);
_;
}
/// @dev check that address is valid
modifier validAddress(address addr) {
require(addr != address(0));
_;
}
}
contract Ownable {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Ownable() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0));
OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
contract LightFundsRegistry is ArgumentsChecker, Ownable, ReentrancyGuard {
using SafeMath for uint256;
enum State {
// gathering funds
GATHERING,
// returning funds to investors
REFUNDING,
// funds sent to owners
SUCCEEDED
}
event StateChanged(State _state);
event Invested(address indexed investor, uint256 amount);
event EtherSent(address indexed to, uint value);
event RefundSent(address indexed to, uint value);
modifier requiresState(State _state) {
require(m_state == _state);
_;
}
// PUBLIC interface
function LightFundsRegistry(address owner80, address owner20)
public
validAddress(owner80)
validAddress(owner20)
{
m_owner80 = owner80;
m_owner20 = owner20;
}
/// @dev performs only allowed state transitions
function changeState(State _newState)
external
onlyOwner
{
assert(m_state != _newState);
if (State.GATHERING == m_state) { assert(State.REFUNDING == _newState || State.SUCCEEDED == _newState); }
else assert(false);
m_state = _newState;
StateChanged(m_state);
if (State.SUCCEEDED == _newState) {
uint _80percent = this.balance.mul(80).div(100);
m_owner80.transfer(_80percent);
EtherSent(m_owner80, _80percent);
uint _20percent = this.balance;
m_owner20.transfer(_20percent);
EtherSent(m_owner20, _20percent);
}
}
/// @dev records an investment
function invested(address _investor)
external
payable
onlyOwner
requiresState(State.GATHERING)
{
uint256 amount = msg.value;
require(0 != amount);
// register investor
if (0 == m_weiBalances[_investor])
m_investors.push(_investor);
// register payment
totalInvested = totalInvested.add(amount);
m_weiBalances[_investor] = m_weiBalances[_investor].add(amount);
Invested(_investor, amount);
}
/// @notice withdraw accumulated balance, called by payee in case crowdsale has failed
function withdrawPayments(address payee)
external
nonReentrant
onlyOwner
requiresState(State.REFUNDING)
{
uint256 payment = m_weiBalances[payee];
require(payment != 0);
require(this.balance >= payment);
totalInvested = totalInvested.sub(payment);
m_weiBalances[payee] = 0;
payee.transfer(payment);
RefundSent(payee, payment);
}
function getInvestorsCount() external view returns (uint) { return m_investors.length; }
// FIELDS
/// @notice total amount of investments in wei
uint256 public totalInvested;
/// @notice state of the registry
State public m_state = State.GATHERING;
/// @dev balances of investors in wei
mapping(address => uint256) public m_weiBalances;
/// @dev list of unique investors
address[] public m_investors;
address public m_owner80;
address public m_owner20;
}