Skip to content

Instantly share code, notes, and snippets.

@gatherheart
Created December 5, 2019 13:04
Show Gist options
  • Save gatherheart/3ebabb391824614f056cef03dd0f4419 to your computer and use it in GitHub Desktop.
Save gatherheart/3ebabb391824614f056cef03dd0f4419 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.1+commit.c8a2cb62.js&optimize=false&gist=
pragma solidity >=0.4.22 < 0.6.0;
// REFERENCE TO github.com/gatherheart
// support for only uint256 and address array
library ArrayUtils{
using ArrayUtils for uint256 [];
using ArrayUtils for address [];
function pop(uint256 [] storage array, uint256 idx) internal returns(uint256){
uint256 ret = array[idx];
array.removeItem(idx);
return ret;
}
function removeAll(uint256 [] storage array) internal {
for (uint256 i = 0; i < array.length - 1; i++){
delete array[i];
}
delete array[array.length - 1];
array.length = 0;
}
function removeAll(address [] storage array) internal {
for (uint256 i = 0; i < array.length - 1; i++){
delete array[i];
}
delete array[array.length - 1];
array.length = 0;
}
function remove(uint256 [] storage array, uint256 index) internal {
if(index >= array.length)
return;
for (uint256 i = index; i < array.length - 1; i++){
array[i] = array[i + 1];
}
delete array[array.length - 1];
array.length--;
}
function remove(address [] storage array, uint256 index) internal {
if(index >= array.length)
return;
for (uint256 i = index; i < array.length - 1; i++){
array[i] = array[i + 1];
}
delete array[array.length - 1];
array.length--;
}
function count(uint256 [] memory array, uint256 item) internal pure returns(uint256){
if(!array.exist(item))
return 0;
uint256 countNum = 0;
for(uint256 i = 0; i < array.length; i++){
if(array[i] == item)
countNum++;
}
return countNum;
}
function count(address [] storage array, address item) internal view returns(uint256){
if(!array.exist(item))
return 0;
uint256 countNum = 0;
for(uint256 i = 0; i < array.length; i++){
if(array[i] == item)
countNum++;
}
return countNum;
}
function removeItem(uint256 [] storage array, uint256 item) internal{
if(!array.exist(item))
return;
for (uint256 i = array.indexOf(item); i < array.length - 1; i++){
array[i] = array[i + 1];
}
delete array[array.length - 1];
array.length--;
}
function removeItem(address [] storage array, address item) internal{
if(!array.exist(item))
return;
for (uint256 i = array.indexOf(item); i < array.length - 1; i++){
array[i] = array[i + 1];
}
delete array[array.length - 1];
array.length--;
}
function indexOf(uint256 [] memory array, uint256 item) internal pure returns(uint256){
require(array.exist(item));
for (uint256 i = 0; i < array.length; i++){
if(array[i] == item)
return i;
}
}
function indexOf(address [] storage array, address item) internal view returns(uint256){
require(array.exist(item));
for (uint256 i = 0; i < array.length; i++){
if(array[i] == item)
return i;
}
}
function exist(uint256 [] memory array, uint256 item) internal pure returns(bool) {
for (uint256 i = 0; i < array.length; i++){
if(array[i] == item)
return true;
}
return false;
}
function exist(address [] storage array, address item) internal view returns(bool) {
for (uint256 i = 0; i < array.length; i++){
if(array[i] == item)
return true;
}
return false;
}
function sort(uint256 [] storage array) internal{
QuickSort(array, 0, array.length - 1);
}
function QuickSort(uint256 [] storage array, uint256 left, uint256 right) internal {
uint256 i = left;
uint256 j = right;
// base
if(i == j)
return;
uint256 pivot = array[ uint256(left + (right - left) / 2) ];
while (i <= j) {
while (array[i] < pivot)
i++;
while (pivot < array[j])
j--;
if (i <= j) {
(array[i], array[j]) = (array[j], array[i]);
i++;
j--;
}
}
// branch
if (left < j)
QuickSort(array, left, j);
if (i < right)
QuickSort(array, i, right);
}
}
pragma solidity >=0.4.22 <0.6.0;
contract Database {
constructor () public {}
}
pragma solidity >=0.4.22 <0.6.0;
import "./IERC20.sol";
contract ERC20 is IERC20{
string public name = "Used2BlockCoin";
string public symbol = "UBC";
uint8 public decimals = 0;
mapping (address => uint256) private balances;
mapping (address => mapping (address => uint256)) private allowed;
uint256 private _totalSupply;
// Address Should not be Zero
modifier NotZeroAddr(address addr){
require(addr != address(0));
_;
}
constructor () public{
_totalSupply = 10**18;
balances[tx.origin] = _totalSupply;
}
function totalSupply() external view returns (uint256){
return _totalSupply;
}
function balanceOf(address who) external view NotZeroAddr(who) returns (uint256){
return balances[who];
}
function allowance(address owner, address spender) external view NotZeroAddr(spender) returns (uint256){
return allowed[owner][spender];
}
function transfer(address to, uint256 value) external NotZeroAddr(to) returns (bool){
// Underflow And overflow check
require(
balances[tx.origin] >= value
&& balances[to] + value > balances[to]
);
_transfer(tx.origin, to, value);
return true;
}
function _transfer(address _from, address to, uint256 value) private{
require(balances[_from] - value < balances[_from] && balances[to] + value > balances[to]);
balances[_from] -= value;
balances[to] += value;
emit Transfer(_from, to, value);
}
function approve(address spender, uint256 value) external NotZeroAddr(spender) returns (bool) {
allowed[tx.origin][spender] = value;
emit Approval(tx.origin, spender, value);
return true;
}
// fund holder: addresss _from,
// sender who is approved from fund holder : msg.sender
// receiver : address to
function transferFrom(address _from, address to, uint256 value) external NotZeroAddr(_from) NotZeroAddr(to) returns (bool){
require(allowed[_from][tx.origin] >= value);
_transfer(_from, to, value);
allowed[_from][tx.origin] -= value;
return true;
}
}
pragma solidity >=0.4.22 <0.6.0;
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.22 < 0.6.0;
contract Ownerable {
// event
event OwnerLog(address);
address public owner;
constructor() public{
owner = msg.sender;
emit OwnerLog(msg.sender);
}
modifier onlyOwner{
require(msg.sender == owner);
_;
}
modifier NotZeroAddr(address addr){
require(addr != address(0));
_;
}
function transferOwnership(address newOwner) public onlyOwner NotZeroAddr(newOwner) {
if(owner != newOwner)
owner = newOwner;
}
}
pragma solidity >=0.4.22 <0.6.0;
// Reference to https://github.com/OpenZeppelin/openzeppelin-solidity
library SafeMath {
function incr(uint256 a) internal pure returns(uint256){
return add(a, 1);
}
function decr(uint256 a) internal pure returns(uint256){
return sub(a, 1);
}
function mul(uint256 a, uint256 b) internal pure returns(uint256){
if (a == 0 || b == 0)
return 0;
uint256 result = a * b;
require(result / b == a, "SafeMath: overflow");
return result;
}
function add(uint256 a, uint256 b) internal pure returns(uint256){
uint256 result = a + b;
require(result >= a && result >= b, "SafeMath: overflow");
return result;
}
function sub(uint256 a, uint256 b) internal pure returns(uint256){
uint256 result = a - b;
require(result <= a, "SafeMath: underflow");
return result;
}
function div(uint256 a, uint256 b) internal pure returns(uint256){
require(b != 0, "Exception: Division by zero");
uint256 result = a / b;
return result;
}
function mod(uint256 a, uint256 b) internal pure returns(uint256){
require(b != 0, "Exception: modulo by zero");
uint256 result = a % b;
return result;
}
}
pragma solidity >=0.4.22 < 0.6.0;
// REFERENCE TO github.com/gatherheart
library StringUtils{
using StringUtils for string;
function length(string calldata str) external pure returns (uint256){
return bytes(str).length;
}
function strcmp(string calldata left, string calldata right) external pure returns (int8){
bytes memory leftTmp = bytes(left);
bytes memory rightTmp = bytes(right);
uint256 leftLen = left.length();
uint256 rightLen = right.length();
uint256 limit = leftLen;
// check smaller string length for for statmement
if(leftLen > rightLen)
limit = rightLen;
for(uint256 i = 0; i < limit; i++){
if(leftTmp[i] < rightTmp[i])
return -1;
else if(leftTmp[i] > rightTmp[i])
return 1;
}
if(leftLen == rightLen)
return 0;
else if(leftLen < rightLen)
return -1;
else
return 1;
}
}
pragma solidity >=0.4.22 <0.6.0;
pragma experimental ABIEncoderV2;
contract Test {
Test2 [] public t2;
address buyer;
function tmp() view public returns(uint256){
return now;
}
function tmp2() public {
t2.push(new Test2());
}
function tmp3() public view returns(address){
return address(t2[0]);
}
function tmp4() public view returns(bool){
return t2[0].tmp();
}
function tmp5() public {
buyer = msg.sender;
}
function tmp6() public view returns(address){
return buyer;
}
function tmp7() public view returns(string [] memory){
return ("HelloWorld", "Test", "Works");
}
}
contract Test2 {
function tmp() pure public returns(bool){
return true;
}
}
pragma solidity >=0.4.22 <0.6.0;
import "./ERC20.sol";
import "./StringUtils.sol";
contract Transaction {
using StringUtils for string;
ERC20 Bank;
address public seller; // owner contract id
address buyer;
address public validator;
string orderId; // order object id
address txid; // transaction id
uint256 txTime; // the time of transaction date
uint8 txStatus; // 0 waiting / 1 Reported / 2 Invalid Transaction / 3 Valid Transaction
uint256 public fee;
uint256 public PoS;
// seller's information
string sellerEmail;
string sellerPhone;
uint256 public productId;
uint256 public amount; // the price of product
string message;
Validation public report; // the list of reports about seller's history
struct Validation {
uint256 timeStamp; // report time
string nameOfPage; // reference page
string nameofSite;
uint256 accessTime;
string url; // reference url
}
constructor (string memory orderId_, address buyer_, address seller_, string memory sellerEmail_, string memory sellerPhone_,
uint256 amount_, string memory message_, address bank_, uint256 fee_, uint256 PoS_) public {
Bank = ERC20(bank_);
orderId = orderId_;
buyer = buyer_;
seller = seller_;
sellerEmail = sellerEmail_;
sellerPhone = sellerPhone_;
txTime = now;
message = message_;
amount = amount_;
PoS = PoS_;
fee = fee_;
}
// Paramerters
// uint256 timeStamp; // report time
// string nameOfPage; // reference page
// string nameofSite;
// uint256 accessTime; // Unix time Stamp
// string url; // reference url
function validate(string memory nameOfPage, string memory nameofSite, uint256 accessTime, string memory url) public {
// PoS applied here
require(PoS >= amount && Bank.balanceOf(tx.origin) >= amount + PoS);
Validation memory v;
v.timeStamp = now;
v.nameOfPage = nameOfPage;
v.nameofSite = nameofSite;
v.accessTime = accessTime;
v.url = url;
report = v;
validator = tx.origin;
}
function getInfo() public view returns (address, string memory){
string memory ret;
string memory delim = "#";
string memory tmp =
string(abi.encodePacked(uint2str(txTime), delim, sellerEmail, delim, sellerPhone, '\n\n'));
ret = string(abi.encodePacked(ret, tmp));
return (seller, ret);
}
function getOrderId() public view returns(string memory){
return orderId;
}
function getBuyer() public view returns (address){
return buyer;
}
function getSeller() public view returns (address){
return seller;
}
function getSellerEmail() public view returns(string memory){
return sellerEmail;
}
function getSellerPhone() public view returns(string memory){
return sellerPhone;
}
function getValidator() public view returns (address){
return validator;
}
function getAmount() public view returns (uint256){
return amount;
}
function getFee() public view returns (uint256){
return fee;
}
function setStatus(uint8 status) public {
require(tx.origin == buyer);
txStatus = status;
}
function getStatus() public view returns(uint8){
return txStatus;
}
function getValidation() public view returns (string memory){
string memory delim = "#";
Validation memory v = report;
string memory ret = string(abi.encodePacked(uint2str(v.timeStamp), delim, v.nameOfPage, delim,
v.nameofSite, delim, uint2str(v.accessTime), delim, v.url, '\n\n'));
return ret;
}
/*REFERENCE: loomnetwork/erc721x/blob/master/contracts/Core/ERC721X/ERC721XTokenNFT.sol*/
function uint2str(uint256 _i) private pure returns (string memory _uintAsString) {
if (_i == 0) {
return "0";
}
uint j = _i;
uint len;
while (j != 0) {
len++;
j /= 10;
}
bytes memory bstr = new bytes(len);
uint k = len - 1;
while (_i != 0) {
bstr[k--] = byte(uint8(48 + _i % 10));
_i /= 10;
}
return string(bstr);
}
}
pragma solidity >=0.4.22 <0.6.0;
import "./ERC20.sol";
import "./Ownerable.sol";
import "./ArrayUtils.sol";
import "./StringUtils.sol";
import "./Transaction.sol";
contract Used2Block is Ownerable {
using ArrayUtils for uint256 [];
using ArrayUtils for address [];
using StringUtils for string;
mapping (string => address []) fraudHistoryPhone;
mapping (address => address []) fraudHistoryAddress;
mapping (string => address []) fraudHistoryEmail;
mapping(string => address) transactions;
// transaction Pool
address [] public openTxids;
// Bank Smart Contract
ERC20 Bank;
constructor (address bank) public {
Bank = ERC20(bank);
}
function getTxLen() public view returns (uint256){
return openTxids.length;
}
function getBalance(address id) public view returns(uint256){
return Bank.balanceOf(id);
}
// return types
// address Transcation address
// uint8 status
// address Seller address
// String Seller's information
function getOpenTx(uint256 idx) public view returns(address, uint8, address, string memory){
require(idx < openTxids.length);
address seller;
string memory tmp;
Transaction t = Transaction(openTxids[idx]);
(seller, tmp) = t.getInfo();
return (openTxids[idx], t.getStatus(), seller, tmp);
}
// return types
// (string => uint256 []) fraudHistoryPhone;
// (address => uint256 []) fraudHistoryAddress;
// (string => uint256 []) fraudHistoryEmail;
function findFraudWithPhone(string memory phone) public view returns (address [] memory){
return fraudHistoryPhone[phone];
}
function findFraudWithAddres(address seller) public view returns (address [] memory){
return fraudHistoryAddress[seller];
}
function findFraudWithEmail(string memory email) public view returns (address [] memory){
return fraudHistoryEmail[email];
}
function getValidation(address txid) public view returns (string memory){
return Transaction(txid).getValidation();
}
// 0 == waiting | 1 == Validated | 2 == terminated | 3 == completed
function getStatus(address txid) public view returns (uint8){
return Transaction(txid).getStatus();
}
function getTxAddress(string memory orderId) public view returns (address){
return transactions[orderId];
}
function getOrderId(address txid) public view returns (string memory){
return Transaction(txid).getOrderId();
}
function makeTx(string memory orderId, address seller, string memory sellerEmail, string memory sellerPhone,
uint256 amount, string memory message, uint256 fee, uint256 PoS) public {
// seller should not be same with buyer
require(msg.sender != seller);
// amount_ * 1.05 = amount + fee
require(fee >= 0 && amount > 0 && Bank.balanceOf(msg.sender) >= (amount + fee));
Transaction tx_ = new Transaction(orderId, msg.sender, seller, sellerEmail, sellerPhone, amount, message, address(Bank), fee, PoS);
openTxids.push(address(tx_));
transactions[orderId] = address(tx_);
}
function validate(address txid, string memory nameOfPage, string memory nameofSite, uint256 accessTime, string memory url) public {
address seller = Transaction(txid).getSeller();
// sender should not be validator and transaction is not validated
require(seller != msg.sender && Transaction(txid).getStatus() < 1);
Transaction(txid).validate(nameOfPage, nameofSite, accessTime, url);
Transaction(txid).setStatus(1);
}
// Complete transaction
function completeTx(address txid) public{
address buyer = Transaction(txid).getBuyer();
address seller = Transaction(txid).getSeller();
address validator = Transaction(txid).getValidator();
uint256 amount = Transaction(txid).getAmount();
uint256 fee = Transaction(txid).getFee();
// msg sender should be buyer
require(buyer == msg.sender && Bank.balanceOf(buyer) > (amount + fee) && Transaction(txid).getStatus() < 2);
Bank.transfer(seller, amount);
Bank.transfer(validator, amount);
openTxids.removeItem(txid);
Transaction(txid).setStatus(3);
}
// Terminate fraud transaction and report fraud
function reportTx(address txid) public {
address buyer = Transaction(txid).getBuyer();
address seller = Transaction(txid).getSeller();
address validator = Transaction(txid).getValidator();
uint256 amount = Transaction(txid).getAmount();
uint256 fee = Transaction(txid).getFee();
// msg sender should be buyer
require(buyer == msg.sender && Bank.balanceOf(buyer) > fee && Transaction(txid).getStatus() == 1);
fraudHistoryPhone[Transaction(txid).getSellerPhone()].push(txid);
fraudHistoryAddress[seller].push(txid);
fraudHistoryEmail[Transaction(txid).getSellerEmail()].push(txid);
openTxids.removeItem(txid);
Bank.transfer(validator, amount);
Transaction(txid).setStatus(2);
}
function revertValidation(address txid) public {
address buyer = Transaction(txid).getBuyer();
require(buyer == msg.sender && Transaction(txid).getStatus() == 1);
Transaction(txid).setStatus(0);
}
function giveToken(address target) public {
Bank.transfer(target, 100);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment