文件 1 的 5:DSMath.sol
pragma solidity ^0.5.2;
contract DSMath {
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
assert((z = x + y) >= x);
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
assert((z = x - y) <= x);
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
assert((z = x * y) >= x);
}
function div(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = x / y;
}
function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
return x <= y ? x : y;
}
function max(uint256 x, uint256 y) internal pure returns (uint256 z) {
return x >= y ? x : y;
}
function hadd(uint128 x, uint128 y) internal pure returns (uint128 z) {
assert((z = x + y) >= x);
}
function hsub(uint128 x, uint128 y) internal pure returns (uint128 z) {
assert((z = x - y) <= x);
}
function hmul(uint128 x, uint128 y) internal pure returns (uint128 z) {
assert((z = x * y) >= x);
}
function hdiv(uint128 x, uint128 y) internal pure returns (uint128 z) {
z = x / y;
}
function hmin(uint128 x, uint128 y) internal pure returns (uint128 z) {
return x <= y ? x : y;
}
function hmax(uint128 x, uint128 y) internal pure returns (uint128 z) {
return x >= y ? x : y;
}
function imin(int256 x, int256 y) internal pure returns (int256 z) {
return x <= y ? x : y;
}
function imax(int256 x, int256 y) internal pure returns (int256 z) {
return x >= y ? x : y;
}
uint128 constant WAD = 10 ** 18;
function wadd(uint128 x, uint128 y) internal pure returns (uint128) {
return hadd(x, y);
}
function wsub(uint128 x, uint128 y) internal pure returns (uint128) {
return hsub(x, y);
}
function wmul(uint128 x, uint128 y) internal pure returns (uint128 z) {
z = cast((uint256(x) * y + WAD / 2) / WAD);
}
function wdiv(uint128 x, uint128 y) internal pure returns (uint128 z) {
z = cast((uint256(x) * WAD + y / 2) / y);
}
function wmin(uint128 x, uint128 y) internal pure returns (uint128) {
return hmin(x, y);
}
function wmax(uint128 x, uint128 y) internal pure returns (uint128) {
return hmax(x, y);
}
uint128 constant RAY = 10 ** 27;
function radd(uint128 x, uint128 y) internal pure returns (uint128) {
return hadd(x, y);
}
function rsub(uint128 x, uint128 y) internal pure returns (uint128) {
return hsub(x, y);
}
function rmul(uint128 x, uint128 y) internal pure returns (uint128 z) {
z = cast((uint256(x) * y + RAY / 2) / RAY);
}
function rdiv(uint128 x, uint128 y) internal pure returns (uint128 z) {
z = cast((uint256(x) * RAY + y / 2) / y);
}
function rpow(uint128 x, uint64 n) internal pure returns (uint128 z) {
z = n % 2 != 0 ? x : RAY;
for (n /= 2; n != 0; n /= 2) {
x = rmul(x, x);
if (n % 2 != 0) {
z = rmul(z, x);
}
}
}
function rmin(uint128 x, uint128 y) internal pure returns (uint128) {
return hmin(x, y);
}
function rmax(uint128 x, uint128 y) internal pure returns (uint128) {
return hmax(x, y);
}
function cast(uint256 x) internal pure returns (uint128 z) {
assert((z = uint128(x)) == x);
}
}
文件 2 的 5:DSTokenBase.sol
pragma solidity ^0.5.2;
import "./DSMath.sol";
import "./ERC20.sol";
contract DSTokenBase is ERC20, DSMath {
uint256 _supply;
mapping (address => uint256) _balances;
mapping (address => mapping (address => uint256)) _approvals;
constructor(uint supply) public {
_supply = supply;
}
function totalSupply() public view returns (uint) {
return _supply;
}
function balanceOf(address src) public view returns (uint) {
return _balances[src];
}
function allowance(address src, address guy) public view returns (uint) {
return _approvals[src][guy];
}
function transfer(address dst, uint wad) public returns (bool) {
return transferFrom(msg.sender, dst, wad);
}
function transferFrom(address src, address dst, uint wad)
public
returns (bool)
{
if (src != msg.sender) {
require(_approvals[src][msg.sender] >= wad, "ds-token-insufficient-approval");
_approvals[src][msg.sender] = sub(_approvals[src][msg.sender], wad);
}
require(_balances[src] >= wad, "ds-token-insufficient-balance");
_balances[src] = sub(_balances[src], wad);
_balances[dst] = add(_balances[dst], wad);
emit Transfer(src, dst, wad);
return true;
}
function approve(address guy, uint wad) public returns (bool) {
_approvals[msg.sender][guy] = wad;
emit Approval(msg.sender, guy, wad);
return true;
}
}
文件 3 的 5:ERC20.sol
pragma solidity ^0.5.2;
import "./DSMath.sol";
contract ERC20Events {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
}
contract ERC20 is ERC20Events {
function totalSupply() public view returns (uint);
function balanceOf(address guy) public view returns (uint);
function allowance(address src, address guy) public view returns (uint);
function approve(address guy, uint wad) public returns (bool);
function transfer(address dst, uint wad) public returns (bool);
function transferFrom(address src, address dst, uint wad) public returns (bool);
}
文件 4 的 5:Lottoshi.sol
pragma solidity ^0.5.2;
import "./DSTokenBase.sol";
import "./Ownable.sol";
interface ILottery {
function getAvailablePrize() external view returns (uint256);
}
contract Lottoshi is DSTokenBase(0), Ownable {
uint256 constant internal magnitude = 2 ** 64;
uint256 constant internal HOUSE_PERCENTAGE = 75;
uint256 constant internal REFERRAL_PERCENTAGE = 50;
uint256 constant internal FOMO_PERCENTAGE = 120;
uint256 constant internal PRIZE_LIMIT_TO_INVEST = 50000 ether;
uint256 constant internal MAX_SUPPLY = 500000 * (10 ** 6);
string constant public name = "Lottoshi";
string constant public symbol = "LTS";
uint256 constant public decimals = 6;
uint256 public profitPerShare;
uint256 public totalStakes;
address payable public lottery;
bool public decentralized;
mapping (address => uint256) public stakesOf;
mapping (address => uint256) public payout;
mapping (address => uint256) public dividends;
event Invest(address indexed user, uint256 ethAmount, uint256 tokenAmount, address referee);
event Stake(address indexed user, uint256 amount);
event Unstake(address indexed user, uint256 amount);
event Withdraw(address indexed user, uint256 amount);
constructor (address payable _lottery) public {
lottery = _lottery;
}
function () external {
}
function decentralize() external {
require(lottery == msg.sender, "invalid sender");
decentralized = true;
}
function contribute(address referral) external payable {
uint256 referralAmount;
if (referral != address(0)) {
referralAmount = msg.value * REFERRAL_PERCENTAGE / 300;
dividends[referral] += referralAmount;
}
uint256 houseAmount;
if (!decentralized) {
houseAmount = msg.value * HOUSE_PERCENTAGE / 300;
dividends[owner()] += houseAmount;
}
profitPerShare += (msg.value - houseAmount - referralAmount) * magnitude / totalStakes;
}
function invest(address referral) public payable {
uint256 prize = getPrize();
require(prize < PRIZE_LIMIT_TO_INVEST, "prize is enough");
uint256 fomoAmount;
if (totalStakes > 0) {
fomoAmount = msg.value * FOMO_PERCENTAGE / 1000;
profitPerShare += fomoAmount * magnitude / totalStakes;
}
lottery.transfer(msg.value - fomoAmount);
uint256 token1 = ethToTokens(prize);
uint256 token2 = ethToTokens(prize + msg.value);
uint256 tokenAmount = (token2 - token1) / 1000000000000;
uint256 referralAmount;
if (referral != address(0) && referral != msg.sender) {
referralAmount = tokenAmount / 20;
stakesOf[referral] += referralAmount;
payout[referral] += referralAmount * profitPerShare;
emit Invest(referral, 0, referralAmount, msg.sender);
emit Transfer(address(0), referral, referralAmount);
emit Transfer(referral, address(this), referralAmount);
emit Stake(referral, referralAmount);
}
uint256 totalAmount = referralAmount + tokenAmount;
require(_supply + totalAmount <= MAX_SUPPLY, "exceed max supply");
stakesOf[msg.sender] += tokenAmount;
payout[msg.sender] += tokenAmount * profitPerShare;
_supply += totalAmount;
totalStakes += totalAmount;
_balances[address(this)] += totalAmount;
emit Invest(msg.sender, msg.value, tokenAmount, address(0));
emit Transfer(address(0), msg.sender, tokenAmount);
emit Transfer(msg.sender, address(this), tokenAmount);
emit Stake(msg.sender, tokenAmount);
}
function stake(uint256 amount) external {
internalTransfer(msg.sender, address(this), amount);
stakesOf[msg.sender] += amount;
payout[msg.sender] += amount * profitPerShare;
totalStakes += amount;
emit Stake(msg.sender, amount);
}
function unstake(uint256 amount) external {
require(stakesOf[msg.sender] >= amount, "stakesOf not enough");
withdrawDividends(msg.sender);
payout[msg.sender] -= amount * profitPerShare;
stakesOf[msg.sender] -= amount;
totalStakes -= amount;
emit Unstake(msg.sender, amount);
internalTransfer(address(this), msg.sender, amount);
}
function withdrawDividends() public {
withdrawDividends(msg.sender);
}
function withdrawDividends(address payable user) internal {
uint256 dividend = dividendOf(user);
if (dividend > 0) {
uint256 dividend2 = dividends[user];
payout[user] += (dividend - dividend2) * magnitude;
if (dividend2 > 0) {
dividends[user] = 0;
}
user.transfer(dividend);
emit Withdraw(user, dividend);
}
}
function dividendOf(address user) public view returns (uint256) {
return (profitPerShare * stakesOf[user] - payout[user]) / magnitude + dividends[user];
}
function ethToTokens(uint256 eth) internal pure returns (uint256) {
return (sqrt(10000800016000000000000000000000000000000000000 + 4000000000000000000000000 * eth) - 100004000000000000000000) >> 1;
}
function sqrt(uint256 x) internal pure returns (uint256 y) {
uint256 z = (x + 1) >> 1;
y = x;
while (z < y) {
y = z;
z = (x / z + z) >> 1;
}
}
function getPrize() internal view returns (uint256) {
return ILottery(lottery).getAvailablePrize();
}
function internalTransfer(address src, address dst, uint wad) internal {
require(_balances[src] >= wad, "ds-token-insufficient-balance");
_balances[src] = sub(_balances[src], wad);
_balances[dst] = add(_balances[dst], wad);
emit Transfer(src, dst, wad);
}
}
文件 5 的 5:Ownable.sol
pragma solidity ^0.5.2;
contract Context {
constructor () internal { }
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this;
return msg.data;
}
}
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
{
"compilationTarget": {
"Lottoshi.sol": "Lottoshi"
},
"evmVersion": "byzantium",
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"constant":false,"inputs":[{"name":"referral","type":"address"}],"name":"invest","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"payout","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"unstake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"withdrawDividends","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"stakesOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decentralized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"dividends","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"src","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"referral","type":"address"}],"name":"contribute","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"decentralize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"profitPerShare","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"user","type":"address"}],"name":"dividendOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"stake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"lottery","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalStakes","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"src","type":"address"},{"name":"guy","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_lottery","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":false,"stateMutability":"nonpayable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":false,"name":"ethAmount","type":"uint256"},{"indexed":false,"name":"tokenAmount","type":"uint256"},{"indexed":false,"name":"referee","type":"address"}],"name":"Invest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Unstake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]