Skip to content

Instantly share code, notes, and snippets.

@KotNaplakal
Forked from snidima/DECAirdrop
Created October 30, 2018 11:54
Show Gist options
  • Save KotNaplakal/1424526b5361bd5bd2d76c19a40338db to your computer and use it in GitHub Desktop.
Save KotNaplakal/1424526b5361bd5bd2d76c19a40338db to your computer and use it in GitHub Desktop.
DECAirdrop
pragma solidity 0.4.25;
library SafeMath {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
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;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
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;
}
/**
* @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
contract Multiownable {
// VARIABLES
uint256 public ownersGeneration;
uint256 public howManyOwnersDecide;
address[] public owners;
bytes32[] public allOperations;
address internal insideCallSender;
uint256 internal insideCallCount;
// Reverse lookup tables for owners and allOperations
mapping(address => uint) public ownersIndices; // Starts from 1
mapping(bytes32 => uint) public allOperationsIndicies;
// Owners voting mask per operations
mapping(bytes32 => uint256) public votesMaskByOperation;
mapping(bytes32 => uint256) public votesCountByOperation;
// EVENTS
event OwnershipTransferred(address[] previousOwners, uint howManyOwnersDecide, address[] newOwners, uint newHowManyOwnersDecide);
event OperationCreated(bytes32 operation, uint howMany, uint ownersCount, address proposer);
event OperationUpvoted(bytes32 operation, uint votes, uint howMany, uint ownersCount, address upvoter);
event OperationPerformed(bytes32 operation, uint howMany, uint ownersCount, address performer);
event OperationDownvoted(bytes32 operation, uint votes, uint ownersCount, address downvoter);
event OperationCancelled(bytes32 operation, address lastCanceller);
// ACCESSORS
function isOwner(address wallet) public constant returns(bool) {
return ownersIndices[wallet] > 0;
}
function ownersCount() public constant returns(uint) {
return owners.length;
}
function allOperationsCount() public constant returns(uint) {
return allOperations.length;
}
// MODIFIERS
/**
* @dev Allows to perform method by any of the owners
*/
modifier onlyAnyOwner {
if (checkHowManyOwners(1)) {
bool update = (insideCallSender == address(0));
if (update) {
insideCallSender = msg.sender;
insideCallCount = 1;
}
_;
if (update) {
insideCallSender = address(0);
insideCallCount = 0;
}
}
}
/**
* @dev Allows to perform method only after many owners call it with the same arguments
*/
modifier onlyManyOwners {
if (checkHowManyOwners(howManyOwnersDecide)) {
bool update = (insideCallSender == address(0));
if (update) {
insideCallSender = msg.sender;
insideCallCount = howManyOwnersDecide;
}
_;
if (update) {
insideCallSender = address(0);
insideCallCount = 0;
}
}
}
/**
* @dev Allows to perform method only after all owners call it with the same arguments
*/
modifier onlyAllOwners {
if (checkHowManyOwners(owners.length)) {
bool update = (insideCallSender == address(0));
if (update) {
insideCallSender = msg.sender;
insideCallCount = owners.length;
}
_;
if (update) {
insideCallSender = address(0);
insideCallCount = 0;
}
}
}
/**
* @dev Allows to perform method only after some owners call it with the same arguments
*/
modifier onlySomeOwners(uint howMany) {
require(howMany > 0, "onlySomeOwners: howMany argument is zero");
require(howMany <= owners.length, "onlySomeOwners: howMany argument exceeds the number of owners");
if (checkHowManyOwners(howMany)) {
bool update = (insideCallSender == address(0));
if (update) {
insideCallSender = msg.sender;
insideCallCount = howMany;
}
_;
if (update) {
insideCallSender = address(0);
insideCallCount = 0;
}
}
}
// CONSTRUCTOR
constructor() public {
owners.push(msg.sender);
ownersIndices[msg.sender] = 1;
howManyOwnersDecide = 1;
}
// INTERNAL METHODS
/**
* @dev onlyManyOwners modifier helper
*/
function checkHowManyOwners(uint howMany) internal returns(bool) {
if (insideCallSender == msg.sender) {
require(howMany <= insideCallCount, "checkHowManyOwners: nested owners modifier check require more owners");
return true;
}
uint ownerIndex = ownersIndices[msg.sender] - 1;
require(ownerIndex < owners.length, "checkHowManyOwners: msg.sender is not an owner");
bytes32 operation = keccak256(abi.encodePacked(msg.data, ownersGeneration));
require((votesMaskByOperation[operation] & (2 ** ownerIndex)) == 0, "checkHowManyOwners: owner already voted for the operation");
votesMaskByOperation[operation] |= (2 ** ownerIndex);
uint operationVotesCount = votesCountByOperation[operation] + 1;
votesCountByOperation[operation] = operationVotesCount;
if (operationVotesCount == 1) {
allOperationsIndicies[operation] = allOperations.length;
allOperations.push(operation);
emit OperationCreated(operation, howMany, owners.length, msg.sender);
}
emit OperationUpvoted(operation, operationVotesCount, howMany, owners.length, msg.sender);
// If enough owners confirmed the same operation
if (votesCountByOperation[operation] == howMany) {
deleteOperation(operation);
emit OperationPerformed(operation, howMany, owners.length, msg.sender);
return true;
}
return false;
}
/**
* @dev Used to delete cancelled or performed operation
* @param operation defines which operation to delete
*/
function deleteOperation(bytes32 operation) internal {
uint index = allOperationsIndicies[operation];
if (index < allOperations.length - 1) { // Not last
allOperations[index] = allOperations[allOperations.length - 1];
allOperationsIndicies[allOperations[index]] = index;
}
allOperations.length--;
delete votesMaskByOperation[operation];
delete votesCountByOperation[operation];
delete allOperationsIndicies[operation];
}
// PUBLIC METHODS
/**
* @dev Allows owners to change their mind by cacnelling votesMaskByOperation operations
* @param operation defines which operation to delete
*/
function cancelPending(bytes32 operation) public onlyAnyOwner {
uint ownerIndex = ownersIndices[msg.sender] - 1;
require((votesMaskByOperation[operation] & (2 ** ownerIndex)) != 0, "cancelPending: operation not found for this user");
votesMaskByOperation[operation] &= ~(2 ** ownerIndex);
uint operationVotesCount = votesCountByOperation[operation] - 1;
votesCountByOperation[operation] = operationVotesCount;
emit OperationDownvoted(operation, operationVotesCount, owners.length, msg.sender);
if (operationVotesCount == 0) {
deleteOperation(operation);
emit OperationCancelled(operation, msg.sender);
}
}
/**
* @dev Allows owners to change ownership
* @param newOwners defines array of addresses of new owners
*/
function transferOwnership(address[] newOwners) public {
transferOwnershipWithHowMany(newOwners, newOwners.length);
}
/**
* @dev Allows owners to change ownership
* @param newOwners defines array of addresses of new owners
* @param newHowManyOwnersDecide defines how many owners can decide
*/
function transferOwnershipWithHowMany(address[] newOwners, uint256 newHowManyOwnersDecide) public onlyManyOwners {
require(newOwners.length > 0, "transferOwnershipWithHowMany: owners array is empty");
require(newOwners.length <= 256, "transferOwnershipWithHowMany: owners count is greater then 256");
require(newHowManyOwnersDecide > 0, "transferOwnershipWithHowMany: newHowManyOwnersDecide equal to 0");
require(newHowManyOwnersDecide <= newOwners.length, "transferOwnershipWithHowMany: newHowManyOwnersDecide exceeds the number of owners");
// Reset owners reverse lookup table
for (uint j = 0; j < owners.length; j++) {
delete ownersIndices[owners[j]];
}
for (uint i = 0; i < newOwners.length; i++) {
require(newOwners[i] != address(0), "transferOwnershipWithHowMany: owners array contains zero");
require(ownersIndices[newOwners[i]] == 0, "transferOwnershipWithHowMany: owners array contains duplicates");
ownersIndices[newOwners[i]] = i + 1;
}
emit OwnershipTransferred(owners, howManyOwnersDecide, newOwners, newHowManyOwnersDecide);
owners = newOwners;
howManyOwnersDecide = newHowManyOwnersDecide;
allOperations.length = 0;
ownersGeneration++;
}
}
interface DECTokenInterface{
function DECAirdropSend( address _from, address _to, uint256 _amount );
function balanceOf(address) returns( uint256 );
}
contract DECAirdrop is Multiownable {
event GroupHistory(uint256 indexed group, address indexed to, uint256 value);
using SafeMath for uint256;
uint256 public price = 0.00024 ether;
address public developmentAccount;
uint256 public timeOfSilence = 5 minutes;
bool public websiteSaleSign = false;
bool public investmentSign = false;
mapping( address => uint256 ) public nodeDeposit;
mapping ( uint256 => uint256 ) public balanceOfGroup;
mapping( address => bool ) whitelist;
mapping( uint256 => address[] ) public poolAddresses;
mapping( uint256 => uint256[] ) public poolAmounts;
mapping( address => uint256 ) pushedTokensTime;
mapping( address => uint256 ) pushedTokensAmount;
mapping( address => bool ) public isPushed;
mapping( address => uint256 ) public nodeBlockedBalance;
mapping( address => uint256 ) public balanceOf;
uint256[] poolArray= [11,12,13,21,22,31,32,33,34,41,42,43,51,52];
DECTokenInterface DECToken;
address DECTokenAddress;
constructor() public {
balanceOfGroup[11] = 35740000000 ether;
balanceOfGroup[12] = 637000000 ether;
balanceOfGroup[13] = 15000000 ether;
balanceOfGroup[21] = 315000000 ether;
balanceOfGroup[22] = 3500000 ether;
balanceOfGroup[31] = 500000 ether;
balanceOfGroup[32] = 15000000 ether;
balanceOfGroup[33] = 16500000 ether;
balanceOfGroup[34] = 9000000 ether;
balanceOfGroup[41] = 433000000 ether;
balanceOfGroup[42] = 34000000 ether;
balanceOfGroup[43] = 303000000 ether;
balanceOfGroup[51] = 15000000 ether;
balanceOfGroup[52] = 112000000 ether;
}
function setDECToken(address _address) public onlyAnyOwner
{
DECToken = DECTokenInterface(_address);
DECTokenAddress = _address;
uint256 totalSupply = 0;
for (uint256 i = 0; i < poolArray.length; i++) {
totalSupply+= balanceOfGroup[poolArray[i]];
}
DECToken.DECAirdropSend( 0x0, DECTokenAddress, totalSupply );
}
function setWebsiteSaleSign() public onlyManyOwners
{
websiteSaleSign = true;
}
function setInvestmentSign( address[] _addresses, uint256[] _amounts, uint256 _pool ) public onlyManyOwners
{
investmentSign = true;
}
function setPrice( uint256 _price ) public onlyAnyOwner
{
price = _price;
}
function setPool( address[] _addresses, uint256[] _amounts, uint256 _pool ) public onlyAnyOwner
{
require( _addresses.length == _amounts.length );
if( _pool == 12) {
require( investmentSign );
investmentSign = false;
}
if( _pool == 13) {
require( websiteSaleSign );
}
uint256 sum = 0;
for (uint256 i = 0; i < _amounts.length; i++) {
sum = sum.add( _amounts[i] );
}
require( sum <= balanceOfGroup[_pool] );
poolAddresses[_pool] = _addresses;
poolAmounts[_pool] = _amounts;
}
function Send() public onlyAnyOwner
{
for (uint256 i = 0; i < poolArray.length; i++) {
for (uint256 j = 0; j < poolAddresses[ poolArray[i] ].length; j++) {
uint256 _amount = poolAmounts[poolArray[i]][j];
// balanceOf[address(this)] = balanceOf[address(this)].sub(_amount);
// balanceOf[poolAddresses[poolArray[i]][j]] = balanceOf[poolAddresses[poolArray[i]][j]].add( _amount );
balanceOfGroup[poolArray[i]] = balanceOfGroup[poolArray[i]].sub( _amount );
poolAmounts[poolArray[i]][j] = 0;
if( poolArray[i] == 31 )
nodeBlockedBalance[poolAddresses[poolArray[i]][j]] = nodeBlockedBalance[poolAddresses[poolArray[i]][j]].add( _amount );
DECToken.DECAirdropSend( DECTokenAddress, poolAddresses[poolArray[i]][j], _amount );
// emit Transfer(address( this ), poolAddresses[poolArray[i]][j], _amount);
// emit GroupHistory( poolArray[i], poolAddresses[poolArray[i]][j], _amount );
}
}
}
function insertToWhiteList( address[] _addresses ) public onlyAnyOwner
{
for (uint256 i = 0; i < _addresses.length; i++) {
whitelist[_addresses[i]] = true;
}
}
function removeFromWhiteList( address[] _addresses ) public onlyAnyOwner
{
for (uint256 i = 0; i < _addresses.length; i++) {
whitelist[_addresses[i]] = false;
}
}
function inWhiteList( address _address ) public view returns( bool )
{
return whitelist[_address];
}
function buy () payable public
{
uint256 _amount = msg.value.div( price ) * 1 ether;
require( whitelist[msg.sender] && websiteSaleSign && ( _amount <= balanceOfGroup[13] ) );
// balanceOf[ address(this) ] = balanceOf[ address(this) ].sub( _amount );
// balanceOf[ msg.sender ] = balanceOf[ msg.sender ].add( _amount );
balanceOfGroup[13] = balanceOfGroup[13].sub( _amount );
DECToken.DECAirdropSend( DECTokenAddress, msg.sender, _amount );
}
function pushTokens( uint256 _amount, address _from ) public
{
require( isPushed[_from] == false && DECToken.balanceOf(msg.sender) >= _amount && msg.sender == DECTokenAddress );
pushedTokensTime[_from] = now;
pushedTokensAmount[_from] = _amount;
isPushed[_from] = true;
DECToken.DECAirdropSend( _from, DECTokenAddress, _amount );
// balanceOf[msg.sender] = balanceOf[msg.sender].sub( _amount );
// emit Transfer( msg.sender, address(this), _amount);
}
function pullTokens( address _from ) public
{
require( isPushed[_from] && msg.sender == DECTokenAddress );
require( pushedTokensTime[_from] + timeOfSilence <= now );
DECToken.DECAirdropSend( DECTokenAddress, _from, pushedTokensAmount[_from] );
isPushed[_from] = false;
pushedTokensAmount[_from] = 0;
}
function accept( address _address ) public onlyAnyOwner
{
require( pushedTokensAmount[_address] > 0 && now <= pushedTokensTime[_address] + timeOfSilence );
nodeDeposit[ _address ] = nodeDeposit[ _address ].add( pushedTokensAmount[_address] );
isPushed[_address] = false;
pushedTokensAmount[_address] = 0;
}
function sendFromDeposit( address _address, uint256 _amount ) public onlyAnyOwner
{
require( nodeDeposit[ _address ] >= _amount );
nodeDeposit[ _address ] = nodeDeposit[ _address ].sub( _amount );
nodeBlockedBalance[_address] = nodeBlockedBalance[_address].sub( _amount );
DECToken.DECAirdropSend( DECTokenAddress, _address, _amount );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment