Skip to content

Instantly share code, notes, and snippets.

@Kotomanga
Created August 21, 2018 13:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kotomanga/e76046d6f4356928434537686dba39ed to your computer and use it in GitHub Desktop.
Save Kotomanga/e76046d6f4356928434537686dba39ed 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.24+commit.e67f0147.js&optimize=true&gist=
pragma solidity ^0.4.13;
import "./owned.sol";
import "./FixedSupplyToken.sol";
contract Exchange is owned {
///////////////////////
// GENERAL STRUCTURE //
///////////////////////
struct Offer{
uint amount;
address who;
}
struct OrderBook{
uint higherPrice;
uint lowerPrice;
mapping (uint => Offer) offers;
uint offers_keys;
uint offers_length;
}
struct Token {
address tokenContract;
string symbolName;
mapping(uint => OrderBook) buyBook;
uint curBuyPrice;
uint lowestBuyPrice;
uint amountBuyPrices;
mapping (uint => OrderBook) sellBook;
uint curSellPrice;
uint highestSellPrice;
uint amountSellPrices;
}
mapping (uint => Token) tokens;
uint8 symbolNameIndex;
//////////////
// BALANCES //
//////////////
mapping(address => mapping(uint8 => uint)) tokenBalanceForAddress;
mapping(address => uint) balanceEthForAddress;
////////////
// EVENTS //
////////////
//EVENTS for Deposit/withdrawal
event DepositForTokenReceived(address indexed _from, uint indexed _symbolIndex, uint _amount, uint _timestamp);
event WithdrawalToken(address indexed _to, uint indexed _symbolIndex, uint _amount, uint _timestamp);
event DepositForEthReceived(address indexed _from, uint _amount, uint _timestamp);
event WithdrawalEth(address indexed _to, uint _amount, uint _timestamp);
//events for orders
event LimitSellOrderCreated(uint indexed _symbolIndex, address indexed _who, uint _amountTokens, uint _priceInWei, uint _orderKey);
event SellOrderFulfilled(uint indexed _symbolIndex, uint _amount, uint _priceInWei, uint _orderKey);
event SellOrderCanceled(uint indexed _symbolIndex, uint _priceInWei, uint _orderKey);
event LimitBuyOrderCreated(uint indexed _symbolIndex, address indexed _who, uint _amountTokens, uint _priceInWei, uint _orderKey);
event BuyOrderFulfilled(uint indexed _symbolIndex, uint _amount, uint _priceInWei, uint _orderKey);
event BuyOrderCanceled(uint indexed _symbolIndex, uint _priceInWei, uint _orderKey);
//events for management
event TokenAddedToSystem(uint _symbolIndex, string _token, uint _timestamp);
//////////////////////////////////
// DEPOSIT AND WITHDRAWAL ETHER //
//////////////////////////////////
function depositEther() payable {
require(balanceEthForAddress[msg.sender] + msg.value >= balanceEthForAddress[msg.sender]);
balanceEthForAddress[msg.sender] += msg.value;
}
function withdrawEther(uint amountInWei){
require(balanceEthForAddress[msg.sender] - amountInWei >= 0);
require(balanceEthForAddress[msg.sender] - amountInWei <= balanceEthForAddress[msg.sender]);
balanceEthForAddress[msg.sender] -= amountInWei;
msg.sender.transfer(amountInWei);
}
function getEthBalanceInWei() constant returns (uint){
return balanceEthForAddress[msg.sender];
}
//////////////////////
// TOKEN MANAGEMENT //
//////////////////////
function addToken(string symbolName, address erc20TokenAddress) onlyOwner {
require(!hasToken(symbolName));
symbolNameIndex++;
tokens[symbolNameIndex].symbolName = symbolName;
tokens[symbolNameIndex].tokenContract = erc20TokenAddress;
}
function hasToken(string symbolName) constant returns(bool){
uint8 index = getSymbolIndex(symbolName);
if(index == 0) {
return false;
}
return true;
}
function getSymbolIndex(string symbolName) internal returns(uint8) {
for(uint8 i = 1; i <= symbolNameIndex; i++){
if(stringsEqual(tokens[i].symbolName, symbolName)){
return i;
}
}
return 0;
}
function getSymbolIndexOrThrow(string symbolName) returns (uint8) {
uint8 index = getSymbolIndex(symbolName);
require(index > 0);
return index;
}
//////////////////////////////////
// DEPOSIT AND WITHDRAWAL TOKEN //
//////////////////////////////////
function depositToken(string symbolName, uint amount) {
uint8 symbolNameIndex = getSymbolIndexOrThrow(symbolName);
require(tokens[symbolName].tokenContract != address(0));
ERC20Interface token = ERC20Interface(tokens[symbolNameIndex].tokenContract);
require(token.transferFrom(msg.sender, address(this), amount) == true);
require(tokenBalanceForAddress[msg.sender][symbolNameIndex] + amount >= balanceEthForAddress);
tokenBalanceForAddress[msg.sender][symbolNameIndex] += amount;
}
function withdrawToken(string symbolName, uint amount) {
uint8 symbolNameIndex = getSymbolIndexOrThrow(symbolName);
require(tokens[symbolNameIndex].tokenContract != address(0));
ERC20Interface token = ERC20Interface(tokens[symbolNameIndex].tokenContract);
require(tokenBalanceForAddress[msg.sender][symbolName] - amount >= 0);
require(tokenBalanceForAddress[msg.sender][symbolName] - amount <= tokenBalanceForAddress );
tokenBalanceForAddress[msg.sender][symbolNameIndex] -= amount;
require(token.transfer(msg.sender, amount) == true);
}
function getBalance(string symbolName) constant returns (uint) {
uint8 symbolNameIndex = getSymbolIndexOrThrow(symbolName);
return tokenBalanceForAddress[msg.sender][symbolNameIndex];
}
/////////////////////////////
// ORDER BOOK - BID ORDERS //
/////////////////////////////
function getBuyOrderBook(string symbolName) constant returns (uint[], uint[]) {
uint8 tokenNameIndex = getSymbolIndexOrThrow(symbolName);
uint[] memory arrPricesBuy = new uint[](tokens[tokenNameIndex].amountBuyPrices);
uint[] memory arrVolumesBuy = new uint[](tokens[tokenNameIndex].amountBuyPrices);
uint whilePrice = tokens[tokenNameIndex].lowestBuyPrice;
uint counter = 0;
if(tokens[tokenNameIndex].curBuyPrice > 0 ){
while (whilePrice <= tokens[tokenNameIndex].curBuyPrice){
arrPricesBuy[counter] = whilePrice;
uint volumeAtPrice = 0;
uint offers_keys = 0;
offers_keys = tokens[tokenNameIndex].buyBook[whilePrice].offers_keys;
while(offers_keys <= tokens[tokenNameIndex].buyBook[whilePrice].offers_length) {
volumeAtPrice += tokens[tokenNameIndex].buyBook[whilePrice].offers[offers_keys].amount;
offers_keys++;
}
arrVolumesBuy[counter] = volumeAtPrice;
// next whilePrice
if(whilePrice == tokens[tokenNameIndex].buyBook[whilePrice].higherPrice){
break;
} else {
whilePrice = tokens[tokenNameIndex].buyBook[whilePrice].higherPrice;
}
counter++;
}
}
return (arrPricesBuy, arrVolumesBuy);
}
/////////////////////////////
// ORDER BOOK - ASK ORDERS //
/////////////////////////////
function getSellOrderbook(string symbolName) constant returns(uint[], uint[]) {
uint8 tokenNameIndex = getSymbolIndexOrThrow(symbolName);
uint[] memory arrPricesSell = new uint[](tokens[tokenNameIndex].amountSellPrices);
uint[] memory arrVolumesSell = new uint[](tokens[tokenNameIndex].amountSellPrices);
uint sellWhilePrice = tokens[tokenNameIndex].curSellPrice;
uint sellCounter = 0;
if(tokens[tokenNameIndex].curSellPrice > 0){
while (sellWhilePrice <= tokens[tokenNameIndex].highestSellPrice){
arrPricesSell[sellCounter] = sellWhilePrice;
uint sellVolumeAtPrice = 0;
uint sell_offers_key = 0;
sell_offers_key = tokens[tokenNameIndex].sellBook[sellWhilePrice].offers_keys;
while(sell_offers_key <= tokens[tokenNameIndex].sellBook[sellWhilePrice].offers_length){
sellVolumeAtPrice += tokens[tokenNameIndex].sellBook[sellWhilePrice].offers[sell_offers_key].amount;
sell_offers_key++;
}
arrVolumesSell[sellCounter] = sellVolumeAtPrice;
//next whilePrice
if(tokens[tokenNameIndex].sellBook[sellWhilePrice].higherPrice == 0) {
break;
} else {
sellWhilePrice = tokens[tokenNameIndex].sellBook[sellWhilePrice].higherPrice;
}
sellCounter++;
}
}
// sell part
return (arrPricesSell, arrVolumesSell);
}
////////////////////////////
// NEW ORDER - BID ORDER //
///////////////////////////
function buyToken(string symbolName, uint priceInWei, uint amount){
uint tokenNameIndex = getSymbolIndexOrThrow(symbolName);
uint total_amount_ether_necessary = 0;
uint total_amount_ether_available = 0;
// if have enouhh ether, we ca, buy that:
total_amount_ether_necessary = amount * priceInWei;
// overflow check
require(total_amount_ether_necessary >= amount);
require(total_amount_ether_necessary >= priceInWei);
require(balanceEthForAddress[msg.sender] >= total_amount_ether_necessary);
require(balanceEthForAddress[msg.sender] - total_amount_ether_necessary >= 0);
// first deduct the amount of ether from our balance
balanceEthForAddress[msg.sender] -= total_amount_ether_necessary;
if(tokens[tokenNameIndex].amountSellPrices == 0 || tokens[tokenNameIndex].curSellPrice > priceInWei){
// limit order: we don't enouth amount to fulfill the amount
addBuyOffer(tokenNameIndex, priceInWei, amount, msg.sender);
LimitBuyOrderCreated(tokenNameIndex, msg.sender, amount, priceInWei, tokens[tokenNameIndex].buyBook[priceInWei].offers_length);
} else {
revert();
}
}
///////////////////////////
// BID LIMIT ORDER LOGIC //
///////////////////////////
function addBuyOffer(uint8 tokenIndex, uint priceInWei, uint amount, address who) internal {
tokens[tokenIndex].buyBook[priceInWei].offers_length++;
tokens[tokenIndex].buyBook[priceInWei].offers[tokens[tokenIndex].buyBook[priceInWei].offers_length] = Offer(amount, who);
if(tokens[tokenIndex].buyBook[priceInWei].offers_length == 1){
tokens[tokenIndex].buyBook[priceInWei].offers_keys = 1;
tokens[tokenIndex].amountBuyPrices++;
uint curBuyPrice = tokens[tokenIndex].lowestBuyPrice;
if(lowestBuyPrice == 0 || lowestBuyPrice > priceInWei) {
if(curBuyPrice == 0) {
tokens[tokenIndex].curBuyPrice = priceInWei;
tokens[tokenIndex].buyBook[priceInWei].higherPrice = priceInWei;
tokens[tokenIndex].buyBook[priceInWei].lowerPrice = 0;
} else {
tokens[tokenIndex].buyBook[lowestBuyPrice].lowerPrice = priceInWei;
tokens[tokenIndex].buyBook[priceInWei].higherPrice = lowerPrice;
tokens[tokenIndex].buyBook[priceInWei].lowerPrice = 0;
}
tokens[tokenIndex].lowestBuyPrice = priceInWei;
} else if(curBuyPrice < priceInWei) {
tokens[tokenIndex].buyBook[curBuyPrice].higherPrice = priceInWei;
tokens[tokenIndex].buyBook[priceInWei].higherPrice = priceInWei;
tokens[tokenIndex].buyBook[priceInWei].lowerPrice = curBuyPrice;
tokens[tokenIndex].curBuyPrice = priceInWei;
} else {
uint buyPrice = tokens[tokenIndex].curBuyPrice;
bool weFoundIt = false;
while(buyPrice > 0 && !weFoundIt){
if( buyPrice < priceInWei &&
tokens[tokenIndex].buyBook[buyPrice].higherPrice > priceInWei) {
tokens[tokenIndex].buyBook[priceInWei].lowerPrice = buyPrice;
tokens[tokenIndex].buyBook[priceInWei].higherPrice = tokens[tokenIndex].buyBook[buyPrice].higherPrice;
// set the higherPrice'd order-book entries lowerPrice to the current priceInWei
tokens[tokenIndex].buyBook[tokens[tokenIndex].buyBook[buyPrice].higherPrice].lowerPrice = priceInWei;
tokens[tokenIndex].buyBook[buyPrice].higherPrice = priceInWei;
weFoundIt = true;
}
buyPrice = tokens[tokenIndex].buyBook[buyPrice].lowerPrice;
}
}
}
}
////////////////////////////
// NEW ORDER - ASK ORDER //
///////////////////////////
function sellToken(string symbolName, uint priceInWei, uint amount) {
uint8 tokenNameIndex = getSymbolIndexOrThrow(symbolName);
uint total_amount_ether_necessary = 0;
uint total_amount_ether_available = 0;
if(tokens[tokenNameIndex].amountBuyPrices == 0 || tokens[tokenNameIndex].curBuyPrice < priceInWei){
total_amount_ether_necessary = amount * priceInWei;
//overflow check
require(total_amount_ether_necessary >= amount);
require(total_amount_ether_necessary >= priceInWei);
require(tokenBalanceForAddress[msg.sender][tokenNameIndex] >= amount);
require(tokenBalanceForAddress[msg.sender][tokenNameIndex] - amount >= 0);
require(balanceEthForAddress[msg.sender] + total_amount_ether_necessary >= balanceEthForAddress[msg.sender]);
// actually substract the amount of tokens it then
tokenBalanceForAddress[msg.sender][tokenNameIndex] -= amount;
// limit order: we don't have enough offers to fullfil the amount
}
}
///////////////////////////
// ASK LIMIT ORDER LOGIC //
///////////////////////////
//////////////////////////////
// CANCEL LIMIT ORDER LOGIC //
//////////////////////////////
////////////////////////////////
// STRING COMPARISON FUNCTION //
////////////////////////////////
function stringsEqual(string storage _a, string memory _b) internal returns (bool) {
bytes storage a = bytes(_a);
bytes memory b = bytes(_b);
if (a.length != b.length) {
return false;
}
// @todo unroll this loop
for (uint i = 0; i < a.length; i ++) {
if (a[i] != b[i]) {
return false;
}
}
return true;
}
}
pragma solidity ^0.4.8;
// ----------------------------------------------------------------------------------------------
// Sample fixed supply token contract
// Enjoy. (c) BokkyPooBah 2017. The MIT Licence.
// ----------------------------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// https://github.com/ethereum/EIPs/issues/20
contract ERC20Interface {
// Get the total token supply
function totalSupply() constant returns (uint256 totalSupply);
// Get the account balance of another account with address _owner
function balanceOf(address _owner) constant returns (uint256 balance);
// Send _value amount of tokens to address _to
function transfer(address _to, uint256 _value) returns (bool success);
// Send _value amount of tokens from address _from to address _to
function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
// Allow _spender to withdraw from your account, multiple times, up to the _value amount.
// If this function is called again it overwrites the current allowance with _value.
// this function is required for some DEX functionality
function approve(address _spender, uint256 _value) returns (bool success);
// Returns the amount which _spender is still allowed to withdraw from _owner
function allowance(address _owner, address _spender) constant returns (uint256 remaining);
// Triggered when tokens are transferred.
event Transfer(address indexed _from, address indexed _to, uint256 _value);
// Triggered whenever approve(address _spender, uint256 _value) is called.
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
contract FixedSupplyToken is ERC20Interface {
string public constant symbol = "FIXED";
string public constant name = "Example Fixed Supply Token";
uint8 public constant decimals = 0;
uint256 _totalSupply = 1000000;
// Owner of this contract
address public owner;
// Balances for each account
mapping (address => uint256) balances;
// Owner of account approves the transfer of an amount to another account
mapping (address => mapping (address => uint256)) allowed;
// Functions with this modifier can only be executed by the owner
modifier onlyOwner() {
if (msg.sender != owner) {
throw;
}
_;
}
// Constructor
function FixedSupplyToken() {
owner = msg.sender;
balances[owner] = _totalSupply;
}
function totalSupply() constant returns (uint256 totalSupply) {
totalSupply = _totalSupply;
}
// What is the balance of a particular account?
function balanceOf(address _owner) constant returns (uint256 balance) {
return balances[_owner];
}
// Transfer the balance from owner's account to another account
function transfer(address _to, uint256 _amount) returns (bool success) {
if (balances[msg.sender] >= _amount
&& _amount > 0
&& balances[_to] + _amount > balances[_to]) {
balances[msg.sender] -= _amount;
balances[_to] += _amount;
Transfer(msg.sender, _to, _amount);
return true;
}
else {
return false;
}
}
// Send _value amount of tokens from address _from to address _to
// The transferFrom method is used for a withdraw workflow, allowing contracts to send
// tokens on your behalf, for example to "deposit" to a contract address and/or to charge
// fees in sub-currencies; the command should fail unless the _from account has
// deliberately authorized the sender of the message via some mechanism; we propose
// these standardized APIs for approval:
function transferFrom(
address _from,
address _to,
uint256 _amount
) returns (bool success) {
if (balances[_from] >= _amount
&& allowed[_from][msg.sender] >= _amount
&& _amount > 0
&& balances[_to] + _amount > balances[_to]) {
balances[_from] -= _amount;
allowed[_from][msg.sender] -= _amount;
balances[_to] += _amount;
Transfer(_from, _to, _amount);
return true;
}
else {
return false;
}
}
// Allow _spender to withdraw from your account, multiple times, up to the _value amount.
// If this function is called again it overwrites the current allowance with _value.
function approve(address _spender, uint256 _amount) returns (bool success) {
allowed[msg.sender][_spender] = _amount;
Approval(msg.sender, _spender, _amount);
return true;
}
function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}
}
pragma solidity ^0.4.24;
contract JobList {
struct Job {
uint256 jobSalary;
string jobTitle;
string jobDescription;
bool salaryDelivred;
bool active;
bool inProgress;
address workerAddress;
address creatorAddress;
}
Job[] jobArray;
uint jobCount = 0;
uint finishedJobCount = 0;
uint workInprogressCount = 0;
mapping (uint => Job) jobs;
mapping (address => uint) myWorkInprogress;
event LogAddJob(string title, string desc, uint salary);
event LogPayFreelancer(uint _index, address indexed creatorAddress, address indexed workerAddress, uint salary);
event LogFreelancerDoneJob(uint index, address indexed workerAddress);
event LogFreelancerTakeJob(uint index, address indexed workerAddress);
function addJob(
string _jobTitle,
string _jobDescription,
uint256 _jobSalary
) public {
require(_jobSalary > 0);
require(bytes(_jobTitle).length > 0);
require(bytes(_jobDescription).length > 0);
Job memory _job = jobs[jobCount];
_job.workerAddress = 0x0;
_job.jobSalary += (_jobSalary * 10e18);
_job.jobTitle = _jobTitle;
_job.jobDescription = _jobDescription;
_job.active = true;
_job.inProgress = false;
_job.creatorAddress = msg.sender;
_job.salaryDelivred = false;
jobArray.push(_job);
jobCount++;
emit LogAddJob(_job.jobTitle, _job.jobDescription, _job.jobSalary);
}
function getTotalJobNumber() view public returns(uint) {
return jobCount;
}
function getJobByIndex(uint _index) view public returns(address, uint, string, string, bool, bool, bool) {
return (
jobs[_index].workerAddress,
jobs[_index].jobSalary,
jobs[_index].jobTitle,
jobs[_index].jobDescription,
jobs[_index].active,
jobs[_index].inProgress,
jobs[_index].salaryDelivred
);
}
function doThisJob(uint _index) public {
require(jobs[_index].active == true);
jobs[_index].workerAddress = msg.sender;
jobs[_index].inProgress = true;
workInprogressCount++;
emit LogFreelancerTakeJob(_index, jobs[_index].workerAddress);
}
function jobDone(uint _index) public {
require(jobs[_index].workerAddress == msg.sender);
jobs[_index].inProgress = false;
jobs[_index].active = false;
emit LogFreelancerDoneJob(_index, jobs[_index].workerAddress);
}
function cancelJob(uint _index) public {
require(jobs[_index].creatorAddress == msg.sender && jobs[_index].inProgress == false);
jobs[_index].active = false;
}
function payTheFreelancer(uint _index) public payable{
require(jobs[_index].creatorAddress == msg.sender);
require(jobs[_index].inProgress == false && jobs[_index].active == false);
address dest = jobs[_index].workerAddress;
require(jobs[_index].jobSalary <= msg.value * 1 ether);
jobs[_index].workerAddress.transfer(msg.value);
jobs[_index].salaryDelivred = true;
emit LogPayFreelancer(_index, jobs[_index].creatorAddress, dest, jobs[_index].jobSalary);
}
}
pragma solidity ^0.4.4;
contract Migrations {
address public owner;
uint public last_completed_migration;
modifier restricted() {
if (msg.sender == owner) _;
}
function Migrations() {
owner = msg.sender;
}
function setCompleted(uint completed) restricted {
last_completed_migration = completed;
}
function upgrade(address new_address) restricted {
Migrations upgraded = Migrations(new_address);
upgraded.setCompleted(last_completed_migration);
}
}
pragma solidity ^0.4.0;
contract owned {
address owner;
modifier onlyOwner() {
if (msg.sender == owner) {
_;
}
}
function owned() {
owner = msg.sender;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment