文件 1 的 1:FinPro.sol
pragma solidity ^0.4.24;
library SafeMath {
function add(uint256 _a, uint256 _b) internal pure returns (uint256) {
uint256 c = _a + _b;
assert(c >= _a);
return c;
}
function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
assert(_a >= _b);
return _a - _b;
}
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) {
return _a / _b;
}
}
contract Ownable {
address public owner;
constructor() public {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
function setOwner(address _owner) onlyOwner public {
owner = _owner;
}
}
interface ERC20Token {
function name() external view returns (string _name);
function symbol() external view returns (string _symbol);
function decimals() external view returns (uint8 _decimals);
function totalSupply() external view returns (uint256 _totalSupply);
function balanceOf(address _owner) external view returns (uint256 _balance);
function transfer(address _to, uint256 _value) external returns (bool _success);
function transferFrom(address _from, address _to, uint256 _value) external returns (bool _success);
function approve(address _spender, uint256 _value) external returns (bool _success);
function allowance(address _owner, address _spender) external view returns (uint256 _remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
contract FinPro is Ownable {
using SafeMath for uint256;
string private constant name = "FinPro";
string private constant version = "v0.96";
uint256[] private fplowerlim;
uint256[] private fplocktime;
uint256[] private fpinterest;
uint256 private fpcount;
ERC20Token private token;
struct investedData {
uint256 fpnum;
uint256 buytime;
uint256 unlocktime;
uint256 value;
bool withdrawn;
}
mapping (address => uint256) private investedAmount;
mapping (address => mapping (uint256 => investedData)) private investorVault;
address[] public admins;
mapping (address => bool) public isAdmin;
mapping (address => mapping (uint256 => mapping (address => mapping (address => bool)))) public adminWithdraw;
mapping (address => mapping (uint256 => mapping (address => bool))) public adminTokenWithdraw;
event FPBought(address _buyer, uint256 _amount, uint256 _investednum,
uint256 _fpnum, uint256 _buytime, uint256 _unlocktime, uint256 _interestrate);
event FPWithdrawn(address _investor, uint256 _amount, uint256 _investednum, uint256 _fpnum);
event FPWithdrawnByAdmins(address indexed _addr, uint256 _amount, address indexed _investor, uint256 _investednum, uint256 _fpnum);
event TokenWithdrawnByAdmins(address indexed _addr, uint256 _amount);
event WrongTokenEmptied(address indexed _token, address indexed _addr, uint256 _amount);
event WrongEtherEmptied(address indexed _addr, uint256 _amount);
constructor (address _tokenAddress, uint256[] _fplowerlim, uint256[] _fplocktime, uint256[] _fpinterest, address[] _admins) public {
require(_fplowerlim.length == _fplocktime.length && _fplocktime.length == _fpinterest.length && _fpinterest.length > 0);
fplowerlim = _fplowerlim;
fplocktime = _fplocktime;
fpinterest = _fpinterest;
fpcount = fplowerlim.length;
token = ERC20Token(_tokenAddress);
admins = _admins;
for (uint256 i = 0; i < admins.length; i++) {
isAdmin[admins[i]] = true;
}
}
modifier onlyAdmin() {
require(isAdmin[msg.sender]);
_;
}
function tokenInfo() public view returns (address _tokenAddress, uint8 _decimals,
string _name, string _symbol, uint256 _tokenBalance) {
return (address(token), token.decimals(), token.name(), token.symbol(), token.balanceOf(address(this)));
}
function showFPCount() public view returns (uint256) {
return fplowerlim.length;
}
function showFPLowerlim() public view returns (uint256[]) {
return fplowerlim;
}
function showFPLocktime() public view returns (uint256[]) {
return fplocktime;
}
function showFPInterest() public view returns (uint256[]) {
return fpinterest;
}
function showFPInfoAll() public view returns (uint256[] _fplowerlim, uint256[] _fplocktime, uint256[] _fpinterest) {
return (fplowerlim, fplocktime, fpinterest);
}
function showInvestedNum(address _addr) public view returns (uint256) {
return investedAmount[_addr];
}
function showInvestorVault(address _addr, uint256 _investednum) public view
returns (uint256 _fpnum, uint256 _buytime, uint256 _unlocktime, uint256 _value, bool _withdrawn, bool _withdrawable) {
require(_investednum > 0 && investedAmount[_addr] >= _investednum);
return (investorVault[_addr][_investednum].fpnum, investorVault[_addr][_investednum].buytime,
investorVault[_addr][_investednum].unlocktime, investorVault[_addr][_investednum].value,
investorVault[_addr][_investednum].withdrawn,
(now > investorVault[_addr][_investednum].unlocktime && !investorVault[_addr][_investednum].withdrawn));
}
function showInvestorVaultFull(address _addr) external view
returns (uint256[] _fpnum, uint256[] _buytime, uint256[] _unlocktime, uint256[] _value,
uint256[] _interestrate, bool[] _withdrawn, bool[] _withdrawable) {
require(investedAmount[_addr] > 0);
_fpnum = new uint256[](investedAmount[_addr]);
_buytime = new uint256[](investedAmount[_addr]);
_unlocktime = new uint256[](investedAmount[_addr]);
_value = new uint256[](investedAmount[_addr]);
_interestrate = new uint256[](investedAmount[_addr]);
_withdrawn = new bool[](investedAmount[_addr]);
_withdrawable = new bool[](investedAmount[_addr]);
for(uint256 i = 0; i < investedAmount[_addr]; i++) {
(_fpnum[i], _buytime[i], _unlocktime[i], _value[i], _withdrawn[i], _withdrawable[i]) = showInvestorVault(_addr, i + 1);
_interestrate[i] = fpinterest[_fpnum[i]];
}
return (_fpnum, _buytime, _unlocktime, _value, _interestrate, _withdrawn, _withdrawable);
}
function buyfp(uint256 _fpnum, uint256 _amount) public {
require(_fpnum < fpcount);
require(_amount >= fplowerlim[_fpnum]);
require(token.transferFrom(msg.sender, address(this), _amount));
investedAmount[msg.sender]++;
investorVault[msg.sender][investedAmount[msg.sender]] = investedData({fpnum: _fpnum, buytime: now,
unlocktime: now.add(fplocktime[_fpnum]), value: _amount, withdrawn: false});
emit FPBought(msg.sender, _amount, investedAmount[msg.sender], _fpnum, now, now.add(fplocktime[_fpnum]), fpinterest[_fpnum]);
}
function withdraw(uint256 _investednum) public {
require(_investednum > 0 && investedAmount[msg.sender] >= _investednum);
require(!investorVault[msg.sender][_investednum].withdrawn);
require(now > investorVault[msg.sender][_investednum].unlocktime);
require(token.balanceOf(address(this)) >= investorVault[msg.sender][_investednum].value);
require(token.transfer(msg.sender, investorVault[msg.sender][_investednum].value));
investorVault[msg.sender][_investednum].withdrawn = true;
emit FPWithdrawn(msg.sender, investorVault[msg.sender][_investednum].value,
_investednum, investorVault[msg.sender][_investednum].fpnum);
}
function withdrawByAdmin(address _investor, uint256 _investednum, address _target) onlyAdmin public {
require(_investednum > 0 && investedAmount[_investor] >= _investednum);
require(!investorVault[_investor][_investednum].withdrawn);
require(token.balanceOf(address(this)) >= investorVault[_investor][_investednum].value);
adminWithdraw[_investor][_investednum][_target][msg.sender] = true;
for (uint256 i = 0; i < admins.length; i++) {
if (!adminWithdraw[_investor][_investednum][_target][admins[i]]) {
return;
}
}
require(token.transfer(_target, investorVault[_investor][_investednum].value));
investorVault[_investor][_investednum].withdrawn = true;
emit FPWithdrawnByAdmins(_target, investorVault[_investor][_investednum].value, _investor,
_investednum, investorVault[_investor][_investednum].fpnum);
}
function withdrawTokenByAdmin(address _target, uint256 _amount) onlyAdmin public {
adminTokenWithdraw[_target][_amount][msg.sender] = true;
uint256 i;
for (i = 0; i < admins.length; i++) {
if (!adminTokenWithdraw[_target][_amount][admins[i]]) {
return;
}
}
for (i = 0; i < admins.length; i++) {
adminTokenWithdraw[_target][_amount][admins[i]] = false;
}
require(token.transfer(_target, _amount));
emit TokenWithdrawnByAdmins(_target, _amount);
}
function () public payable {
revert();
}
function emptyWrongToken(address _addr) onlyOwner public {
require(_addr != address(token));
ERC20Token wrongToken = ERC20Token(_addr);
uint256 amount = wrongToken.balanceOf(address(this));
require(amount > 0);
require(wrongToken.transfer(msg.sender, amount));
emit WrongTokenEmptied(_addr, msg.sender, amount);
}
function emptyWrongEther() onlyOwner public {
uint256 amount = address(this).balance;
require(amount > 0);
msg.sender.transfer(amount);
emit WrongEtherEmptied(msg.sender, amount);
}
}