Skip to content

Instantly share code, notes, and snippets.

@crypto-perry
Created October 4, 2019 09:21
Show Gist options
  • Save crypto-perry/466ac35e592b369cd54ab10462abc241 to your computer and use it in GitHub Desktop.
Save crypto-perry/466ac35e592b369cd54ab10462abc241 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.5.11+commit.c082d0b4.js&optimize=false&gist=
pragma solidity >=0.5.0;
interface IERC20 {
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
require(c >= a);
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
if (a == 0) {
return 0;
}
c = a * b;
require(c / a == b);
return c;
}
}
contract ERC20OpenBuy {
using SafeMath for uint256;
event UpdateBuy(address maker, address token, uint256 ethPerToken, uint256 expiration, uint256 amountRemaining);
address public owner;
uint256 public feesGathered;
mapping (uint256 => uint256) public trades;
modifier onlyOwner {
require(msg.sender == owner);
_;
}
constructor() public {
owner = msg.sender;
}
function addToBuyOffer(address token, uint256 ethPerToken, uint256 expiration) public payable {
uint256 tradeId = uint256(keccak256(abi.encodePacked(msg.sender, token, ethPerToken, expiration)));
trades[tradeId] = trades[tradeId].add((msg.value.mul(1000) - 5) / 1000);
emit UpdateBuy(msg.sender, token, ethPerToken, expiration, trades[tradeId]); // Log open BUY
}
function partialFillBuy(address token, uint256 ethPerToken, uint256 expiration, uint256 tokenAmount, address payable other) public {
uint256 tradeId = uint256(keccak256(abi.encodePacked(other, token, ethPerToken, expiration)));
uint256 ethPayment = tokenAmount.mul(ethPerToken);
require(trades[tradeId] >= ethPayment); // Make sure there is enough ether to pay for these tokens
trades[tradeId] = trades[tradeId] - ethPayment;
require(IERC20(token).transferFrom(msg.sender, other, tokenAmount)); // Take tokens from seller and give to buyer
uint256 fee = computeFee(ethPayment);
msg.sender.transfer(ethPayment - fee);
feesGathered = feesGathered.add(fee).add(fee);
emit UpdateBuy(other, token, ethPerToken, expiration, trades[tradeId]); // Log open BUY
}
function cancelBuyOffer(address token, uint256 ethPerToken, uint256 expiration) public {
uint256 tradeId = uint256(keccak256(abi.encodePacked(msg.sender, token, ethPerToken, expiration)));
uint256 ethAmount = trades[tradeId];
trades[tradeId] = 0;
msg.sender.transfer(ethAmount + computeFee(ethAmount)); // Refund eth + fee to buyer
emit UpdateBuy(msg.sender, token, ethPerToken, expiration, 0); // Log open BUY
}
function _withdrawFees() public onlyOwner {
uint256 amount = feesGathered;
feesGathered = 0;
msg.sender.transfer(amount);
}
function computeFee(uint256 value) private pure returns (uint256) {
return value.mul(5) / 1000; // this is the fee we take on each side (0.5%)
}
function tradeInfo(address token, uint256 ethPerToken, uint256 expiration, uint256 tokenAmount, address payable other) public view
returns (uint256 _tradeId, uint256 _buySideTotal, uint256 _amountRemaining) {
_buySideTotal = tokenAmount.mul(ethPerToken);
_buySideTotal = _buySideTotal.add(computeFee(_buySideTotal));
address payable maker = other == address(0x0) ? msg.sender : other;
_tradeId = uint256(keccak256(abi.encodePacked(maker, token, ethPerToken, expiration)));
return (_tradeId, _buySideTotal, trades[_tradeId]);
}
function() external payable {
revert();
}
}
contract ERC20OpenSell {
using SafeMath for uint256;
event UpdateSell(address maker, address token, uint256 ethPerToken, uint256 expiration, uint256 amountRemaining);
address public owner;
address public allowedSpender;
uint256 public feesGathered;
mapping (uint256 => uint256) public trades;
modifier onlyOwner {
require(msg.sender == owner);
_;
}
constructor() public {
owner = msg.sender;
}
function addToSellOffer(address token, uint256 ethPerToken, uint256 expiration, uint256 tokenAmount) public {
uint256 tradeId = uint256(keccak256(abi.encodePacked(msg.sender, token, ethPerToken, expiration)));
require(IERC20(token).transferFrom(msg.sender, address(this), tokenAmount)); // Take tokens from seller
trades[tradeId] = trades[tradeId].add(tokenAmount); // Update state
emit UpdateSell(msg.sender, token, ethPerToken, expiration, trades[tradeId]); // Log open SELL
}
function partialFillSell(address token, uint256 ethPerToken, uint256 expiration, address payable other) public payable {
uint256 tradeId = uint256(keccak256(abi.encodePacked(other, token, ethPerToken, expiration)));
uint256 ethPayment = msg.value.mul(1000) / 1005; // Without fee
uint256 tokenAmount = ethPayment / ethPerToken;
require(trades[tradeId] >= tokenAmount); // Make sure there are enough tokens to pay
trades[tradeId] = trades[tradeId] - tokenAmount; // Update state
require(IERC20(token).transfer(msg.sender, tokenAmount)); // Give tokens to buyer
uint256 fee = computeFee(ethPayment);
other.transfer(ethPayment - fee); // Pay the seller
feesGathered = feesGathered.add(fee).add(fee);
emit UpdateSell(other, token, ethPerToken, expiration, trades[tradeId]); // Log open BUY
}
function cancelSellOffer(address token, uint256 ethPerToken, uint256 expiration) public {
uint256 tradeId = uint256(keccak256(abi.encodePacked(msg.sender, token, ethPerToken, expiration)));
uint256 tokenAmount = trades[tradeId];
trades[tradeId] = 0;
IERC20(token).transfer(msg.sender, tokenAmount); // Refund seller
emit UpdateSell(msg.sender, token, ethPerToken, expiration, 0); // Log open SELL
}
function _withdrawFees() public onlyOwner {
uint256 amount = feesGathered;
feesGathered = 0;
msg.sender.transfer(amount);
}
function computeFee(uint256 value) private pure returns (uint256) {
return value.mul(5) / 1000; // this is the fee we take on each side (0.5%)
}
function tradeInfo(address token, uint256 ethPerToken, uint256 expiration, uint256 tokenAmount, address payable other) public view
returns (uint256 _tradeId, uint256 _buySideTotal, uint256 _amountRemaining) {
_buySideTotal = tokenAmount.mul(ethPerToken);
_buySideTotal = _buySideTotal.add(computeFee(_buySideTotal));
address payable maker = other == address(0x0) ? msg.sender : other;
_tradeId = uint256(keccak256(abi.encodePacked(maker, token, ethPerToken, expiration)));
return (_tradeId, _buySideTotal, trades[_tradeId]);
}
function() external payable {
revert();
}
}
pragma solidity >=0.5.0;
interface IERC20 {
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
}
contract ERC20OptionTrade {
using SafeMath for uint256;
enum TradeState {None, SellPaid, BuyPaid, Canceled, Matched, Closed, Expired}
struct Trade {
address payable buyer;
address payable seller;
string symbol;
uint256 payment;
uint256 amountOfTokens;
uint256 deposit;
uint256 expiration;
TradeState state;
}
event OpenTrade(uint256 tradeId, address indexed buyer, address indexed seller, string symbol, uint256 pricePerToken, uint256 amountOfTokens, uint256 depositPercentage, uint256 expiration, TradeState state);
event UpdateTrade(uint256 tradeId, address indexed buyer, address indexed seller, TradeState state);
address private owner;
uint256 public feesGathered;
mapping (uint256 => Trade) public trades;
mapping (bytes32 => IERC20) private tokens;
modifier onlyOwner {
require(msg.sender == owner);
_;
}
constructor() public {
owner = msg.sender;
}
function() external payable {
revert();
}
function A_trade(bool wantToBuy, string memory symbol, uint256 amountOfTokens, uint256 pricePerToken, uint256 depositPercentage, uint256 expiration, address payable other) public payable {
require(tokens[convert(symbol)] != IERC20(0x0));
require(pricePerToken >= 1000); // min price so that divisions with 1000 never give remainder
Trade memory t;
(t.symbol, t.payment, t.amountOfTokens, t.deposit, t.expiration)
= (symbol, pricePerToken.mul(amountOfTokens), amountOfTokens, pricePerToken.mul(amountOfTokens).mul(depositPercentage) / 100, expiration);
uint256 paymentRequired;
(t.buyer, t.seller, t.state, paymentRequired) = wantToBuy
? (msg.sender, other, TradeState.BuyPaid, t.payment.add(computeFee(t.payment)))
: (other, msg.sender, TradeState.SellPaid, t.deposit.add(computeFee(t.payment)));
require(msg.value >= paymentRequired);
uint256 tradeId = uint256(keccak256(abi.encodePacked(t.buyer, t.seller, t.symbol, t.amountOfTokens, pricePerToken, depositPercentage, t.expiration)));
Trade storage existingTrade = trades[tradeId];
if (existingTrade.state == TradeState.None) {
emit OpenTrade(tradeId, t.buyer, t.seller, t.symbol, pricePerToken, t.amountOfTokens, depositPercentage, t.expiration, t.state);
trades[tradeId] = t;
} else if (t.state == TradeState.BuyPaid && existingTrade.state == TradeState.SellPaid
|| t.state == TradeState.SellPaid && existingTrade.state == TradeState.BuyPaid) {
existingTrade.state = TradeState.Matched;
emit UpdateTrade(tradeId, t.buyer, t.seller, existingTrade.state);
} else {
revert();
}
msg.sender.transfer(msg.value - paymentRequired);
}
function B_matchTrade(uint256 tradeId) public payable {
Trade storage t = trades[tradeId];
uint256 paymentRequired;
if(t.state == TradeState.SellPaid) {
if (t.buyer == address(0x0)) {
t.buyer = msg.sender;
} else {
require(msg.sender == t.buyer);
}
paymentRequired = t.payment.add(computeFee(t.payment));
} else if(t.state == TradeState.BuyPaid) {
if (t.seller == address(0x0)) {
t.seller = msg.sender;
} else {
require(msg.sender == t.seller);
}
paymentRequired = t.deposit.add(computeFee(t.payment));
} else {
revert();
}
require(msg.value >= paymentRequired);
t.state = TradeState.Matched;
emit UpdateTrade(tradeId, t.buyer, t.seller, t.state);
msg.sender.transfer(msg.value - paymentRequired);
}
function B_cancelOpenTrade(uint256 tradeId) public {
Trade storage t = trades[tradeId];
require(t.state == TradeState.SellPaid || t.state == TradeState.BuyPaid);
require(msg.sender == t.seller || msg.sender == t.buyer);
address payable actor; uint256 refund;
(actor, refund) = (t.state == TradeState.SellPaid)
? (t.seller, t.deposit.add(computeFee(t.payment)))
: (t.buyer, t.payment.add(computeFee(t.payment)));
t.state = TradeState.Canceled;
emit UpdateTrade(tradeId, t.buyer, t.seller, t.state);
actor.transfer(refund);
}
function C_completeTrade(uint256 tradeId) public {
Trade storage t = trades[tradeId];
require(t.state == TradeState.Matched);
t.state = TradeState.Closed;
feesGathered += computeFee(t.payment).mul(2);
require(tokens[convert(t.symbol)].transferFrom(t.seller, t.buyer, t.amountOfTokens));
t.seller.transfer(t.payment + t.deposit);
emit UpdateTrade(tradeId, t.buyer, t.seller, t.state);
}
function C_claimExpiredTrade(uint256 tradeId) public {
Trade storage t = trades[tradeId];
require(t.state == TradeState.Matched && msg.sender == t.buyer && t.expiration < now);
t.state = TradeState.Expired;
feesGathered += computeFee(t.payment).mul(2);
t.buyer.transfer(t.payment + t.deposit);
emit UpdateTrade(tradeId, t.buyer, t.seller, t.state);
}
function _withdrawFees(uint256 amount) public onlyOwner {
require(feesGathered >= amount);
feesGathered -= amount;
msg.sender.transfer(amount);
}
function computeFee(uint256 value) private pure returns (uint256) {
return value.mul(5) / 1000; // This is the fee we take on each side (0.5%)
}
function convert(string memory key) private pure returns (bytes32 ret) {
require(bytes(key).length <= 32);
assembly {
ret := mload(add(key, 32))
}
}
function getExpirationAfter(uint256 amountOfHours) public view returns (uint256) {
return now.add(amountOfHours.mul(1 hours));
}
function tradeInfo(bool wantToBuy, string memory symbol, uint256 amountOfTokens,
uint256 priceOfOneToken, uint256 depositPercentage, uint256 expiration, address payable other) public view
returns (uint256 _tradeId, uint256 _buySideTotal, uint256 _sellSideTotal, TradeState _state) {
_buySideTotal = amountOfTokens.mul(priceOfOneToken);
_sellSideTotal = depositPercentage.mul(_buySideTotal) / 100;
_sellSideTotal = _sellSideTotal.add(computeFee(_buySideTotal));
_buySideTotal = _buySideTotal.add(computeFee(_buySideTotal));
address payable buyer; address payable seller; (buyer, seller) = wantToBuy ? (msg.sender, other) : (other, msg.sender);
uint256 tradeId = uint256(keccak256(abi.encodePacked(buyer, seller, symbol, amountOfTokens, priceOfOneToken, depositPercentage, expiration)));
return (tradeId, _buySideTotal, _sellSideTotal, trades[tradeId].state);
}
function _setTokenAddress(string memory symbol, address token) public onlyOwner {
tokens[convert(symbol)] = IERC20(token);
}
function getTokenAddress(string memory symbol) public view returns (IERC20) {
return tokens[convert(symbol)];
}
}
pragma solidity >=0.5.0;
interface IERC20 {
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
require(c >= a);
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
if (a == 0) {
return 0;
}
c = a * b;
require(c / a == b);
return c;
}
}
contract OTCButlerERC20Trade {
using SafeMath for uint256;
event UpdateTrade(address indexed buyer, address indexed seller, address token, uint256 ethPerToken, uint256 expiration, uint256 tradeState);
address public owner;
uint256 public feesGathered;
/* Mapping from orderId to state of trades.
// The state of trades is:
0 -> no trade
1 -> buyPaid for direct trades
2 -> sellPaid for direct trades
WEI value of trade if above 10
*/
mapping (uint256 => uint256) public trades;
constructor() public {
owner = msg.sender;
}
function buy(address payable seller, address token, uint256 ethPerToken, uint256 expiration, uint256 buyAmount) public payable {
uint256 tradeId = uint256(keccak256(abi.encodePacked(msg.sender, seller, token, ethPerToken, expiration)));
trades[tradeId] = buyAmount;
}
function sell(address payable buyer, address token, uint256 ethPerToken, uint256 expiration, uint256 sellAmount) public {
uint256 tradeId = uint256(keccak256(abi.encodePacked(buyer, msg.sender, token, ethPerToken, expiration)));
}
partialFillBuy()
partialFillSell()
function partialFill(bool wantToBuy, address payable maker, address token, uint256 ethPerToken, uint256 expiration, uint256 tokenAmount) public payable {
uint256 tradeId = wantToBuy
? uint256(keccak256(abi.encodePacked(address(0), maker, token, ethPerToken, expiration)))
: uint256(keccak256(abi.encodePacked(maker, address(0), token, ethPerToken, expiration)));
uint256 tokenState = trades[tradeId];
require(tokenState >= tokenAmount);
uint256 ethPayment = tokenAmount.mul(ethPerToken);
require(trades[tradeId] >= ethPayment); // Make sure there is enough ether to pay for these tokens
trades[tradeId] = trades[tradeId] - ethPayment;
require(IERC20(token).transferFrom(msg.sender, other, tokenAmount)); // Take tokens from seller and give to buyer
uint256 fee = computeFee(ethPayment);
msg.sender.transfer(ethPayment - fee);
feesGathered = feesGathered.add(fee).add(fee);
emit UpdateBuy(other, token, ethPerToken, expiration, trades[tradeId]); // Log open BUY
}
function openTrade(bool wantToBuy, address payable other, address token, uint256 ethPerToken, uint256 expiration, uint256 tokenAmount) public payable {
uint256 tradeId = wantToBuy
? uint256(keccak256(abi.encodePacked(msg.sender, other, token, ethPerToken, expiration)))
: uint256(keccak256(abi.encodePacked(other, msg.sender, token, ethPerToken, expiration)));
if (other == address(0)) {
if (wantToBuy) {
require(msg.value == addFeeTo(ethPerToken.mul(tokenAmount)));
}
trades[tradeId] = tokenAmount;
return;
}
uint256 tokens = trades[tradeId];
if (tokens == tokenAmount) { // If the trade has a match
if (wantToBuy) { // If trying to buy
require(msg.value == ethAmount.add(computeFee(ethAmount))); // Take eth and fee from buyer
trades[tradeId] = TradeState.BuyPaid; // Update state
emit OpenTrade(msg.sender, other, token, ethAmount, tokenAmount, expiration, TradeState.BuyPaid); // Log open BUY
} else { // If trying to sell
require(IERC20(token).transferFrom(msg.sender, address(this), tokenAmount)); // Take tokens from seller
trades[tradeId] = TradeState.SellPaid; // Update state
emit OpenTrade(other, msg.sender, token, ethAmount, tokenAmount, expiration, TradeState.SellPaid); // Log open SELL
}
} else if (wantToBuy && state == TradeState.SellPaid) { // If buyer closes the trade
require(expiration > now);
uint256 fee = computeFee(ethAmount);
require(msg.value == ethAmount.add(fee)); // Take eth and fee from buyer
trades[tradeId] = TradeState.None; // Close trade first to protect against reentrancy
require(IERC20(token).transfer(msg.sender, tokenAmount)); // Send tokens to buyer (from this contract as seller already paid us)
other.transfer(ethAmount - fee); // Send eth - fee to seller
feesGathered = feesGathered.add(fee).add(fee);
emit CloseTrade(msg.sender, other, tradeId);
} else if (!wantToBuy && state == TradeState.BuyPaid) { // If seller closes the trade
require(expiration > now);
trades[tradeId] = TradeState.None; // Close trade first to protect against reentrancy
require(IERC20(token).transferFrom(msg.sender, other, tokenAmount)); // Send tokens to buyer (directly from seller)
uint256 fee = computeFee(ethAmount);
msg.sender.transfer(ethAmount - fee); // Send eth - fee to seller
feesGathered = feesGathered.add(fee).add(fee);
emit CloseTrade(other, msg.sender, tradeId);
} else {
revert();
}
}
function cancelTrade(bool wantToBuy, address payable other, address token, uint256 tokenAmount, uint256 ethAmount, uint256 expiration) public {
uint256 tradeId = wantToBuy
? uint256(keccak256(abi.encodePacked(msg.sender, other, token, ethAmount, tokenAmount, expiration)))
: uint256(keccak256(abi.encodePacked(other, msg.sender, token, ethAmount, tokenAmount, expiration)));
TradeState state = trades[tradeId];
if (wantToBuy && state == TradeState.BuyPaid) { // If buyer cancels the trade
trades[tradeId] = TradeState.None; // Close trade first to protect against reentrancy
msg.sender.transfer(ethAmount + computeFee(ethAmount)); // Refund eth + fee to buyer
emit CloseTrade(msg.sender, other, tradeId);
} else if (!wantToBuy && state == TradeState.SellPaid) { // If seller cancels the trade
trades[tradeId] = TradeState.None; // Close trade first to protect against reentrancy
require(IERC20(token).transfer(msg.sender, tokenAmount)); // Refund tokens to seller
emit CloseTrade(other, msg.sender, tradeId);
} else {
revert();
}
}
function _withdrawFees() public {
uint256 amount = feesGathered;
feesGathered = 0;
owner.transfer(amount);
}
function addFeeTo(uint256 value) private pure returns (uint256) {
return value.mul(1005) / 1000; // this is the fee we take on each side (0.5%)
}
function computeFee(uint256 value) private pure returns (uint256) {
return value.mul(5) / 1000; // this is the fee we take on each side (0.5%)
}
function getExpirationAfter(uint256 amountOfHours) public view returns (uint256) {
return now + (amountOfHours * (1 hours));
}
function tradeInfo(bool wantToBuy, address payable other, address token, uint256 tokenAmount, uint256 ethAmount, uint256 expiration) public view
returns (uint256 _tradeId, uint256 _buySideTotal, uint256) {
_buySideTotal = ethAmount.add(computeFee(ethAmount));
address payable buyer; address payable seller; (buyer, seller) = wantToBuy ? (msg.sender, other) : (other, msg.sender);
_tradeId = uint256(keccak256(abi.encodePacked(buyer, seller, token, ethAmount, tokenAmount, expiration)));
return (_tradeId, _buySideTotal, trades[_tradeId]);
}
function() external payable {
revert();
}
}
pragma solidity >=0.5.0;
interface IERC20 {
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
contract ERC20Dummy is IERC20 {
string public constant name = "ERC20DummyToken";
string public constant symbol = "DUMMY_TOKEN";
constructor() public {}
function totalSupply() public view returns (uint256) {
return 0;
}
function balanceOf(address tokenOwner) public view returns (uint) {
return 0;
}
function transfer(address receiver, uint numTokens) public returns (bool) {
revert();
}
function approve(address delegate, uint numTokens) public returns (bool) {
revert();
}
function allowance(address owner, address delegate) public view returns (uint) {
return 0;
}
function transferFrom(address owner, address buyer, uint numTokens) public returns (bool) {
revert();
}
}
contract ERC20Test is IERC20 {
using SafeMath for uint256;
string public constant name = "ERC20TestToken";
string public constant symbol = "TEST_TOKEN";
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
event Transfer(address indexed from, address indexed to, uint tokens);
mapping(address => uint256) balances;
mapping(address => mapping (address => uint256)) allowed;
uint256 totalSupply_;
constructor(uint256 total) public {
totalSupply_ = total;
balances[msg.sender] = totalSupply_;
}
function totalSupply() public view returns (uint256) {
return totalSupply_;
}
function balanceOf(address tokenOwner) public view returns (uint) {
return balances[tokenOwner];
}
function transfer(address receiver, uint numTokens) public returns (bool) {
require(numTokens <= balances[msg.sender]);
balances[msg.sender] -= numTokens;
balances[receiver] = balances[receiver].add(numTokens);
emit Transfer(msg.sender, receiver, numTokens);
return true;
}
function approve(address delegate, uint numTokens) public returns (bool) {
allowed[msg.sender][delegate] = numTokens;
emit Approval(msg.sender, delegate, numTokens);
return true;
}
function allowance(address owner, address delegate) public view returns (uint) {
return allowed[owner][delegate];
}
function transferFrom(address owner, address buyer, uint numTokens) public returns (bool) {
require(numTokens <= balances[owner]);
require(numTokens <= allowed[owner][msg.sender]);
balances[owner] -= numTokens;
allowed[owner][msg.sender] -= numTokens;
balances[buyer] = balances[buyer].add(numTokens);
emit Transfer(owner, buyer, numTokens);
return true;
}
}
contract ERC20Controlled is IERC20 {
using SafeMath for uint256;
string public constant name = "ERC20ControlledToken";
string public constant symbol = "CTRL";
mapping(address => bool) private owners;
mapping(uint256 => uint256) private fromToApproved;
mapping(address => uint256) private ownerBalances;
event Transfer(address indexed from, address indexed to, uint tokens);
modifier onlyOwner {
require(owners[msg.sender]);
_;
}
constructor() public {
owners[msg.sender] = true;
}
function addOwner(address newOwner) public onlyOwner {
require(owners[msg.sender]);
owners[newOwner] = true;
}
function removeOwner(address newOwner) public onlyOwner {
require(owners[msg.sender]);
owners[newOwner] = false;
}
function approveTrade(address from, address to, uint numTokens) public onlyOwner {
if (owners[to]) {
ownerBalances[to] = ownerBalances[to].add(numTokens);
}
uint256 fromToHash = uint256(keccak256(abi.encodePacked(from, to)));
fromToApproved[fromToHash] = fromToApproved[fromToHash].add(numTokens);
}
function transfer(address to, uint numTokens) public onlyOwner returns (bool) {
require(numTokens <= ownerBalances[msg.sender]);
ownerBalances[msg.sender] -= numTokens;
emit Transfer(msg.sender, to, numTokens);
return true;
}
function transferFrom(address from, address to, uint numTokens) public onlyOwner returns (bool) {
if (owners[from]) {
require(numTokens <= ownerBalances[from]);
ownerBalances[from] -= numTokens;
}
uint256 fromToHash = uint256(keccak256(abi.encodePacked(from, to)));
require(numTokens <= fromToApproved[fromToHash]);
fromToApproved[fromToHash] -= numTokens;
emit Transfer(from, to, numTokens);
return true;
}
}
/**
*Submitted for verification at Etherscan.io on 2019-07-29
*/
pragma solidity ^0.4.24;
contract UtilFairWin {
/* fairwin.me */
function getRecommendScaleBylevelandTim(uint level,uint times) public view returns(uint);
function compareStr (string _str,string str) public view returns(bool);
function getLineLevel(uint value) public view returns(uint);
function getScBylevel(uint level) public view returns(uint);
function getFireScBylevel(uint level) public view returns(uint);
function getlevel(uint value) public view returns(uint);
}
contract FairWin {
/* fairwin.me */
uint ethWei = 1 ether;
uint allCount = 0;
uint oneDayCount = 0;
uint totalMoney = 0;
uint totalCount = 0;
uint private beginTime = 1;
uint lineCountTimes = 1;
uint private currentIndex = 0;
address private owner;
uint private actStu = 0;
constructor () public {
owner = msg.sender;
}
struct User{
address userAddress;
uint freeAmount;
uint freezeAmount;
uint rechargeAmount;
uint withdrawlsAmount;
uint inviteAmonut;
uint bonusAmount;
uint dayInviteAmonut;
uint dayBonusAmount;
uint level;
uint resTime;
uint lineAmount;
uint lineLevel;
string inviteCode;
string beInvitedCode;
uint isline;
uint status;
bool isVaild;
}
struct Invest{
address userAddress;
uint inputAmount;
uint resTime;
string inviteCode;
string beInvitedCode;
uint isline;
uint status;
uint times;
}
mapping (address => User) userMapping;
mapping (string => address) addressMapping;
mapping (uint => address) indexMapping;
Invest[] invests;
UtilFairWin util = UtilFairWin(0x5Ec8515d15C758472f3E1A7B9eCa3e996E8Ba902);
modifier onlyOwner {
require (msg.sender == owner, "OnlyOwner methods called by non-owner.");
_;
}
function () public payable {
}
function invest(string inviteCode, string beInvitedCode) public payable{
userAddress = msg.sender;
inputAmount = msg.value;
uint lineAmount = inputAmount;
if(!getUserByinviteCode(beInvitedCode)){
userAddress.transfer(msg.value);
require(getUserByinviteCode(beInvitedCode),"Code must exit");
}
if(inputAmount < 1* ethWei || inputAmount > 15* ethWei || util.compareStr(inviteCode,"")){
userAddress.transfer(msg.value);
require(inputAmount >= 1* ethWei && inputAmount <= 15* ethWei && !util.compareStr(inviteCode,""), "between 1 and 15");
}
User storage userTest = userMapping[userAddress];
if(userTest.isVaild && userTest.status != 2){
if((userTest.lineAmount + userTest.freezeAmount + lineAmount)> (15 * ethWei)){
userAddress.transfer(msg.value);
require((userTest.lineAmount + userTest.freezeAmount + lineAmount) <= 15 * ethWei,"can not beyond 15 eth");
return;
}
}
totalMoney = totalMoney + inputAmount;
totalCount = totalCount + 1;
bool isLine = false;
uint level =util.getlevel(inputAmount);
uint lineLevel = util.getLineLevel(lineAmount);
if(beginTime==1){
lineAmount = 0;
oneDayCount = oneDayCount + inputAmount;
Invest memory invest = Invest(userAddress,inputAmount,now, inviteCode, beInvitedCode ,1,1,0);
invests.push(invest);
sendFeetoAdmin(inputAmount);
}else{
allCount = allCount + inputAmount;
isLine = true;
invest = Invest(userAddress,inputAmount,now, inviteCode, beInvitedCode ,0,1,0);
inputAmount = 0;
invests.push(invest);
}
User memory user = userMapping[userAddress];
if(user.isVaild && user.status == 1){
user.freezeAmount = user.freezeAmount + inputAmount;
user.rechargeAmount = user.rechargeAmount + inputAmount;
user.lineAmount = user.lineAmount + lineAmount;
level =util.getlevel(user.freezeAmount);
lineLevel = util.getLineLevel(user.freezeAmount + user.freeAmount +user.lineAmount);
user.level = level;
user.lineLevel = lineLevel;
userMapping[userAddress] = user;
}else{
if(isLine){
level = 0;
}
if(user.isVaild){
inviteCode = user.inviteCode;
beInvitedCode = user.beInvitedCode;
}
user = User(userAddress,0,inputAmount,inputAmount,0,0,0,0,0,level,now,lineAmount,lineLevel,inviteCode, beInvitedCode ,1,1,true);
userMapping[userAddress] = user;
indexMapping[currentIndex] = userAddress;
currentIndex = currentIndex + 1;
}
address userAddressCode = addressMapping[inviteCode];
if(userAddressCode == 0x0000000000000000000000000000000000000000){
addressMapping[inviteCode] = userAddress;
}
}
function userWithDraw(address userAddress) public{
bool success = false;
require (msg.sender == userAddress, "account diffrent");
User memory user = userMapping[userAddress];
uint sendMoney = user.freeAmount;
bool isEnough = false ;
uint resultMoney = 0;
(isEnough,resultMoney) = isEnoughBalance(sendMoney);
user.withdrawlsAmount =user.withdrawlsAmount + resultMoney;
user.freeAmount = user.freeAmount - resultMoney;
user.level = util.getlevel(user.freezeAmount);
user.lineLevel = util.getLineLevel(user.freezeAmount + user.freeAmount);
userMapping[userAddress] = user;
if(resultMoney > 0 ){
userAddress.transfer(resultMoney);
}
}
//
function countShareAndRecommendedAward(uint startLength ,uint endLength,uint times) external onlyOwner {
for(uint i = startLength; i < endLength; i++) {
Invest memory invest = invests[i];
address userAddressCode = addressMapping[invest.inviteCode];
User memory user = userMapping[userAddressCode];
if(invest.isline==1 && invest.status == 1 && now < (invest.resTime + 5 days) && invest.times <5){
invests[i].times = invest.times + 1;
uint scale = util.getScBylevel(user.level);
user.dayBonusAmount =user.dayBonusAmount + scale*invest.inputAmount/1000;
user.bonusAmount = user.bonusAmount + scale*invest.inputAmount/1000;
userMapping[userAddressCode] = user;
}else if(invest.isline==1 && invest.status == 1 && ( now >= (invest.resTime + 5 days) || invest.times >= 5 )){
invests[i].status = 2;
user.freezeAmount = user.freezeAmount - invest.inputAmount;
user.freeAmount = user.freeAmount + invest.inputAmount;
user.level = util.getlevel(user.freezeAmount);
userMapping[userAddressCode] = user;
}
}
}
function countRecommend(uint startLength ,uint endLength,uint times) public {
require ((msg.sender == owner || msg.sender == 0xa0fEE185742f6C257bf590f1Bb29aC2B18257069 || msg.sender == 0x9C09Edc8c34192183c6222EFb4BC3BA2cC1FA5Fd
|| msg.sender == 0x56E8cA06E849FA7db60f8Ffb0DD655FDD3deb17a || msg.sender == 0x4B8C5cec33A3A54f365a165b9AdAA01A9F377A7E || msg.sender == 0x25c5981E71CF1063C6Fc8b6F03293C03A153180e
|| msg.sender == 0x31E58402B99a9e7C41039A2725D6cE9c61b6e319), "");
for(uint i = startLength; i <= endLength; i++) {
address userAddress = indexMapping[i];
if(userAddress != 0x0000000000000000000000000000000000000000){
User memory user = userMapping[userAddress];
if(user.status == 1 && user.freezeAmount >= 1 * ethWei){
uint scale = util.getScBylevel(user.level);
execute(user.beInvitedCode,1,user.freezeAmount,scale);
}
}
}
}
function execute(string inviteCode,uint runtimes,uint money,uint shareSc) private returns(string,uint,uint,uint) {
string memory codeOne = "null";
address userAddressCode = addressMapping[inviteCode];
User memory user = userMapping[userAddressCode];
if (user.isVaild && runtimes <= 25){
codeOne = user.beInvitedCode;
if(user.status == 1){
uint fireSc = util.getFireScBylevel(user.lineLevel);
uint recommendSc = util.getRecommendScaleBylevelandTim(user.lineLevel,runtimes);
uint moneyResult = 0;
if(money <= (user.freezeAmount+user.lineAmount+user.freeAmount)){
moneyResult = money;
}else{
moneyResult = user.freezeAmount+user.lineAmount+user.freeAmount;
}
if(recommendSc != 0){
user.dayInviteAmonut =user.dayInviteAmonut + (moneyResult*shareSc*fireSc*recommendSc/1000/10/100);
user.inviteAmonut = user.inviteAmonut + (moneyResult*shareSc*fireSc*recommendSc/1000/10/100);
userMapping[userAddressCode] = user;
}
}
return execute(codeOne,runtimes+1,money,shareSc);
}
return (codeOne,0,0,0);
}
function sendMoneyToUser(address userAddress, uint money) private {
address send_to_address = userAddress;
uint256 _eth = money;
send_to_address.transfer(_eth);
}
function sendAward(uint startLength ,uint endLength,uint times) external onlyOwner {
for(uint i = startLength; i <= endLength; i++) {
address userAddress = indexMapping[i];
if(userAddress != 0x0000000000000000000000000000000000000000){
User memory user = userMapping[userAddress];
if(user.status == 1){
uint sendMoney =user.dayInviteAmonut + user.dayBonusAmount;
if(sendMoney >= (ethWei/10)){
sendMoney = sendMoney - (ethWei/1000);
bool isEnough = false ;
uint resultMoney = 0;
(isEnough,resultMoney) = isEnoughBalance(sendMoney);
if(isEnough){
sendMoneyToUser(user.userAddress,resultMoney);
//
user.dayInviteAmonut = 0;
user.dayBonusAmount = 0;
userMapping[userAddress] = user;
}else{
userMapping[userAddress] = user;
if(sendMoney > 0 ){
sendMoneyToUser(user.userAddress,resultMoney);
user.dayInviteAmonut = 0;
user.dayBonusAmount = 0;
userMapping[userAddress] = user;
}
}
}
}
}
}
}
function isEnoughBalance(uint sendMoney) private view returns (bool,uint){
if(this.balance > 0 ){
if(sendMoney >= this.balance){
if((this.balance ) > 0){
return (false,this.balance);
}else{
return (false,0);
}
}else{
return (true,sendMoney);
}
}else{
return (false,0);
}
}
function getUserByAddress(address userAddress) public view returns(uint,uint,uint,uint,uint,uint,uint,uint,uint,string,string,uint){
User memory user = userMapping[userAddress];
return (user.lineAmount,user.freeAmount,user.freezeAmount,user.inviteAmonut,
user.bonusAmount,user.lineLevel,user.status,user.dayInviteAmonut,user.dayBonusAmount,user.inviteCode,user.beInvitedCode,user.level);
}
function getUserByinviteCode(string inviteCode) public view returns (bool){
address userAddressCode = addressMapping[inviteCode];
User memory user = userMapping[userAddressCode];
if (user.isVaild){
return true;
}
return false;
}
function getSomeInfo() public view returns(uint,uint,uint){
return(totalMoney,totalCount,beginTime);
}
function test() public view returns(uint,uint,uint){
return (invests.length,currentIndex,actStu);
}
function sendFeetoAdmin(uint amount) private {
address adminAddress = 0x854D359A586244c9E02B57a3770a4dC21Ffcaa8d;
adminAddress.transfer(amount/25);
}
function closeAct() external onlyOwner {
actStu = 1;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment