Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- pragma solidity ^ 0.6.3;
- /*
- ,/`.
- ,'/ __`.
- ,'_/__ _ _`.
- ,'__/__ _ _ _`.
- ,'_ /___ __ _ __ `.
- '-.._/___ _ __ __ __`.
- */
- contract Pyramid{
- // scaleFactor is used to convert Ether into bonds and vice-versa: they're of different
- // orders of magnitude, hence the need to bridge between the two.
- uint256 constant scaleFactor = 0x10000000000000000;
- address payable address0 = address(0);
- int constant crr_n = 1;
- int constant crr_d = 2;
- int constant public slope = -0x1337FA66607BADA55;
- // Typical values that we have to declare.
- string constant public name = "Mass";
- string constant public symbol = "Mass";
- uint8 constant public decimals = 18;
- // Array between each address and their number of bonds.
- mapping(address => uint256) public mass;
- mapping(address => mapping(address => uint)) approvals;
- // For calculating resolves minted
- mapping(address => uint256) public average_ethSpent;
- // For calculating hodl multiplier that factors into resolves minted
- mapping(address => uint256) public average_buyInTimeSum;
- // Array between each address and their number of resolves being staked.
- mapping(address => uint256) public resolveWeight;
- // Array between each address and how much Ether has been paid out to it.
- // Note that this is scaled by the scaleFactor variable.
- mapping(address => int256) public payouts;
- // Variable tracking how many bonds are in existence overall.
- uint256 public _totalSupply;
- // The total number of resolves being staked in this contract
- uint256 public dissolvingResolves;
- // The ethereum locked up into bonds
- uint public contractBalance;
- // For calculating the hodl multiplier. Weighted average release time
- uint public sumOfInputETH;
- uint public sumOfInputTime;
- uint public sumOfOutputETH;
- uint public sumOfOutputTime;
- // Something about invarience.
- int256 earningsOffset;
- // Variable tracking how much Ether each token is currently worth.
- // Note that this is scaled by the scaleFactor variable.
- uint256 earningsPerResolve;
- //The resolve token contract
- ResolveToken public resolveToken;
- constructor() public{
- resolveToken = new ResolveToken( address(this) );
- }
- function totalSupply() public view returns (uint256) {
- return _totalSupply;
- }
- // Returns the number of bonds currently held by _owner.
- function balanceOf(address _owner) public view returns (uint256 balance) {
- return mass[_owner];
- }
- function fluxFee(uint paidAmount) public view returns (uint fee) {
- uint totalResolveSupply = resolveToken.totalSupply() - resolveToken.balanceOf( address(0) );
- if ( dissolvingResolves == 0 )
- return 0;
- return paidAmount * ( totalResolveSupply - dissolvingResolves ) / totalResolveSupply * sumOfOutputETH / sumOfInputETH;
- }
- // Converts the Ether accrued as resolveEarnings back into bonds without having to
- // withdraw it first. Saves on gas and potential price spike loss.
- event Reinvest( address indexed addr, uint256 reinvested, uint256 dissolved, uint256 bonds, uint256 resolveTax);
- function reinvestEarnings(uint amountFromEarnings) public returns(uint,uint){
- address sender = msg.sender;
- // Retrieve the resolveEarnings associated with the address the request came from.
- uint upScaleDivs = (uint)((int256)( earningsPerResolve * resolveWeight[sender] ) - payouts[sender]);
- uint totalEarnings = upScaleDivs / scaleFactor;//resolveEarnings(sender);
- require(amountFromEarnings <= totalEarnings, "the amount exceeds total earnings");
- uint oldWeight = resolveWeight[sender];
- resolveWeight[sender] = oldWeight * (totalEarnings - amountFromEarnings) / totalEarnings;
- uint weightDiff = oldWeight - resolveWeight[sender];
- resolveToken.transfer( address0, weightDiff );
- dissolvingResolves -= weightDiff;
- // something about invariance
- int withdrawnEarnings = (int)(upScaleDivs * amountFromEarnings / totalEarnings) - (int)(weightDiff*earningsPerResolve);
- payouts[sender] += withdrawnEarnings;
- // Increase the total amount that's been paid out to maintain invariance.
- earningsOffset += withdrawnEarnings;
- // Assign balance to a new variable.
- uint value_ = (uint) (amountFromEarnings);
- // If your resolveEarnings are worth less than 1 szabo, abort.
- if (value_ < 0.000001 ether)
- revert();
- // Calculate the fee
- uint fee = fluxFee(value_);
- // The amount of Ether used to purchase new bonds for the caller
- uint numEther = value_ - fee;
- //resolve reward tracking stuff
- average_ethSpent[sender] += numEther;
- average_buyInTimeSum[sender] += now * scaleFactor * numEther;
- sumOfInputETH += numEther;
- sumOfInputTime += now * scaleFactor * numEther;
- // The number of bonds which can be purchased for numEther.
- uint createdBonds = calculateBondsFromReinvest(numEther, amountFromEarnings);
- // the variable stoslope the amount to be paid to stakers
- uint resolveFee;
- // Check if we have bonds in existence
- if ( dissolvingResolves > 0 ) {
- resolveFee = fee * scaleFactor;
- // Fee is distributed to all existing resolve stakers before the new bonds are purchased.
- // rewardPerResolve is the amount(ETH) gained per resolve token from this purchase.
- uint rewardPerResolve = resolveFee / dissolvingResolves;
- // The Ether value per token is increased proportionally.
- earningsPerResolve += rewardPerResolve;
- }
- // Add the createdBonds to the total supply.
- _totalSupply += createdBonds;
- // Assign the bonds to the balance of the buyer.
- mass[sender] += createdBonds;
- emit Reinvest(sender, value_, weightDiff, createdBonds, resolveFee);
- return (createdBonds, weightDiff);
- }
- // Sells your bonds for Ether
- function sellAllBonds() public returns(uint returned_eth, uint returned_resolves, uint initialInput_ETH){
- return sell( balanceOf(msg.sender) );
- }
- function sellBonds(uint amount) public returns(uint returned_eth, uint returned_resolves, uint initialInput_ETH){
- uint balance = balanceOf(msg.sender);
- require(balance >= amount, "Amount is more than balance");
- ( returned_eth, returned_resolves, initialInput_ETH ) = sell(amount);
- return (returned_eth, returned_resolves, initialInput_ETH);
- }
- // Big red exit button to pull all of a holder's Ethereum value from the contract
- function getMeOutOfHere() public {
- sellAllBonds();
- withdraw( resolveEarnings(msg.sender) );
- }
- // Gatekeeper function to check if the amount of Ether being sent isn't too small
- function fund() payable public returns(uint){
- uint bought;
- if (msg.value > 0.000001 ether) {
- contractBalance += msg.value;
- bought = buy();
- } else {
- revert();
- }
- return bought;
- }
- // Function that returns the (dynamic) pricing for buys, sells and fee
- function pricing(uint scale) public view returns (uint buyPrice, uint sellPrice, uint fee) {
- uint buy_eth = scaleFactor * getPriceForBonds( scale, true) / ( scaleFactor - fluxFee(scaleFactor) ) ;
- uint sell_eth = getPriceForBonds(scale, false);
- sell_eth -= fluxFee(sell_eth);
- return ( buy_eth, sell_eth, fluxFee(scale) );
- }
- // For calculating the price
- function getPriceForBonds(uint256 bonds, bool buy_or_sell) public view returns (uint256 price) {
- uint reserveAmount = reserve();
- if(buy_or_sell){
- uint x = fixedExp((fixedLog(_totalSupply + bonds) - slope) * crr_d/crr_n);
- return x - reserveAmount;
- }else{
- uint x = fixedExp((fixedLog(_totalSupply - bonds) - slope) * crr_d/crr_n);
- return reserveAmount - x;
- }
- }
- // Calculate the current resolveEarnings associated with the caller address. This is the net result
- // of multiplying the number of resolves held by their current value in Ether and subtracting the
- // Ether that has already been paid out.
- function resolveEarnings(address _owner) public view returns (uint256 amount) {
- return (uint256) ((int256)(earningsPerResolve * resolveWeight[_owner]) - payouts[_owner]) / scaleFactor;
- }
- event Buy( address indexed addr, uint256 spent, uint256 bonds, uint256 resolveTax);
- function buy() internal returns(uint){
- address sender = msg.sender;
- // Any transaction of less than 1 szabo is likely to be worth less than the gas used to send it.
- if ( msg.value < 0.000001 ether )
- revert();
- // Calculate the fee
- uint fee = fluxFee(msg.value);
- // The amount of Ether used to purchase new bonds for the caller.
- uint numEther = msg.value - fee;
- //resolve reward tracking stuff
- uint currentTime = now;
- average_ethSpent[sender] += numEther;
- average_buyInTimeSum[sender] += currentTime * scaleFactor * numEther;
- sumOfInputETH += numEther;
- sumOfInputTime += currentTime * scaleFactor * numEther;
- // The number of bonds which can be purchased for numEther.
- uint createdBonds = getBondsForEther(numEther);
- // Add the createdBonds to the total supply.
- _totalSupply += createdBonds;
- // Assign the bonds to the balance of the buyer.
- mass[sender] += createdBonds;
- // Check if we have bonds in existence
- uint resolveFee;
- if (dissolvingResolves > 0) {
- resolveFee = fee * scaleFactor;
- // Fee is distributed to all existing resolve holders before the new bonds are purchased.
- // rewardPerResolve is the amount gained per resolve token from this purchase.
- uint rewardPerResolve = resolveFee/dissolvingResolves;
- // The Ether value per resolve is increased proportionally.
- earningsPerResolve += rewardPerResolve;
- }
- emit Buy( sender, msg.value, createdBonds, resolveFee);
- return createdBonds;
- }
- function avgHodl() public view returns(uint hodlTime){
- return now - (sumOfInputTime - sumOfOutputTime) / (sumOfInputETH - sumOfOutputETH) / scaleFactor;
- }
- function getReturnsForBonds(address addr, uint bondsReleased) public view returns(uint etherValue, uint mintedResolves, uint new_releaseTimeSum, uint new_releaseAmount, uint initialInput_ETH){
- uint output_ETH = getEtherForBonds(bondsReleased);
- uint input_ETH = average_ethSpent[addr] * bondsReleased / mass[addr];
- // hodl multiplier. because if you don't hodl at all, you shouldn't be rewarded resolves.
- // and the multiplier you get for hodling needs to be relative to the average hodl
- uint buyInTime = average_buyInTimeSum[addr] / average_ethSpent[addr];
- uint cashoutTime = now * scaleFactor - buyInTime;
- uint new_sumOfOutputTime = sumOfOutputTime + average_buyInTimeSum[addr] * bondsReleased / mass[addr];
- uint new_sumOfOutputETH = sumOfOutputETH + input_ETH;//It's based on the original ETH, so that's why input_ETH is used. Not output_ETH.
- uint averageHoldingTime = now * scaleFactor - ( sumOfInputTime - sumOfOutputTime ) / ( sumOfInputETH - sumOfOutputETH );
- return (output_ETH, input_ETH * cashoutTime / averageHoldingTime * input_ETH / output_ETH, new_sumOfOutputTime, new_sumOfOutputETH, input_ETH);
- }
- event Sell( address indexed addr, uint256 bondsSold, uint256 cashout, uint256 resolves, uint256 resolveTax, uint256 initialCash);
- function sell(uint256 amount) internal returns(uint eth, uint resolves, uint initialInput){
- address payable sender = msg.sender;
- // Calculate the amount of Ether & Resolves that the holder's bonds sell for at the current sell price.
- (uint numEthersBeforeFee,uint mintedResolves,uint new_sumOfOutputTime,uint new_sumOfOutputETH,uint initialInput_ETH) = getReturnsForBonds(sender, amount);
- // calculate the fee
- uint fee = fluxFee(numEthersBeforeFee);
- // magic distribution
- resolveToken.mint(sender, mintedResolves);
- // update weighted average cashout time
- sumOfOutputTime = new_sumOfOutputTime;
- sumOfOutputETH = new_sumOfOutputETH;
- // reduce the amount of "eth spent" based on the percentage of bonds being sold back into the contract
- average_ethSpent[sender] = average_ethSpent[sender] * ( mass[sender] - amount) / mass[sender];
- // reduce the "buyInTime" sum that's used for average buy in time
- average_buyInTimeSum[sender] = average_buyInTimeSum[sender] * (mass[sender] - amount) / mass[sender];
- // Net Ether for the seller after the fee has been subtracted.
- uint numEthers = numEthersBeforeFee - fee;
- // Burn the bonds which were just sold from the total supply.
- _totalSupply -= amount;
- // Remove the bonds from the balance of the buyer.
- mass[sender] -= amount;
- // Check if we have bonds in existence
- uint resolveFee;
- if ( dissolvingResolves > 0 ){
- // Scale the Ether taken as the selling fee by the scaleFactor variable.
- resolveFee = fee * scaleFactor;
- // Fee is distributed to all remaining resolve holders.
- // rewardPerResolve is the amount gained per resolve thanks to this sell.
- uint rewardPerResolve = resolveFee/dissolvingResolves;
- // The Ether value per resolve is increased proportionally.
- earningsPerResolve += rewardPerResolve;
- }
- // Send the ethereum to the address that requested the sell.
- contractBalance -= numEthers;
- (bool success, ) = sender.call.value(numEthers)("");
- require(success, "Transfer failed.");
- emit Sell( sender, amount, numEthers, mintedResolves, resolveFee, initialInput_ETH);
- return (numEthers, mintedResolves, initialInput_ETH);
- }
- // Dynamic value of Ether in reserve, according to the CRR requirement.
- function reserve() public view returns (uint256 amount) {
- return Common.subtract( balance(), (uint256) ((int256) (earningsPerResolve * dissolvingResolves) - earningsOffset) / scaleFactor );
- }
- function balance() internal view returns (uint256 amount) {
- // msg.value is the amount of Ether sent by the transaction.
- return contractBalance - msg.value;
- }
- // Calculates the number of bonds that can be bought for a given amount of Ether, according to the
- // dynamic reserve and _totalSupply values (derived from the buy and sell prices).
- function getBondsForEther(uint256 ethervalue) public view returns (uint256 bonds) {
- return Common.subtract(fixedExp( fixedLog( reserve() + ethervalue ) * crr_n/crr_d + slope ) , _totalSupply);
- }
- // Semantically similar to getBondsForEther, but subtracts the callers balance from the amount of Ether returned for conversion.
- function calculateBondsFromReinvest(uint256 ethervalue, uint256 subvalue) public view returns (uint256 bondTokens) {
- return Common.subtract(fixedExp(fixedLog(Common.subtract(reserve() , subvalue) + ethervalue)*crr_n/crr_d + slope) , _totalSupply);
- }
- // Converts a number bonds into an Ether value.
- function getEtherForBonds(uint256 bondTokens) public view returns (uint256 ethervalue) {
- // How much reserve Ether do we have left in the contract?
- uint reserveAmount = reserve();
- // If you're the Highlander (or bagholder), you get The Prize. Everything left in the remainder's vault.
- if (bondTokens == _totalSupply)
- return reserveAmount;
- // If there would be excess Ether left after the transaction this is called within, return the Ether
- // corresponding to the equation in Dr Jochen Hoenicke's original Ponzi paper, which can be found
- // at https://test.jochen-hoenicke.de/eth/ponzitoken/ in the third equation, with the CRR numerator
- // and denominator altered to 1 and 2 respectively.
- return Common.subtract(reserveAmount, fixedExp( ( fixedLog(_totalSupply-bondTokens)-slope ) * crr_d/crr_n) );
- }
- // You don't care about these, but if you really do they're hex values for
- // co-efficients used to simulate approximations of the log and exp functions.
- int256 constant one = 0x10000000000000000;
- uint256 constant sqrt2 = 0x16a09e667f3bcc908;
- uint256 constant sqrtdot5 = 0x0b504f333f9de6484;
- int256 constant ln2 = 0x0b17217f7d1cf79ac;
- int256 constant ln2_64dot5 = 0x2cb53f09f05cc627c8;
- int256 constant c1 = 0x1ffffffffff9dac9b;
- int256 constant c3 = 0x0aaaaaaac16877908;
- int256 constant c5 = 0x0666664e5e9fa0c99;
- int256 constant c7 = 0x049254026a7630acf;
- int256 constant c9 = 0x038bd75ed37753d68;
- int256 constant c11 = 0x03284a0c14610924f;
- // The polynomial R = c1*x + c3*x^3 + ... + c11 * x^11
- // approximates the function log(1+x)-log(1-x)
- // Hence R(s) = log((1+s)/(1-s)) = log(a)
- function fixedLog(uint256 a) internal pure returns (int256 log) {
- int32 scale = 0;
- while (a > sqrt2) {
- a /= 2;
- scale++;
- }
- while (a <= sqrtdot5) {
- a *= 2;
- scale--;
- }
- int256 s = (((int256)(a) - one) * one) / ((int256)(a) + one);
- int z = (s*s) / one;
- return scale * ln2 +
- (s*(c1 + (z*(c3 + (z*(c5 + (z*(c7 + (z*(c9 + (z*c11/one))
- /one))/one))/one))/one))/one);
- }
- int256 constant c2 = 0x02aaaaaaaaa015db0;
- int256 constant c4 = -0x000b60b60808399d1;
- int256 constant c6 = 0x0000455956bccdd06;
- int256 constant c8 = -0x000001b893ad04b3a;
- // The polynomial R = 2 + c2*x^2 + c4*x^4 + ...
- // approximates the function x*(exp(x)+1)/(exp(x)-1)
- // Hence exp(x) = (R(x)+x)/(R(x)-x)
- function fixedExp(int256 a) internal pure returns (uint256 exp) {
- int256 scale = (a + (ln2_64dot5)) / ln2 - 64;
- a -= scale*ln2;
- int256 z = (a*a) / one;
- int256 R = ((int256)(2) * one) +
- (z*(c2 + (z*(c4 + (z*(c6 + (z*c8/one))/one))/one))/one);
- exp = (uint256) (((R + a) * one) / (R - a));
- if (scale >= 0)
- exp <<= scale;
- else
- exp >>= -scale;
- return exp;
- }
- // Allow contract to accept resolve tokens
- event StakeResolves( address indexed addr, uint256 amountStaked, bytes _data );
- function tokenFallback(address from, uint value, bytes calldata _data) external{
- if(msg.sender == address(resolveToken) ){
- resolveWeight[from] += value;
- dissolvingResolves += value;
- // Then we update the payouts array for the "resolve shareholder" with this amount
- int payoutDiff = (int256) (earningsPerResolve * value);
- payouts[from] += payoutDiff;
- earningsOffset += payoutDiff;
- emit StakeResolves(from, value, _data);
- }else{
- revert("no want");
- }
- }
- // Withdraws resolveEarnings held by the caller sending the transaction, updates
- // the requisite global variables, and transfers Ether back to the caller.
- event Withdraw( address indexed addr, uint256 earnings, uint256 dissolve );
- function withdraw(uint amount) public returns(uint){
- address payable sender = msg.sender;
- // Retrieve the resolveEarnings associated with the address the request came from.
- uint upScaleDivs = (uint)((int256)( earningsPerResolve * resolveWeight[sender] ) - payouts[sender]);
- uint totalEarnings = upScaleDivs / scaleFactor;
- require( amount <= totalEarnings && amount > 0 );
- uint oldWeight = resolveWeight[sender];
- resolveWeight[sender] = oldWeight * ( totalEarnings - amount ) / totalEarnings;
- uint weightDiff = oldWeight - resolveWeight[sender];
- resolveToken.transfer( address0, weightDiff);
- dissolvingResolves -= weightDiff;
- // something about invariance
- int withdrawnEarnings = (int)(upScaleDivs * amount / totalEarnings) - (int)(weightDiff*earningsPerResolve);
- payouts[sender] += withdrawnEarnings;
- // Increase the total amount that's been paid out to maintain invariance.
- earningsOffset += withdrawnEarnings;
- contractBalance -= amount;
- // Send the resolveEarnings to the address that requested the withdraw.
- (bool success, ) = sender.call.value(amount)("");
- require(success, "Transfer failed.");
- emit Withdraw( sender, amount, weightDiff);
- return weightDiff;
- }
- event PullResolves( address indexed addr, uint256 pulledResolves, uint256 forfeiture);
- function pullResolves(uint amount) public returns (uint forfeiture){
- address sender = msg.sender;
- uint resolves = resolveWeight[ sender ];
- require(amount <= resolves && amount > 0);
- require(amount < dissolvingResolves);//"you can't forfeit the last resolve"
- uint yourTotalEarnings = (uint)((int256)(resolves * earningsPerResolve) - payouts[sender]);
- uint forfeitedEarnings = yourTotalEarnings * amount / resolves;
- // Update the payout array so that the "resolve shareholder" cannot claim resolveEarnings on previous staked resolves.
- payouts[sender] += (int256)(forfeitedEarnings) - (int256)(earningsPerResolve * amount);
- resolveWeight[sender] -= amount;
- dissolvingResolves -= amount;
- // The Ether value per token is increased proportionally.
- earningsPerResolve += forfeitedEarnings / dissolvingResolves;
- resolveToken.transfer( sender, amount );
- emit PullResolves( sender, amount, forfeitedEarnings / scaleFactor);
- return forfeitedEarnings / scaleFactor;
- }
- // Function that is called when a user or another contract wants to transfer funds .
- function transfer(address _to, uint _value, bytes memory _data) public returns (bool success) {
- if (balanceOf(msg.sender) < _value) revert();
- if(Common.isContract(_to)) {
- return transferToContract(_to, _value, _data);
- }else{
- return transferToAddress(_to, _value, _data);
- }
- }
- // Standard function transfer similar to ERC20 transfer with no _data .
- // Added due to backwards compatibility reasons .
- function transfer(address _to, uint _value) public returns (bool success) {
- if (balanceOf(msg.sender) < _value) revert();
- //standard function transfer similar to ERC20 transfer with no _data
- //added due to backwards compatibility reasons
- bytes memory empty;
- if(Common.isContract(_to)){
- return transferToContract(_to, _value, empty);
- }else{
- return transferToAddress(_to, _value, empty);
- }
- }
- //function that is called when transaction target is an address
- function transferToAddress(address _to, uint _value, bytes memory _data) private returns (bool success) {
- moveTokens(msg.sender,_to,_value);
- emit Transfer(msg.sender, _to, _value, _data);
- return true;
- }
- //function that is called when transaction target is a contract
- function transferToContract(address _to, uint _value, bytes memory _data) private returns (bool success) {
- address sender = msg.sender;
- moveTokens(sender, _to, _value);
- ERC223ReceivingContract reciever = ERC223ReceivingContract(_to);
- reciever.tokenFallback(sender, _value, _data);
- emit Transfer(sender, _to, _value, _data);
- return true;
- }
- function moveTokens(address _from, address _to, uint _amount) private{
- uint totalBonds = mass[_from];
- require(_amount <= totalBonds && _amount > 0);
- uint ethSpent = average_ethSpent[_from] * _amount / totalBonds;
- uint buyInTimeSum = average_buyInTimeSum[_from] * _amount / totalBonds;
- average_ethSpent[_from] -= ethSpent;
- average_buyInTimeSum[_from] -= buyInTimeSum;
- mass[_from] -= _amount;
- average_ethSpent[_to] += ethSpent;
- average_buyInTimeSum[_to] += buyInTimeSum;
- mass[_to] += _amount;
- }
- function allowance(address src, address guy) public view returns (uint) {
- return approvals[src][guy];
- }
- function transferFrom(address src, address dst, uint wad) public returns (bool){
- address sender = msg.sender;
- require(approvals[src][sender] >= wad, "That amount is not approved");
- require(mass[src] >= wad, "That amount is not available from this wallet");
- if (src != sender) {
- approvals[src][sender] -= wad;
- }
- moveTokens(src,dst,wad);
- bytes memory empty;
- emit Transfer(src, dst, wad, empty);
- return true;
- }
- function approve(address guy, uint wad) public returns (bool) {
- approvals[msg.sender][guy] = wad;
- emit Approval(msg.sender, guy, wad);
- return true;
- }
- event Transfer(
- address indexed from,
- address indexed to,
- uint256 amount,
- bytes data
- );
- event Approval(address indexed src, address indexed guy, uint wad);
- }
- abstract contract ERC223ReceivingContract{
- function tokenFallback(address _from, uint _value, bytes calldata _data) external virtual;
- }
- contract ResolveToken{
- mapping(address => uint) balances;
- mapping(address => mapping(address => uint)) approvals;
- string public name = "Resolve";
- string public symbol = "`r";
- uint8 constant public decimals = 18;
- uint256 private _totalSupply;
- address public hourglass;
- constructor(address _hourglass) public{
- hourglass = _hourglass;
- }
- modifier hourglassOnly{
- require(msg.sender == hourglass);
- _;
- }
- event Transfer(
- address indexed from,
- address indexed to,
- uint256 amount,
- bytes data
- );
- event Mint(
- address indexed addr,
- uint256 amount
- );
- function totalSupply() public view returns (uint256) {
- return _totalSupply;
- }
- function mint(address _address, uint _value) external hourglassOnly(){
- balances[_address] += _value;
- _totalSupply += _value;
- emit Mint(_address, _value);
- }
- // Function that is called when a user or another contract wants to transfer funds .
- function transfer(address _to, uint _value, bytes memory _data) public returns (bool success) {
- if (balanceOf(msg.sender) < _value) revert();
- if(Common.isContract(_to)) {
- return transferToContract(_to, _value, _data);
- }else{
- return transferToAddress(_to, _value, _data);
- }
- }
- // Standard function transfer similar to ERC20 transfer with no _data .
- // Added due to backwards compatibility reasons .
- function transfer(address _to, uint _value) public returns (bool success) {
- if (balanceOf(msg.sender) < _value) revert();
- //standard function transfer similar to ERC20 transfer with no _data
- //added due to backwards compatibility reasons
- bytes memory empty;
- if(Common.isContract(_to)){
- return transferToContract(_to, _value, empty);
- }else{
- return transferToAddress(_to, _value, empty);
- }
- }
- //function that is called when transaction target is an address
- function transferToAddress(address _to, uint _value, bytes memory _data) private returns (bool success) {
- moveTokens(msg.sender,_to,_value);
- emit Transfer(msg.sender, _to, _value, _data);
- return true;
- }
- //function that is called when transaction target is a contract
- function transferToContract(address _to, uint _value, bytes memory _data) private returns (bool success) {
- address sender = msg.sender;
- moveTokens(sender, _to, _value);
- ERC223ReceivingContract reciever = ERC223ReceivingContract(_to);
- reciever.tokenFallback(sender, _value, _data);
- emit Transfer(sender, _to, _value, _data);
- return true;
- }
- function moveTokens(address _from, address _to, uint _amount) private{
- balances[_from] -= _amount;
- balances[_to] += _amount;
- }
- function balanceOf(address _owner) public view returns (uint balance) {
- return balances[_owner];
- }
- function allowance(address src, address guy) public view returns (uint) {
- return approvals[src][guy];
- }
- function transferFrom(address src, address dst, uint wad) public returns (bool){
- address sender = msg.sender;
- require(approvals[src][sender] >= wad, "That amount is not approved");
- require(balances[src] >= wad, "That amount is not available from this wallet");
- if (src != sender) {
- approvals[src][sender] -= wad;
- }
- moveTokens(src,dst,wad);
- bytes memory empty;
- emit Transfer(src, dst, wad, empty);
- return true;
- }
- function approve(address guy, uint wad) public returns (bool) {
- approvals[msg.sender][guy] = wad;
- emit Approval(msg.sender, guy, wad);
- return true;
- }
- event Approval(address indexed src, address indexed guy, uint wad);
- }
- /**
- * @title Common
- * @dev Math operations with safety checks that throw on error
- */
- library Common {
- /**
- * @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
- */
- function subtract(uint256 a, uint256 b) internal pure returns (uint256) {
- assert(b <= a);
- return a - b;
- }
- //assemble the given address bytecode. If bytecode exists then the _addr is a contract.
- function isContract(address _addr) public view returns (bool is_contract) {
- uint length;
- assembly {
- //retrieve the size of the code on target address, this needs assembly
- length := extcodesize(_addr)
- }
- if(length>0) {
- return true;
- }else {
- return false;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement