Skip to content

Instantly share code, notes, and snippets.

@redjade
Created May 25, 2018 14:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save redjade/ca88d90e3f838c57ea7a1a287b23e30a to your computer and use it in GitHub Desktop.
Save redjade/ca88d90e3f838c57ea7a1a287b23e30a to your computer and use it in GitHub Desktop.
bancor_test.cpp
#include <iostream>
#include <cmath>
#include <iomanip>
#include <limits>
using namespace std;
class Connector {
public:
long double balance;
long double weight;
string symbol;
};
class Supply {
public:
long double amount;
string symbol;
};
class Asset {
public:
long double amount;
string symbol;
};
class Bancor {
public:
Supply supply;
Connector base;
Connector quote;
string mode;
int debug;
Bancor() {
supply.amount = 100000000000000ll;
//supply.amount = 100000;
supply.symbol = "RAMCORE";
base.balance = 1024.0 * 1024.0 * 1024.0 * 64.0;
//base.balance = 10000;
base.weight = 0.5;
base.symbol = "RAM";
quote.balance = 1000000000ll / 1000.0;
//quote.balance = 5000;
quote.weight = 0.5;
quote.symbol = "CORE";
}
void report() {
cout << supply.symbol << " " << supply.amount << endl;
cout << base.symbol << " " << base.balance << endl;
cout << quote.symbol << " " << quote.balance << endl;
}
Asset convert_to_exchange(Connector& c, Asset in) {
Asset asset;
long double R = supply.amount;
long double C;
if (mode == "hy") {
C = c.balance;
} else if (mode == "cur") {
C = c.balance + in.amount;
} else {
cout << "mode not defined" << endl;
}
if (debug) {
cout << "conn bal " << c.balance << endl;
cout << "conn bal + in.amount" << c.balance + in.amount << endl;
cout << "C in mode " << mode << " " << C << endl;
}
long double F = c.weight / 1000.0;
//long double F = c.weight;
long double T = in.amount;
long double E;
E = R * ( std::pow( 1.0 + T / C, F) - 1.0 );
cout << "E " << E << endl;
supply.amount += E;
c.balance += T;
asset.amount = E;
asset.symbol = supply.symbol;
return asset;
}
Asset convert_from_exchange(Connector& c, Asset in) {
Asset asset;
long double R;
if (mode == "hy") {
R = supply.amount;
} else if (mode == "cur") {
R = supply.amount - in.amount;
} else {
cout << "mode not defined" << endl;
}
if (debug) {
cout << "sup bal " << supply.amount << endl;
cout << "sup bal - in.amount " << supply.amount - in.amount << endl;
cout << "R in mode " << mode << " " << R << endl;
}
long double C = c.balance;
long double F = 1000.0 / c.weight;
//long double F = 1.0 / c.weight;
long double E = in.amount;
long double T;
if (mode == "hy") {
T = -C * ( std::pow( 1.0 - E / R, F ) - 1.0 );
//cout << "mode hy" << endl;
} else if (mode == "cur") {
T = C * ( std::pow( 1.0 + E / R, F ) - 1.0 );
//cout << "mode cur" << endl;
} else {
cout << "mode not defined" << endl;
}
cout << "T " << T << endl;
supply.amount -= E;
c.balance -= T;
asset.amount = T;
asset.symbol = c.symbol;
return asset;
}
Asset convert(Asset from, string symbol) {
string sell_symbol = from.symbol;
string ex_symbol = supply.symbol;
string base_symbol = base.symbol;
string quote_symbol = quote.symbol;
if( sell_symbol != ex_symbol ) {
if( sell_symbol == base_symbol ) {
from = convert_to_exchange( base, from );
} else if( sell_symbol == quote_symbol ) {
from = convert_to_exchange( quote, from );
} else {
cout << "invalid sell" << endl;
}
} else {
if( symbol == base_symbol ) {
from = convert_from_exchange( base, from );
} else if( symbol == quote_symbol ) {
from = convert_from_exchange( quote, from );
} else {
cout << "invalid conversion" << endl;
}
}
if( symbol != from.symbol )
return convert( from, symbol );
return from;
}
};
void test(string mode, string to_symbol) {
Bancor bc;
Asset asset, r_asset, r_asset_2;
Asset core_asset;
Asset acc_asset;
string mode_desc;
cout << std::setprecision(std::numeric_limits<long double>::digits10 + 1);
acc_asset.amount = 0.0;
acc_asset.symbol = to_symbol;
core_asset.amount = 0.0;
core_asset.symbol = "CORE";
bc.mode = mode;
if (mode == "hy") {
mode_desc = "with fixes by @hyunwoongJi";
} else if (mode == "cur") {
mode_desc = "with current EOSIO implementation";
}
cout << "Test mode: " << mode_desc << ", converting between CORE <-> " << to_symbol << endl;
bc.report();
asset.amount = 1247.49294959;
asset.symbol = "CORE";
core_asset.amount += asset.amount;
cout << "converting CORE " << asset.amount << " to " << to_symbol << endl;
r_asset = bc.convert(asset, to_symbol);
acc_asset.amount += r_asset.amount;
cout << r_asset.amount << " " << r_asset.symbol << endl;
cout << "eff price ( CORE / " << to_symbol << " ): " << asset.amount / r_asset.amount << endl;
bc.report();
asset.amount = 332.49294959;
asset.symbol = "CORE";
core_asset.amount += asset.amount;
cout << "converting CORE " << asset.amount << " to " << to_symbol << endl;
r_asset = bc.convert(asset, to_symbol);
acc_asset.amount += r_asset.amount;
cout << r_asset.amount << " " << r_asset.symbol << endl;
cout << "eff price ( CORE / " << to_symbol << " ): " << asset.amount / r_asset.amount << endl;
bc.report();
asset.amount = 672.49294959;
asset.symbol = "CORE";
core_asset.amount += asset.amount;
cout << "converting CORE " << asset.amount << " to " << to_symbol << endl;
r_asset = bc.convert(asset, to_symbol);
acc_asset.amount += r_asset.amount;
cout << r_asset.amount << " " << r_asset.symbol << endl;
cout << "eff price ( CORE / " << to_symbol << " ): " << asset.amount / r_asset.amount << endl;
bc.report();
cout << "converting " << to_symbol << " " << acc_asset.amount << " to CORE" << endl;
r_asset_2 = bc.convert(acc_asset, "CORE");
bc.report();
cout << "CORE total paid so far: " << core_asset.amount << " " << core_asset.symbol<< endl;
cout << "CORE total regained: " << r_asset_2.amount << " " << r_asset_2.symbol << endl;
cout << "CORE regained - paid: " << r_asset_2.amount - core_asset.amount << " CORE" << endl;
cout << "Test done: " << mode_desc << ", converting between CORE <-> " << to_symbol << endl << endl;
return;
}
int main() {
test("hy", "RAMCORE");
test("cur", "RAMCORE");
test("hy", "RAM");
test("cur", "RAM");
}
@hyunwoongJi
Copy link

Add two new functions into class Bancor,

        long double buyRAM(long double dC) {
            long double R = base.balance; // RAM
            long double C = quote.balance; // EOS
            long double dR; // dRAM

            dR = R * (dC / (C + dC));

            base.balance -= dR;
            quote.balance += dC;

            return dR;
        }

        long double sellRAM(long double dR) {
            long double R = base.balance; // RAM
            long double C = quote.balance; // EOS
            long double dC;

            dC = C * (dR / (R + dR));

            quote.balance -= dC;
            base.balance += dR;

            return dC;
        }

And add test_relay function() into main()

void test_relay() {
    Bancor bc;
    long double c_amount, r_amount;
    long double c_amount_acc = 0.0;
    long double  r_amount_acc = 0.0;

    c_amount = 1247.49294959;
    r_amount = bc.buyRAM(c_amount);
    c_amount_acc += c_amount;
    r_amount_acc += r_amount;
    cout << "converting CORE " << c_amount << " to RAM" << endl;
    cout << "RAM: " << r_amount << endl;

    c_amount = 332.49294959;
    r_amount = bc.buyRAM(c_amount);
    c_amount_acc += c_amount;
    r_amount_acc += r_amount;
    cout << "converting CORE " << c_amount << " to RAM" << endl;
    cout << "RAM: " << r_amount << endl;

    c_amount = 672.49294959;
    r_amount = bc.buyRAM(c_amount);
    c_amount_acc += c_amount;
    r_amount_acc += r_amount;
    cout << "converting CORE " << c_amount << " to RAM" << endl;
    cout << "RAM: " << r_amount << endl;

    c_amount = bc.sellRAM(r_amount_acc);
    cout << "converting RAM " << r_amount_acc << " to CORE" << endl;
    cout << "CORE total paid so far: " << c_amount_acc << " CORE" << endl;
    cout << "CORE total regained: " << c_amount << " CORE" << endl;
    cout << "CORE regained - paid: " << c_amount - c_amount_acc << " CORE" <<  endl;
}

int main() {
    test_relay();
}

And the result is as follows:

converting CORE 1247.49294959000008 to RAM
RAM: 85620252.06687848171
converting CORE 332.4929495900000234 to RAM
RAM: 22784274.55156515296
converting CORE 672.4929495899999665 to RAM
RAM: 46036765.48410075686
converting RAM 154441292.1025443915 to CORE
CORE total paid so far: 2252.47884877000007 CORE
CORE total regained: 2252.47884877000007 CORE
CORE regained - paid: -2.220446049250313081e-16 CORE

The error is much less than the previous one.

  • error of recommended implementation above : -2.220446049250313081e-16
  • error of correct implementation with convert_to_exchange and convert_from_exchange : -1.389548476282698175e-10
  • error of current EOSIO implementation with convert_to_exchange and convert_from_exchange : -1.218400935698582543e-10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment