Skip to content

Instantly share code, notes, and snippets.

@abdul
Created January 12, 2018 11:53
Show Gist options
  • Save abdul/cd6f5aca050ad6ec72bacfe420f985be to your computer and use it in GitHub Desktop.
Save abdul/cd6f5aca050ad6ec72bacfe420f985be to your computer and use it in GitHub Desktop.
Created using browser-solidity: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://ethereum.github.io/browser-solidity/#version=soljson-v0.4.19+commit.c4cbbb05.js&optimize=false&gist=
pragma solidity ^0.4.18;
import './ERC20Basic.sol';
import './SafeMath.sol';
/**
* @title Basic token
* @dev Basic version of StandardToken, with no allowances.
* https://github.com/OpenZeppelin/zeppelin-solidity/
*/
contract BasicToken is ERC20Basic {
using SafeMath for uint256;
mapping(address => uint256) balances;
/**
* @dev transfer token for a specified address
* @param _to The address to transfer to.
* @param _value The amount to be transferred.
*/
function transfer(address _to, uint256 _value) public returns (bool) {
require(_to != address(0));
require(_value <= balances[msg.sender]);
// SafeMath.sub will throw if there is not enough balance.
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
Transfer(msg.sender, _to, _value);
return true;
}
/**
* @dev Gets the balance of the specified address.
* @param _owner The address to query the the balance of.
* @return An uint256 representing the amount owned by the passed address.
*/
function balanceOf(address _owner) public view returns (uint256 balance) {
return balances[_owner];
}
}
pragma solidity ^0.4.18;
import "./Ownable.sol";
import "./ERC20Basic.sol";
import "./SafeERC20.sol";
/**
* @title Contracts that should be able to recover tokens
* @author SylTi
* @dev This allow a contract to recover any ERC20 token received in a contract by transferring the balance to the contract owner.
* This will prevent any accidental loss of tokens.
* https://github.com/OpenZeppelin/zeppelin-solidity/
*/
contract CanReclaimToken is Ownable {
using SafeERC20 for ERC20Basic;
/**
* @dev Reclaim all ERC20Basic compatible tokens
* @param token ERC20Basic The address of the token contract
*/
function reclaimToken(ERC20Basic token) external onlyOwner {
uint256 balance = token.balanceOf(this);
token.safeTransfer(owner, balance);
}
}
pragma solidity ^0.4.13;
/**
* @title DayLimit
* @dev Base contract that enables methods to be protected by placing a linear limit (specifiable)
* on a particular resource per calendar day. Is multiowned to allow the limit to be altered.
*/
contract DayLimit {
uint256 public dailyLimit;
uint256 public spentToday;
uint256 public lastDay;
/**
* @dev Constructor that sets the passed value as a dailyLimit.
* @param _limit uint256 to represent the daily limit.
*/
function DayLimit(uint256 _limit) {
dailyLimit = _limit;
lastDay = today();
}
/**
* @dev sets the daily limit. Does not alter the amount already spent today.
* @param _newLimit uint256 to represent the new limit.
*/
function _setDailyLimit(uint256 _newLimit) internal {
dailyLimit = _newLimit;
}
/**
* @dev Resets the amount already spent today.
*/
function _resetSpentToday() internal {
spentToday = 0;
}
/**
* @dev Checks to see if there is enough resource to spend today. If true, the resource may be expended.
* @param _value uint256 representing the amount of resource to spend.
* @return A boolean that is True if the resource was spended and false otherwise.
*/
function underLimit(uint256 _value) internal returns (bool) {
// reset the spend limit if we're on a different day to last time.
if (today() > lastDay) {
spentToday = 0;
lastDay = today();
}
// check to see if there's enough left - if so, subtract and return true.
// overflow protection // dailyLimit check
if (spentToday + _value >= spentToday && spentToday + _value <= dailyLimit) {
spentToday += _value;
return true;
}
return false;
}
/**
* @dev Private function to determine today's index
* @return uint256 of today's index.
*/
function today() private constant returns (uint256) {
return now / 1 days;
}
/**
* @dev Simple modifier for daily limit.
*/
modifier limitedDaily(uint256 _value) {
require(underLimit(_value));
_;
}
}
pragma solidity ^0.4.18;
import './ERC20Basic.sol';
/**
* @title ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/20
* https://github.com/OpenZeppelin/zeppelin-solidity/
*/
contract ERC20 is ERC20Basic {
function allowance(address owner, address spender) public view returns (uint256);
function transferFrom(address from, address to, uint256 value) public returns (bool);
function approve(address spender, uint256 value) public returns (bool);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
pragma solidity ^0.4.18;
/**
* @title ERC20Basic
* @dev Simpler version of ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/179
* https://github.com/OpenZeppelin/zeppelin-solidity/
*/
contract ERC20Basic {
uint256 public totalSupply;
function balanceOf(address who) public view returns (uint256);
function transfer(address to, uint256 value) public returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
}
pragma solidity ^0.4.18;
import "./CanReclaimToken.sol";
/**
* @title Contracts that should not own Tokens
* @author Remco Bloemen <remco@2π.com>
* @dev This blocks incoming ERC23 tokens to prevent accidental loss of tokens.
* Should tokens (any ERC20Basic compatible) end up in the contract, it allows the
* owner to reclaim the tokens.
* https://github.com/OpenZeppelin/zeppelin-solidity/
*/
contract HasNoTokens is CanReclaimToken {
/**
* @dev Reject all ERC23 compatible tokens
* @param from_ address The address that is transferring the tokens
* @param value_ uint256 the amount of the specified token
* @param data_ Bytes The data passed from the caller.
*/
function tokenFallback(address from_, uint256 value_, bytes data_) pure external {
from_;
value_;
data_;
revert();
}
}
pragma solidity ^0.4.2;
contract Migrations {
address public owner;
uint public last_completed_migration;
modifier restricted() {
if (msg.sender == owner) {
_;
}
}
function Migrations() public {
owner = msg.sender;
}
function setCompleted(uint completed) public restricted {
last_completed_migration = completed;
}
function upgrade(address new_address) public restricted {
Migrations upgraded = Migrations(new_address);
upgraded.setCompleted(last_completed_migration);
}
}
pragma solidity ^0.4.13;
/**
* @title Multisig
* @dev Interface contract for multisig proxy contracts; see below for docs.
*/
contract Multisig {
// EVENTS
// logged events:
// Funds has arrived into the wallet (record how much).
event Deposit(address _from, uint256 value);
// Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going).
event SingleTransact(address owner, uint256 value, address to, bytes data);
// Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going).
event MultiTransact(address owner, bytes32 operation, uint256 value, address to, bytes data);
// Confirmation still needed for a transaction.
event ConfirmationNeeded(bytes32 operation, address initiator, uint256 value, address to, bytes data);
// FUNCTIONS
// TODO: document
function changeOwner(address _from, address _to) external;
function execute(address _to, uint256 _value, bytes _data) external returns (bytes32);
function confirm(bytes32 _h) returns (bool);
}
pragma solidity ^0.4.13;
import "./Multisig.sol";
import "./Shareable.sol";
import "./DayLimit.sol";
/**
* MultisigWallet
* Usage:
* bytes32 h = Wallet(w).from(oneOwner).execute(to, value, data);
* Wallet(w).from(anotherOwner).confirm(h);
*/
contract MultisigWallet is Multisig, Shareable, DayLimit {
struct Transaction {
address to;
uint256 value;
bytes data;
}
/**
* Constructor, sets the owners addresses, number of approvals required, and daily spending limit
* @param _owners A list of owners.
* @param _required The amount required for a transaction to be approved.
*/
function MultisigWallet(address[] _owners, uint256 _required, uint256 _daylimit)
Shareable(_owners, _required)
DayLimit(_daylimit) { }
/**
* @dev destroys the contract sending everything to `_to`.
*/
function destroy(address _to) onlymanyowners(keccak256(msg.data)) external {
selfdestruct(_to);
}
/**
* @dev Fallback function, receives value and emits a deposit event.
*/
function() payable {
// just being sent some cash?
if (msg.value > 0)
Deposit(msg.sender, msg.value);
}
/**
* @dev Outside-visible transaction entry point. Executes transaction immediately if below daily
* spending limit. If not, goes into multisig process. We provide a hash on return to allow the
* sender to provide shortcuts for the other confirmations (allowing them to avoid replicating
* the _to, _value, and _data arguments). They still get the option of using them if they want,
* anyways.
* @param _to The receiver address
* @param _value The value to send
* @param _data The data part of the transaction
*/
function execute(address _to, uint256 _value, bytes _data) external onlyOwner returns (bytes32 _r) {
// first, take the opportunity to check that we're under the daily limit.
if (underLimit(_value)) {
SingleTransact(msg.sender, _value, _to, _data);
// yes - just execute the call.
if (!_to.call.value(_value)(_data)) {
revert();
}
return 0;
}
// determine our operation hash.
_r = keccak256(msg.data, block.number);
if (!confirm(_r) && txs[_r].to == 0) {
txs[_r].to = _to;
txs[_r].value = _value;
txs[_r].data = _data;
ConfirmationNeeded(_r, msg.sender, _value, _to, _data);
}
}
/**
* @dev Confirm a transaction by providing just the hash. We use the previous transactions map,
* txs, in order to determine the body of the transaction from the hash provided.
* @param _h The transaction hash to approve.
*/
function confirm(bytes32 _h) onlymanyowners(_h) returns (bool) {
if (txs[_h].to != 0) {
assert(txs[_h].to.call.value(txs[_h].value)(txs[_h].data));
MultiTransact(msg.sender, _h, txs[_h].value, txs[_h].to, txs[_h].data);
delete txs[_h];
return true;
}
}
/**
* @dev Updates the daily limit value.
* @param _newLimit uint256 to represent the new limit.
*/
function setDailyLimit(uint256 _newLimit) onlymanyowners(keccak256(msg.data)) external {
_setDailyLimit(_newLimit);
}
/**
* @dev Resets the value spent to enable more spending
*/
function resetSpentToday() onlymanyowners(keccak256(msg.data)) external {
_resetSpentToday();
}
// INTERNAL METHODS
/**
* @dev Clears the list of transactions pending approval.
*/
function clearPending() internal {
uint256 length = pendingsIndex.length;
for (uint256 i = 0; i < length; ++i) {
delete txs[pendingsIndex[i]];
}
super.clearPending();
}
// FIELDS
// pending transactions we have at present.
mapping (bytes32 => Transaction) txs;
}
pragma solidity ^0.4.18;
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
* https://github.com/OpenZeppelin/zeppelin-solidity/
*/
contract Ownable {
address public owner; // Operational owner.
address public masterOwner = 0x6b116eB37e76730Afafb73D8a157D1b17c4dc0d6; // for ownership transfer segregation of duty, hard coded to wallet account
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 {
require(newOwner != address(0));
require(masterOwner == msg.sender); // only master owner can initiate change to ownershipe
OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
pragma solidity ^0.4.18;
import "./Ownable.sol";
/**
* @title Pausable
* @dev Base contract which allows children to implement an emergency stop mechanism.
* https://github.com/OpenZeppelin/zeppelin-solidity/
*/
contract Pausable is Ownable {
event Pause();
event Unpause();
bool public paused = false;
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*/
modifier whenNotPaused() {
require(!paused);
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*/
modifier whenPaused() {
require(paused);
_;
}
/**
* @dev called by the owner to pause, triggers stopped state
*/
function pause() onlyOwner whenNotPaused public {
paused = true;
Pause();
}
/**
* @dev called by the owner to unpause, returns to normal state
*/
function unpause() onlyOwner whenPaused public {
paused = false;
Unpause();
}
}
pragma solidity ^0.4.18;
import './ERC20Basic.sol';
import './ERC20.sol';
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure.
* To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
function safeTransfer(ERC20Basic token, address to, uint256 value) internal {
assert(token.transfer(to, value));
}
function safeTransferFrom(ERC20 token, address from, address to, uint256 value) internal {
assert(token.transferFrom(from, to, value));
}
function safeApprove(ERC20 token, address spender, uint256 value) internal {
assert(token.approve(spender, value));
}
}
pragma solidity ^0.4.18;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
* https://github.com/OpenZeppelin/zeppelin-solidity/
*/
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;
}
function cei(uint256 a, uint256 b) internal pure returns (uint256) {
return ((a + b - 1) / b) * b;
}
}
pragma solidity ^0.4.13;
/**
* @title Shareable
* @dev inheritable "property" contract that enables methods to be protected by requiring the
* acquiescence of either a single, or, crucially, each of a number of, designated owners.
* @dev Usage: use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by some number (specified in constructor) of the set of owners (specified in the constructor) before the interior is executed.
*/
contract Shareable {
// struct for the status of a pending operation.
struct PendingState {
uint256 yetNeeded;
uint256 ownersDone;
uint256 index;
}
// the number of owners that must confirm the same operation before it is run.
uint256 public required;
// list of owners
address[256] owners;
// index on the list of owners to allow reverse lookup
mapping(address => uint256) ownerIndex;
// the ongoing operations.
mapping(bytes32 => PendingState) pendings;
bytes32[] pendingsIndex;
// this contract only has six types of events: it can accept a confirmation, in which case
// we record owner and operation (hash) alongside it.
event Confirmation(address owner, bytes32 operation);
event Revoke(address owner, bytes32 operation);
// simple single-sig function modifier.
modifier onlyOwner {
require(isOwner(msg.sender));
_;
}
/**
* @dev Modifier for multisig functions.
* @param _operation The operation must have an intrinsic hash in order that later attempts can be
* realised as the same underlying operation and thus count as confirmations.
*/
modifier onlymanyowners(bytes32 _operation) {
if (confirmAndCheck(_operation)) {
_;
}
}
/**
* @dev Constructor is given the number of sigs required to do protected "onlymanyowners"
* transactions as well as the selection of addresses capable of confirming them.
* @param _owners A list of owners.
* @param _required The amount required for a transaction to be approved.
*/
function Shareable(address[] _owners, uint256 _required) {
owners[1] = msg.sender;
ownerIndex[msg.sender] = 1;
for (uint256 i = 0; i < _owners.length; ++i) {
owners[2 + i] = _owners[i];
ownerIndex[_owners[i]] = 2 + i;
}
required = _required;
require(required <= owners.length);
}
/**
* @dev Revokes a prior confirmation of the given operation.
* @param _operation A string identifying the operation.
*/
function revoke(bytes32 _operation) external {
uint256 index = ownerIndex[msg.sender];
// make sure they're an owner
if (index == 0) {
return;
}
uint256 ownerIndexBit = 2**index;
var pending = pendings[_operation];
if (pending.ownersDone & ownerIndexBit > 0) {
pending.yetNeeded++;
pending.ownersDone -= ownerIndexBit;
Revoke(msg.sender, _operation);
}
}
/**
* @dev Gets an owner by 0-indexed position (using numOwners as the count)
* @param ownerIndex uint256 The index of the owner
* @return The address of the owner
*/
function getOwner(uint256 ownerIndex) external constant returns (address) {
return address(owners[ownerIndex + 1]);
}
/**
* @dev Checks if given address is an owner.
* @param _addr address The address which you want to check.
* @return True if the address is an owner and fase otherwise.
*/
function isOwner(address _addr) constant returns (bool) {
return ownerIndex[_addr] > 0;
}
/**
* @dev Function to check is specific owner has already confirme the operation.
* @param _operation The operation identifier.
* @param _owner The owner address.
* @return True if the owner has confirmed and false otherwise.
*/
function hasConfirmed(bytes32 _operation, address _owner) constant returns (bool) {
var pending = pendings[_operation];
uint256 index = ownerIndex[_owner];
// make sure they're an owner
if (index == 0) {
return false;
}
// determine the bit to set for this owner.
uint256 ownerIndexBit = 2**index;
return !(pending.ownersDone & ownerIndexBit == 0);
}
/**
* @dev Confirm and operation and checks if it's already executable.
* @param _operation The operation identifier.
* @return Returns true when operation can be executed.
*/
function confirmAndCheck(bytes32 _operation) internal returns (bool) {
// determine what index the present sender is:
uint256 index = ownerIndex[msg.sender];
// make sure they're an owner
require(index != 0);
var pending = pendings[_operation];
// if we're not yet working on this operation, switch over and reset the confirmation status.
if (pending.yetNeeded == 0) {
// reset count of confirmations needed.
pending.yetNeeded = required;
// reset which owners have confirmed (none) - set our bitmap to 0.
pending.ownersDone = 0;
pending.index = pendingsIndex.length++;
pendingsIndex[pending.index] = _operation;
}
// determine the bit to set for this owner.
uint256 ownerIndexBit = 2**index;
// make sure we (the message sender) haven't confirmed this operation previously.
if (pending.ownersDone & ownerIndexBit == 0) {
Confirmation(msg.sender, _operation);
// ok - check if count is enough to go ahead.
if (pending.yetNeeded <= 1) {
// enough confirmations: reset and run interior.
delete pendingsIndex[pendings[_operation].index];
delete pendings[_operation];
return true;
} else {
// not enough: record that this owner in particular confirmed.
pending.yetNeeded--;
pending.ownersDone |= ownerIndexBit;
}
}
return false;
}
/**
* @dev Clear the pending list.
*/
function clearPending() internal {
uint256 length = pendingsIndex.length;
for (uint256 i = 0; i < length; ++i) {
if (pendingsIndex[i] != 0) {
delete pendings[pendingsIndex[i]];
}
}
delete pendingsIndex;
}
}
pragma solidity ^0.4.18;
import './BasicToken.sol';
import './ERC20.sol';
/**
* @title Standard ERC20 token
*
* @dev Implementation of the basic standard token.
* @dev https://github.com/ethereum/EIPs/issues/20
* @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
* https://github.com/OpenZeppelin/zeppelin-solidity/
*/
contract StandardToken is ERC20, BasicToken {
mapping (address => mapping (address => uint256)) internal allowed;
/**
* @dev Transfer tokens from one address to another
* @param _from address The address which you want to send tokens from
* @param _to address The address which you want to transfer to
* @param _value uint256 the amount of tokens to be transferred
*/
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
require(_to != address(0));
require(_value <= balances[_from]);
require(_value <= allowed[_from][msg.sender]);
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
Transfer(_from, _to, _value);
return true;
}
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
*
* Beware that changing an allowance with this method brings the risk that someone may use both the old
* and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
* race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
* @param _spender The address which will spend the funds.
* @param _value The amount of tokens to be spent.
*/
function approve(address _spender, uint256 _value) public returns (bool) {
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
/**
* @dev Function to check the amount of tokens that an owner allowed to a spender.
* @param _owner address The address which owns the funds.
* @param _spender address The address which will spend the funds.
* @return A uint256 specifying the amount of tokens still available for the spender.
*/
function allowance(address _owner, address _spender) public view returns (uint256) {
return allowed[_owner][_spender];
}
/**
* approve should be called when allowed[_spender] == 0. To increment
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
*/
function increaseApproval (address _spender, uint _addedValue) public returns (bool) {
allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
return true;
}
function decreaseApproval (address _spender, uint _subtractedValue) public returns (bool) {
uint oldValue = allowed[msg.sender][_spender];
if (_subtractedValue > oldValue) {
allowed[msg.sender][_spender] = 0;
} else {
allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
}
Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
return true;
}
}
pragma solidity ^0.4.18;
import "./StandardToken.sol";
import "./Ownable.sol";
contract VZToken is StandardToken, Ownable {
/* metadata */
string public constant NAME = "VectorZilla Token";
string public constant SYMBOL = "VZT";
string public constant VERSION = "0.5";
uint8 public constant DECIMALS = 18;
/* all accounts in wei */
uint256 public constant INITIAL_SUPPLY = 10000 * 10**18; //100000000 * 10**18;
uint256 public constant VECTORZILLA_RESERVE_VZT = 2500 * 10**18; //25000000 * 10**18;
// these three multi-sig addresses will be replaced on production:
address public constant VECTORZILLA_RESERVE = 0x76f458A8aBe327D79040931AC97f74662EF3CaD0;
// minimum VZT token to be transferred to make the gas worthwhile (avoid micro transfer), cannot be higher than minimal subscribed amount in crowd sale.
uint256 public token4Gas = 1*10**18;
// gas in wei to reimburse must be the lowest minimum 0.6Gwei * 80000 gas limit.
uint256 public gas4Token = 80000*0.6*10**9;
// minimum wei required in an account to perform an action (avg gas price 4Gwei * avg gas limit 80000).
uint256 public minGas4Accts = 80000*4*10**9;
// list of addresses that has transfer restriction.
mapping (address => bool) public accreditedList;
uint256 public NumOfAccredited = 0;
uint256 public accreditedDate = 1703543589; // Assume many years
event Withdraw(address indexed from, address indexed to, uint256 value);
event GasRebateFailed(address indexed to, uint256 value);
/**
* @dev Contructor that gives msg.sender all existing tokens.
*/
function VZToken(address _owner) public {
require(_owner != address(0));
totalSupply = INITIAL_SUPPLY;
balances[_owner] = INITIAL_SUPPLY - VECTORZILLA_RESERVE_VZT;
balances[VECTORZILLA_RESERVE] = VECTORZILLA_RESERVE_VZT;
owner = _owner;
}
/**
* @dev transfer token for a specified address
* @param _to The address to transfer to.
* @param _value The amount to be transferred.
*/
function transfer(address _to, uint256 _value) public returns (bool) {
require(canTransferTokens()); // Team tokens lock 1 year
require(_value > 0 && _value >= token4Gas); // do nothing if less than allowed minimum but do not fail
balances[msg.sender] = balances[msg.sender].sub(_value); // insufficient token balance would revert here inside safemath
balances[_to] = balances[_to].add(_value);
Transfer(msg.sender, _to, _value);
// Keep a minimum balance of gas in all sender accounts. It would not be executed if the account has enough ETH for next action.
if (this.balance > gas4Token && msg.sender.balance < minGas4Accts) {
// reimburse gas in ETH to keep a minimal balance for next transaction, use send instead of transfer thus ignore failed rebate(not enough ether to rebate etc.).
if (!msg.sender.send(gas4Token)) {
GasRebateFailed(msg.sender,gas4Token);
}
}
return true;
}
/*
Allow changes to accredited date.
*/
function setAccreditedDate(uint256 newAccreditedDate) public onlyOwner {
accreditedDate = newAccreditedDate;
}
/*
add the ether address to accredited list to put in transfer restrction.
*/
function addToAccreditedList(address _addr) external onlyOwner {
require(_addr != address(0));
require(!accreditedList[_addr]);
accreditedList[_addr] = true;
NumOfAccredited += 1;
}
/*
remove the ether address from accredited list to remove transfer restriction.
*/
function delFrAccreditedList(address _addr) external onlyOwner {
require(accreditedList[_addr]);
delete accreditedList[_addr];
NumOfAccredited -= 1;
}
// return true if buyer is an accredited
function isAccreditedlisted(address buyer) public view returns (bool) {
return accreditedList[buyer];
}
/* When necessary, adjust minimum VZT to transfer to make the gas worthwhile */
function setToken4Gas(uint newVZTAmount) public onlyOwner {
require(newVZTAmount > 0); // Upper bound is not necessary.
token4Gas = newVZTAmount;
}
/* Only when necessary such as gas price change, adjust the gas to be reimbursed on every transfer when sender account below minimum */
function setGas4Token(uint newGasInWei) public onlyOwner {
require(newGasInWei > 0 && newGasInWei <= 840000*10**9); // must be less than a reasonable gas value
gas4Token = newGasInWei;
}
/* When necessary, adjust the minimum wei required in an account before an reimibusement of fee is triggerred */
function setMinGas4Accts(uint minBalanceInWei) public onlyOwner {
require(minBalanceInWei > 0 && minBalanceInWei <= 840000*10**9); // must be less than a reasonable gas value
minGas4Accts = minBalanceInWei;
}
/* This unnamed function is called whenever the owner send Ether to fund the gas fees and gas reimbursement */
function() payable public onlyOwner {
}
/* Owner withdrawal for excessive gas fees deposited */
function withdrawToOwner (uint256 weiAmt) public onlyOwner {
require(weiAmt > 0); // do not allow zero transfer
msg.sender.transfer(weiAmt);
Withdraw(this, msg.sender, weiAmt); // signal the event for communication only it is meaningful
}
/* below are internal functions */
/*
VectorZilla and Accredited folks can only transfer tokens after accredited date.
*/
function canTransferTokens() internal view returns (bool) {
if (accreditedList[msg.sender]) {
return now >= accreditedDate;
} else {
return true;
}
}
}
pragma solidity ^0.4.18;
import "./SafeMath.sol";
import "./VZToken.sol";
import "./Ownable.sol";
import "./Pausable.sol";
import "./HasNoTokens.sol";
contract VZTPresale is Ownable, Pausable, HasNoTokens {
using SafeMath for uint256;
string public constant NAME = "VectorZilla Public Presale";
string public constant VERSION = "0.5";
VZToken token;
// this multi-sig address will be replaced on production:
address public constant VZT_WALLET = 0x4D9B157E1c2ed052560304ce10E81ec67AEAbbdF;
uint256 public startDate = 1514764800; //1515974400; // January 15, 2018 5:30 AM UTC
uint256 public endDate = 1517788800; // Febuary 5, 2018 5:30 AM UTC
uint256 public weiRaised = 0; // total amount of Ether raised in wei
uint256 public purchaserCount = 0; // total number of purchasers purchased VZT
uint256 public tokensSold = 0; // total number of VZT tokens sold
uint256 public numWhitelisted = 0; // total number whitelisted
/* if the minimum funding goal in wei is not reached, purchasers may withdraw their funds */
uint256 public constant MIN_FUNDING_GOAL = 2 * 10 ** 18; //200 * 10 ** 18;
uint256 public constant PRESALE_TOKEN_SOFT_CAP = 2500 * 10**18; //1875000 * 10 ** 18; // presale ends 48 hours after soft cap of 1,875,000 VZT is reached
uint256 public constant PRESALE_RATE = 1250; // presale price is 1 ETH to 1,250 VZT
uint256 public constant SOFTCAP_RATE = 1150; // presale price becomes 1 ETH to 1,150 VZT after softcap is reached
uint256 public constant PRESALE_TOKEN_HARD_CAP = 5000 * 10**18; //5900000 * 10 ** 18; // presale token hardcap
uint256 public constant MIN_PURCHASE = 0.25 * 10 ** 17; // minimum purchase is 0.25 ETH to make the gas worthwhile
uint256 public constant MIN_VZT_PURCHASE = 1150 * 10 ** 18; // minimum token purchase is 100 or 0.1 ETH
bool public isFinalized = false; // it becomes true when token sale is completed
bool public publicSoftCapReached = false; // it becomes true when public softcap is reached
/** the amount of ETH in wei each address has purchased in this crowdsale */
mapping(address => uint256) public purchasedAmountOf;
/** the amount of tokens this crowdsale has credited for each purchaser address */
mapping(address => uint256) public tokenAmountOf;
/** this becomes true when crowdsale has distributed purchased tokens with bonus for each purchaser address */
mapping(address => bool) public tokenDistributed;
/** the amount of leftover tokens this crowdsale has distributed for each purchaser address */
mapping(address => uint256) public leftoverAmountOf;
/** this becomes true when crowdsale has distributed leftover tokens for each purchaser address */
mapping(address => bool) public leftoverDistributed;
// purchaser wallets
address[] public purchasers;
// list of addresses that can purchase
mapping(address => bool) public whitelist;
/**
* event for token purchase logging
* @param purchaser who paid for the tokens
* @param beneficiary who got the tokens
* @param value weis paid for purchase
* @param amount amount of tokens purchased
*/
event TokenPurchase(address indexed purchaser, address indexed beneficiary, uint256 value, uint256 amount);
// event logging for token sale finalized
event Finalized();
// event logging for softcap reached
event SoftCapReached();
// event logging for funds transfered to VectorZilla multi-sig wallet
event FundsTransferred();
// event logging for each individual refunded amount
event Refunded(address indexed beneficiary, uint256 weiAmount);
// event logging for each individual distributed token + bonus
event TokenDistributed(address indexed purchaser, uint256 tokenAmt);
// event logging for each individual distributed leftover
event LeftoverTokenDistributed(address indexed purchaser, uint256 tokenAmt);
/*
Constructor to initialize everything.
*/
function VZTPresale(address _token, address _owner) public {
require(_token != address(0));
require(_owner != address(0));
token = VZToken(_token);
owner = _owner;
// default owner
tokenAmountOf[owner] = PRESALE_TOKEN_HARD_CAP;
// maximum tokens to be sold in presale
}
/*
default function to buy tokens.
*/
function() payable public whenNotPaused {
// stop if no more token is allocated for sale
require(isPresale());
// stop if address not valid
require(!hasSoldOut());
// stop if the purchase is too small
require(msg.sender != address(0));
// no purchase unless whitelisted
require(msg.value >= MIN_PURCHASE);
// do public presale
require(isWhitelisted(msg.sender));
purchasePresale(msg.sender, msg.value);
}
function setDates(uint256 newStartDate, uint256 newEndDate) public onlyOwner {
startDate = newStartDate;
endDate = newEndDate;
}
function setTokenContract(address _token) external onlyOwner {
require(token != address(0));
token = VZToken(_token);
}
/*
add the ether address to whitelist to enable purchase of token.
*/
function addToWhitelist(address buyer) external onlyOwner {
require(buyer != address(0));
if (!isWhitelisted(buyer)) {
whitelist[buyer] = true;
numWhitelisted += 1;
}
}
/*
remove the ether address from whitelist in case a mistake was made.
*/
function delFrWhitelist(address buyer) public onlyOwner {
// Valid address
require(buyer != address(0));
// No purchase yet.
require(purchasedAmountOf[buyer] <= 0);
if (isWhitelisted(buyer)) {
delete whitelist[buyer];
numWhitelisted -= 1;
}
}
// return true if buyer is whitelisted
function isWhitelisted(address buyer) public view returns (bool) {
return whitelist[buyer];
}
function purchasePresale(address buyer, uint256 value) internal {
uint256 tokens = 0;
// still under soft cap
if (!publicSoftCapReached) {
// 1 ETH for 1,250 VZT
tokens = value * PRESALE_RATE;
// get less if over softcap
if (tokensSold + tokens > PRESALE_TOKEN_SOFT_CAP) {
uint256 availablePresaleTokens = PRESALE_TOKEN_SOFT_CAP - tokensSold;
uint256 softCapTokens = (value - (availablePresaleTokens / PRESALE_RATE)) * SOFTCAP_RATE;
tokens = availablePresaleTokens + softCapTokens;
// process presale at 1 ETH to 1,150 VZT
processSale(buyer, value, tokens, SOFTCAP_RATE);
// public soft cap has been reached
publicSoftCapReached = true;
// signal the event for communication
SoftCapReached();
} else {
// process presale @PRESALE_RATE
processSale(buyer, value, tokens, PRESALE_RATE);
}
} else {
// 1 ETH to 1,150 VZT
tokens = value * SOFTCAP_RATE;
// process presale at 1 ETH to 1,150 VZT
processSale(buyer, value, tokens, SOFTCAP_RATE);
}
}
/*
process sale at determined price.
*/
function processSale(address buyer, uint256 value, uint256 vzt, uint256 vztRate) internal {
uint256 vztOver = 0;
uint256 excessEthInWei = 0;
uint256 paidValue = value;
uint256 purchasedVzt = vzt;
if (tokensSold + purchasedVzt > PRESALE_TOKEN_HARD_CAP) {// if maximum is exceeded
// find overage
vztOver = tokensSold + purchasedVzt - PRESALE_TOKEN_HARD_CAP;
// overage ETH to refund
excessEthInWei = vztOver / vztRate;
// adjust tokens purchased
purchasedVzt = purchasedVzt - vztOver;
// adjust Ether paid
paidValue = paidValue - excessEthInWei;
}
if (tokenAmountOf[buyer] == 0) {
// count new purchasers
purchaserCount++;
purchasers.push(buyer);
}
// deduct VZT from Vectorzilla account
tokenAmountOf[owner] = tokenAmountOf[owner].sub(purchasedVzt);
// record VZT on purchaser account
tokenAmountOf[buyer] = tokenAmountOf[buyer].add(purchasedVzt);
// record ETH paid
purchasedAmountOf[buyer] = purchasedAmountOf[buyer].add(paidValue);
// total ETH raised
weiRaised += paidValue;
// total VZT sold
tokensSold += purchasedVzt;
// signal the event for communication
TokenPurchase(buyer, buyer, paidValue, purchasedVzt);
// transfer must be done at the end after all states are updated to prevent reentrancy attack.
if (excessEthInWei > 0) {
// refund overage ETH
buyer.transfer(excessEthInWei);
// signal the event for communication
Refunded(buyer, excessEthInWei);
}
}
/*
default function to buy tokens.
*/
function payableInFiatEth(address buyer, uint256 value) external onlyOwner {
require(isPresale());
// stop if no more token is allocated for sale
require(!hasSoldOut());
// stop if address not valid
require(buyer != address(0));
// stop if the purchase is too small
require(value >= MIN_PURCHASE);
// no purchase unless whitelisted
require(isWhitelisted(buyer));
// do public presale
purchasePresale(buyer, value);
}
/*
Check to see if this is public presale.
*/
function isPresale() public view returns (bool) {
return !isFinalized && now >= startDate && now <= endDate;
}
/*
check if allocated has sold out.
*/
function hasSoldOut() public view returns (bool) {
return PRESALE_TOKEN_HARD_CAP - tokensSold < MIN_VZT_PURCHASE;
}
/*
Check to see if the crowdsale end date has passed or if all tokens allocated for sale has been purchased.
*/
function hasEnded() public view returns (bool) {
return now > endDate || (PRESALE_TOKEN_HARD_CAP - tokensSold < MIN_VZT_PURCHASE);
}
/*
Determine if the minimum goal in wei has been reached.
*/
function isMinimumGoalReached() public view returns (bool) {
return weiRaised >= MIN_FUNDING_GOAL;
}
/*
Called after crowdsale ends, to do some extra finalization work.
*/
function finalize() public onlyOwner {
require(!isFinalized);
// do nothing if finalized
require(hasEnded());
// crowdsale must have ended
if (isMinimumGoalReached()) {
VZT_WALLET.transfer(this.balance);
// transfer to VectorZilla multisig wallet
FundsTransferred();
// signal the event for communication
}
isFinalized = true;
// mark as finalized
Finalized();
// signal the event for communication
}
/*
purchaser requesting a refund if minimum goal not reached.
*/
function claimRefund() external {
require(isFinalized && !isMinimumGoalReached());
// cannot refund unless authorized
uint256 depositedValue = purchasedAmountOf[msg.sender];
// ETH to refund
purchasedAmountOf[msg.sender] = 0;
// assume all refunded
// transfer must be called only after purchasedAmountOf is updated to prevent reentrancy attack.
msg.sender.transfer(depositedValue);
// refund all ETH
Refunded(msg.sender, depositedValue);
// signal the event for communication
}
/*
send refund to purchaser if minimum goal not reached.
*/
function sendRefund(address buyer) external onlyOwner {
// cannot refund unless authorized
require(isFinalized && !isMinimumGoalReached());
// ETH to refund
uint256 depositedValue = purchasedAmountOf[buyer];
// assume all refunded
purchasedAmountOf[buyer] = 0;
// transfer must be called only after purchasedAmountOf is updated to prevent reentrancy attack.
// refund all ETH
buyer.transfer(depositedValue);
// signal the event for communication
Refunded(buyer, depositedValue);
}
/*
For the convenience of crowdsale interface to find current discount tier.
*/
function getTier() public view returns (uint256) {
// Assume presale top tier discount
uint256 tier = 1;
if (now >= startDate && now < endDate && getSoftCapReached()) {
// tier 2 discount
tier = 2;
}
return tier;
}
/*
For the convenience of crowdsale interface to present status info.
*/
function getSoftCapReached() public view returns (bool) {
return publicSoftCapReached;
}
/*
For the convenience of crowdsale interface to present status info.
*/
function getPresaleStatus() public view returns (uint256[3]) {
// 0 - presale not started
// 1 - presale started
// 2 - presale ended
if (now < startDate)
return ([0, startDate, endDate]);
else if (now <= endDate && !hasEnded())
return ([1, startDate, endDate]);
else
return ([2, startDate, endDate]);
}
}
pragma solidity ^0.4.18;
import './SafeMath.sol';
import "./VZToken.sol";
import "./Ownable.sol";
import "./HasNoTokens.sol";
import "./VZTPresale.sol";
contract VZTPresaleDist is Ownable, HasNoTokens {
using SafeMath for uint256;
string public constant NAME = "VectorZilla token distribution";
string public constant VERSION = "0.3";
VZToken token;
VZTPresale preSale;
uint256 public purchaserCount = 0; // total number of purchasers purchased VZT
uint256 public purchaserDistCount = 0; // total number of purchasers received purchased VZT + bonus
uint256 public tokensSold = 0;
uint256 public minVztPurchase = 0;
uint256 public tokenHardCap = 0;
/** this becomes true when crowdsale has distributed purchased tokens with bonus for each purchaser address */
mapping (address => bool) public tokenDistributed;
event TokenDistributed(address indexed purchaser, uint256 tokenAmt); // event logging for each individual distributed token + bonus
/*
Constructor to initialize everything.
*/
function VZTPresaleDist (address _presale, address _token, address _owner) public {
if (_owner == address(0)) {
_owner = msg.sender;
}
require(_presale != address(0));
require(_owner != address(0));
token = VZToken(_token);
owner = _owner; // default owner
preSale = VZTPresale(_presale);
purchaserCount = preSale.purchaserCount(); // initialize to all purchaser count
tokensSold = preSale.tokensSold(); // initialize token sold from crowd sale
minVztPurchase = preSale.MIN_VZT_PURCHASE();
tokenHardCap = preSale.PRESALE_TOKEN_HARD_CAP();
}
function setTokenContract(address _token) external onlyOwner {
require(token != address(0));
token = VZToken(_token);
}
/*
Distribute tokens purchased with bonus.
*/
function distributeTokensFor(address purchaser) external onlyOwner {
require(token != address(0));
require(preSale.isFinalized());
require(preSale.isMinimumGoalReached());
require(preSale.tokenAmountOf(purchaser) > 0);
require(!tokenDistributed[purchaser]);
tokenDistributed[purchaser] = true; // token + bonus distributed
uint256 tokenPurchased = preSale.tokenAmountOf(purchaser);
purchaserDistCount++; // one more purchaser received token + bonus
// transfer the purchased tokens + bonus
token.transfer(purchaser, tokenPurchased);
// signal the event for communication
TokenDistributed(purchaser, tokenPurchased);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment