Skip to content

Instantly share code, notes, and snippets.

@darrendbutler
Created November 14, 2018 20:45
Show Gist options
  • Select an option

  • Save darrendbutler/2e33a3b1d2ec763b9c40b6487955778f to your computer and use it in GitHub Desktop.

Select an option

Save darrendbutler/2e33a3b1d2ec763b9c40b6487955778f 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.4.25+commit.59dbf8f1.js&optimize=true&gist=
pragma solidity ^0.4.24;
//CrowdSale contract knows the function signatures of IERC20
// because it is imported here
//Call functions from IERC20 like token.transfer(...).
import "./IERC20.sol";
import "./SafeMath.sol";
//The crowd sale contract allows a user to send ether directly to the
//contract's address and receive tokens in return.
contract Crowdsale {
using SafeMath for uint256;
uint256 private cap; // maximum amount of ether to be raised
//once the contract receives the preset amount of ether,
//the sale ends and no one can buy more tokens
uint256 private weiRaised; // current amount of wei raised in the contract
uint256 private rate; // price in wei per smallest unit of token (e.g. 1 wei = 10 smallet unit of a token)
address private wallet; // wallet to hold the ethers raised. ether can be transfered her
IERC20 private token; // address of erc20 tokens
//Rate and wallet are passed into the constructor
//Address of the token is passed into contructor
/**
* 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 TokensPurchased(
address indexed purchaser,
address indexed beneficiary,
uint256 value,
uint256 amount
);
// -----------------------------------------
// Public functions (DO NOT change the interface!)
// -----------------------------------------
/**
* @param _rate Number of token units a buyer gets per wei
* @dev The rate is the conversion between wei and the smallest and indivisible token unit.
* @param _wallet Address where collected funds will be forwarded to
* @param _token Address of the token being sold
*/
constructor(uint256 _rate, address _wallet, IERC20 _token, uint256 _cap, uint256 _weiRaised) public {
// TODO: Your Code Here
rate = _rate;
wallet = _wallet;
token = _token;
cap = _cap;
weiRaised = _weiRaised;
}
/**
* @dev Fallback function for users to send ether directly to contract address
* It should call the buyTokens function
*/
//Fallback function function is invoked when a user tries to send ether
//directly to a smart contract address
//Call the
function() external payable {
//Call the buyTokens function.
//Pass in the address of the buyer
buyTokens(msg.sender);
}
//determine how many tokens the user will get based on the amount
//of ethers they've sent
// Let's say 1 wei = 10 smallet unit of a token
//Retreive the amount of ethers sent with msg.value
//Transfer the amount of token to the user by
//invoking the transfer() function in the ERC20 contract
//The transfer function in the ERC20 contract transfers tokens
//The transfer function on addrersses transfers wei
//beneficiary will get tokens once they've bought them
function buyTokens(address beneficiary) public payable {
// - Calculate number of tokens
//For every unit of wei the user gets some amount of tokens
//The amount of tokens the user will get is
// equal to the number the amount of wei being sent times the rate
//(number of wei for every token)
uint256 buyerTokens = msg.value.mul(rate);
// - Validate any conditions
//Make sure that the buyer is sending some wei
require(msg.value > 0, "Invalid amount sent");
//Make sure that it hasn't reached the cap
require(capReached() == false, "The cap has already been reached. No more ether can be received");
//Make sure that the wei being sent doesn't exceed the cap
require(msg.value <= cap, "The amount being sent exceeds the cap");
//Ensure we have enough tokens in stock to complete this request
//Check that the buyerTokens (tokens being requested) is less than
// or equal to the tokens at the address stored in "tokens"
require(buyerTokens <= token.balanceOf(address(this)), "number of tokens requested exceeds the amount of available tokens");
//Make sure the address wei is going to is valid
require(beneficiary != 0, "Invalid beneficiary address");
// - Update any states
//Receive pmt and give bidder their tokens
//Add the wei payed to the weiRaised in the contract
weiRaised = weiRaised.add(msg.value);
// - Forward the wei payed to the beneificiary's wallet
wallet.transfer(msg.value);
// - Transfer tokens and emit event
token.transfer(beneficiary, buyerTokens);
emit TokensPurchased(msg.sender, beneficiary, msg.value, buyerTokens);
}
/**
* @dev Checks whether the cap has been reached.
* @return Whether the cap was reached
*/
function capReached() public view returns (bool) {
// TODO: Your Code Here
bool maxedOut;
if(weiRaised >= cap ){
//If the weiRaised is equal to or greater than than cap, then
// then the cap has been reached
maxedOut = true;
} else {
maxedOut = false;
}
return maxedOut;
}
// -----------------------------------------
// Internal functions (you can write any other internal helper functions here)
// -----------------------------------------
}
pragma solidity ^0.4.24;
import "./IERC20.sol";
import "./SafeMath.sol";
/**
* @title Standard ERC20 token
* @dev Implementation of the basic standard token.
*/
contract ERC20 is IERC20 {
using SafeMath for uint256;
//_balances: an address points to an integer that represnts
//the number of tokens a user address owns
//Update the mapping when a token is transferred
mapping (address => uint256) internal _balances;
//An address that represents the owner of some token points to another
// adrress that has been authorized to spend tokens by the owner, which points
//to an integer represnetation of tokens
//(The owner's address points to the spender's address that points to
//the amount of tokens to be spent)
//Access it like myMapping[outerKey][innerKey].
mapping (address => mapping (address => uint256)) internal _allowed;
//Keeps track of the total amount of tokens in the system
uint256 internal _totalSupply;
// -----------------------------------------
// Public Functions (DO NOT CHANGE!!)
// -----------------------------------------
/**
* @dev returns the Total number of tokens in existence
*/
function totalSupply() public view returns (uint256) {
// TODO: Your Code Here
return _totalSupply;
}
/**
* @dev Gets the balance of the specified address.
* @param owner (The address you want the balance of.)
* @return An uint256 representing the amount owned by the passed address.
*/
function balanceOf(address owner) public view returns (uint256) {
// TODO: Your Code Here
return _balances[owner];
}
/**
* @dev Function to check the amount of tokens that an owner allows
* a spender to spend
* @param owner address is the address which owns the funds.
* @param spender address is the address which will spend the funds.
* @return A uint256 (integer) the amount of tokens the spender can still
* spend.
*/
function allowance(address owner, address spender) public view returns(uint256) {
// TODO: Your Code Here
return _allowed[owner][spender];
}
/**
* @dev Allow the owner to tansfer tokens to another user
* @param to The address to transfer to.
* @param value The amount to be transferred.
* @return Should always return true if all conditions are met (if the owner
* has tokens. Otherwise throw exception using require statements.
*/
function transfer(address to, uint256 value) public returns (bool) {
// TODO: Your Code Here
//Require the balances is greater than or equal to the value of tokens
//being sent
require (_balances[msg.sender] >= value, "Insufficient tokens to transfer specified amount");
//Require that the adress is not a 0x0 address (it must be elligible)
require(to != address(0), "Invalid address used");
//Substract the value being transfered from the address of the owner
_balances[msg.sender] = _balances[msg.sender].sub(value);
//Add the tokens being transferred to the balance of the receiving address
_balances[to] = _balances[to].add(value);
//Log information of transfer to the blockchain using the Transfer event
//from IERC20
emit Transfer(msg.sender, to, value);
return true;
}
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
* Note that the owner (msg.sender) can approve someone to spend tokens that they do not yet have.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return Should always return true if success. Otherwise throw exception.
*/
function approve(address spender, uint256 value) public returns (bool) {
// TODO: Your Code Here
//Only allow the owner to approve an address to spend
require(msg.sender != spender);
//Make sure the spender address is valid
require(spender != address(0), "Invalid spender address");
//Catch negative numbers or zero
require(value > 0, "Value to be spent must be greater than 0");
//Set the amount of tokens that can be spent.
value = _allowed[msg.sender][spender];
//Log the approval information to the blockchain
emit Approval(msg.sender, spender, value);
return true;
}
/**
* @dev Transfer tokens from one address to another
* A spender will call to spend an owner's token
* @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) {
// TODO: Your Code Here
//First check that the receiving address is valid
require(to != address(0));
//Check that the value being sent is greater than 0
require(value > 0);
//check that the spender is approved by the owner
//Check that the value being spent is greater than or equal the
//value allowed by the owner
require(_allowed[from][msg.sender] >= value, "You are not allowed to spend that many tokens.");
//check that the owner has enough tokens to spend
//The balance associated with address "from" must be greater than or equal to value being spent
require(_balances[from] >= value, "Owner has insufficient tokens");
//Substract the value of tokens being transfered from the owners's balance
_balances[from] = _balances[from].sub(value);
//Add the value of token being transfered to the receiving address balance
_balances[to] = _balances[to].add(value);
//Substract the value of tokens being transferred from the
//amount the spender is allowed to spender
_allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value);
//transfer the tokens to the receiving address
to.transfer(value);
//check
//update state
//Log the transfer information to the blockchain
emit Transfer(from, to, value);
}
// -----------------------------------------
// Internal functions (you can write any other internal helper functions here)
// -----------------------------------------
}
pragma solidity ^0.4.24;
import "./ERC20.sol";
contract ERC20Test is ERC20 {
address public owner;
constructor() public {
owner = msg.sender;
}
/**
* @dev Function that mints an amount of the token and assigns it to
* an account. This encapsulates the modification of balances such that the
* proper events are emitted.
* @param account The account that will receive the created tokens.
* @param amount The amount that will be created.
*/
function mint(address account, uint256 amount) public {
require(msg.sender == owner);
require(account != 0);
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
}
pragma solidity ^0.4.24;
/**
* @title ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
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);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
pragma solidity ^0.4.24;
/**
* @title SafeMath
* @dev Math operations with safety checks that revert on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, reverts on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0); // Solidity only automatically asserts 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 Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Adds two numbers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
/**
* @dev Divides two numbers and returns the remainder (unsigned integer modulo),
* reverts when dividing by zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment