GNTTokenTrader And GNTTokenTraderFactory
The GNTTokenTrader contract is the original SellOnly TokenTraderFactory deployed on the Ethereum network to support the Golem Network Token (GNT) that is partially ERC20 compliant.
A Market Maker uses the GNTTokenTraderFactory to create a GNTTokenTrader contract that specifies the price the Market Maker is willing to sell GNTs. The Market Maker then loads the contracts with GNTs.
A Market Taker simply sends ethers to the GNTTokenTrader contracts to receive the GNTs at the specified price. The Market Maker can later withdraw the ethers from the GNTTokenTrader contracts.
- Always test the use of these contracts with small amounts of ethers and/or tokens before committing larger amounts.
- You are responsible for your own trades. We accept no liability for errors or ommissions. Methods are provided on this page for you to independently verify the correctness of these contracts, and always test first with small amounts.
- The TokenTraderFactory And TokenSellerFactory Bug Bounty is now active.
- When convenient, please replace the GNTTokenTrader and GNTTokenTraderFactory contracts with the improved TokenSeller and TokenSellerFactory. The differences between the GNTTokenTrader and GNTTokenTraderFactory compared to the TokenSeller and TokenSellerFactory can be found in the table at the Dec 19 2016 History entry.
- GNTTokenTrader And GNTTokenTraderFactory Contract Information
- Fees
- Market Taker Operations
- Market Maker Operations
- How To Watch The GNTTokenTraderFactory Contract In Ethereum Wallet / Mist
- How To Find GNTTokenTrader Contracts
- How To Verify GNTTokenTrader Contracts
- How To Watch A GNTTokenTrader Contract In Ethereum Wallet / Mist
- Source Code
- GNTTokenTraderFactory Address:
0xc4af56cd5254aef959d4bce2f75874007808b701
- TokenTrader Address:
This is generated dynamically by GNTTokenTraderFactory
- Taker can buy tokens?
Yes
- Taker can sell tokens?
NO
The approximate Ethereum transaction fees to use these contracts follow, assuming a gas price of 0.00000002 Ether and USD ~ cost @ Jan 19 2017. These fees do not vary with the amount of ethers or tokens traded or transferred.
Role | Action | Gas | Cost ETH | Cost USD | Sample Transaction |
---|---|---|---|---|---|
Taker | Buy Token | 40,874 | 0.000817480 | $0.0083 | 0x78e4ca4a... |
Maker | Create Sale Contract | 761,317 | 0.031213997 | $0.3200 | 0x6feb16a4... |
Maker | (De)Activate Contract | No sample yet | |||
Maker | Add Tokens To Contract | 51,720 | 0.001034400 | $0.0100 | 0x54bd74fa... |
Maker | Withdraw Ethers From Contract | 30,516 | 0.000610320 | $0.0062 | 0xf70bbfed... |
Maker | Withdraw Tokens From Contract | 39,504 | 0.000790080 | $0.0081 | 0x3bf83f5e... |
Maker | Withdraw Other Tokens From Contract | No sample yet |
Compare these fees with other exchanges, and consider send some of your huge savings on exchange fees to 0x000001f568875f378bf6d170b790967fe429c81a to help keep this site running and improving.
To purchase tokens from a GNTTokenTrader contract, Find the GNTTokenTrader contract with a price suitable to you and with a GNT balance. Send ethers from your Ethereum address using your favourite wallet (e.g. Ethereum Wallet / Mist, Parity or https://www.myetherwallet.com/). DO NOT send ethers from your exchange (e.g. Poloniex or Kraken) account.
Send a small amount of ethers first and Check Your GNT Balance. Confirm the number of tokens you receive is correct. You should also see your executed trade in https://cryptoderivatives.market/gnt_trades.html:
If you send more ethers than there are tokens owned by the contract at the exchange rate, you will receive a refund of the excess ethers you paid back to your address.
When the Market Taker sends ethers to the GNTTokenTrader contract, the function () payable
in the code below is called. This function then calls function buy() payable
.
//user buys token with ETH
function buy() payable {
if(sellsTokens || msg.sender == owner)
{
uint order = msg.value / sellPrice;
uint can_sell = ERC20(asset).balanceOf(address(this)) / units;
if(order > can_sell)
{
uint256 change = msg.value - (can_sell * sellPrice);
order = can_sell;
if(!msg.sender.send(change)) throw;
}
if(order > 0) {
if(!ERC20(asset).transfer(msg.sender,order * units)) throw;
}
UpdateEvent();
}
else if(!msg.sender.send(msg.value)) throw; // return user funds if the contract is not selling
}
// sending ETH to contract sells GNT to user
function () payable {
buy();
}
The code above has the effect of:
- Transferring
numberOfEthersSentByTaker / sellPrice x units
tokens to the Taker's account - Transferring
numberOfEthersSentByTaker
to the Maker's contract - If there are insufficient tokens in the Maker's contract, the number of tokens transferred to the Taker's account will be limited by this amount. The excess amount of ethers over the amount required to purchase the limited number of tokens in the contract will be sent back to the Taker's account
So, if sellPrice
is 194
and units
is 100,000
, the effective price is 0.00194
ETH per GNT. If if sellPrice
is 1939
and units
is 1,000,000
, the effective price is 0.001939
ETH per GNT.
The operations documented below are for use with Ethereum Wallet / Mist.
-
Click on SHOW CONTRACT INFO to display the READ FROM CONTRACT and WRITE TO CONTRACT headings
-
Under Select function, select Create Trade Contract
-
Under asset - address, enter the GNT token address
0xa74476443119a942de498590fe1f2454d7d4ac0d
as listed in GNT - Token Contract Information -
Under sell price, enter the sell price per unit. sellPrice/unit is the ETH rate per GNT. For example
194 / 100,000 = 0.00194
which is0.00194
ETH per GNT token. -
Under units, enter the units. The recommended value to use is
100,000
-
Under sells tokens, tick the Yes checkbox if you want this selling function activated immediately
-
Click on Execute, then confirm your transaction.
-
After creating the new GNTTokenTrader contract:
Here are some sample contracts. Enter the contract address into the GNTTokenTraderFactory verify field and click Query to view the contract data:
Address | asset | sellPrice | units | ETH per GNT |
---|---|---|---|---|
0x45ff5e9d... |
0xa7447644... |
193 |
100000 |
0.00193000 |
0x32ed5652... |
0xa7447644... |
2109 |
999977 |
0.00210905 |
0x66712798... |
0xa7447644... |
190 |
90000 |
0.00211111 |
(sample) | 0xa7447644... |
2345 |
1000000 |
0.00234500 |
Note that asset must always be the GNT contract address which is 0xa74476443119a942de498590fe1f2454d7d4ac0d
.
For a contract to be listed on https://cryptoderivatives.market/, the following conditions need to be met:
- sellsTokens = true
- units >= 1
- units <= 100,000,000
- (sellPrice / units) >= 0.0000001
- (sellPrice / units) <= 1,000,000
- tokenBalance >= 0.00000001
Watch the GNTTokenTrader contract. View the contract and under the WRITE TO CONTRACT section:
-
Under Select function, select Activate
-
Under sells tokens, tick the Yes checkbox to activate the contract or untick the checkbox to deactivate the contract
-
Click on Execute, then confirm your transaction.
To add tokens to the GNTTokenTrader contract, Transfer Your GNT Tokens to the GNTTokenTrader contract address.
Watch the GNTTokenTrader contract. View the contract and under the WRITE TO CONTRACT section:
-
Under Select function, select Withdraw
-
Under value, enter the number of ethers to 18 decimal places. e.g.,
1230000000000000000
is1230000000000000000 / 1e18 = 1.23
ETH -
Under Execute from, select your account that is the owner of this GNTTokenTrader contract
-
Click on Execute, then confirm your transaction.
Watch the GNTTokenTrader contract. View the contract and under the WRITE TO CONTRACT section:
-
Under Select function, select Withdraw Asset
-
Under value, enter the number of GNTs to 18 decimal places. e.g.,
1230000000000000000
is1230000000000000000 / 1e18 = 1.23
GNT -
Under Execute from, select your account that is the owner of this GNTTokenTrader contract
-
Click on Execute, then confirm your transaction.
This function is to allow the owner to withdraw tokens OTHER than GNTs that have been accidentally sent to the GNTTokenTrader contract.
Watch the GNTTokenTrader contract. View the contract and under the WRITE TO CONTRACT section:
-
Under Select function, select Withdraw Token
-
Under token - address, enter the address of the token contract. e.g., the address for Augur REP is 0x48c80f1f4d53d5951e5d5438b54cba84f29f32a5
-
Under value, enter the number of tokens. Note that you will have to take into account the number of decimal places the tokens are denominated in. For Augur REP this is 18 decimal places. e.g.,
2340000000000000000
is2340000000000000000 / 1e18 = 2.34
REP -
Under Execute from, select your account that is the owner of this GNTTokenTrader contract
-
Click on Execute, then confirm your transaction.
In Ethereum Wallet / Mist, select the CONTRACTS tab and click WATCH CONTRACT to open the Watch contract window. Then:
-
Under CONTRACT NAME, enter
GNTTokenTraderFactory
-
Under CONTRACT ADDRESS:
- For Mainnet, enter
0xc4af56cd5254aef959d4bce2f75874007808b701
- For Mainnet, enter
-
Copy the Application Binary Interface below and paste it into the JSON INTERFACE text box
[{"constant":false,"inputs":[{"name":"_asset","type":"address"},{"name":"_sellPrice","type":"uint256"},{"name":"_units","type":"uint256"},{"name":"_sellsTokens","type":"bool"}],"name":"createTradeContract","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"tradeContract","type":"address"}],"name":"verify","outputs":[{"name":"valid","type":"bool"},{"name":"asset","type":"address"},{"name":"sellPrice","type":"uint256"},{"name":"units","type":"uint256"},{"name":"sellsTokens","type":"bool"}],"payable":false,"type":"function"},{"payable":false,"type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"bookid","type":"bytes32"},{"indexed":false,"name":"owner","type":"address"},{"indexed":false,"name":"addr","type":"address"}],"name":"TradeListing","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"bookid","type":"bytes32"},{"indexed":false,"name":"asset","type":"address"},{"indexed":false,"name":"units","type":"uint256"}],"name":"NewBook","type":"event"}]
-
Click OK
Navigate to https://cryptoderivatives.market/ and the contract addresses are on the left column of the top grid:
View the GNTTokenTraderFactory contract in Ethereum Wallet (see above). Scroll to the bottom of the page. You may have to click on Watch contract events to trigger the loading of the events. In the first event on the page, the GNTTokenTrader address is listed in the field addr, and in this case is 0x1a22bb6827dbb7df60a6de726519c2a509271695
.
Navigate to https://etherscan.io/address/0xc4af56cd5254aef959d4bce2f75874007808b701#internaltx.
Click on the Contract Creation field in the To column to view the GNTTokenTrader contract details as shown below:
There is a findGNTTokenTrader
script in https://github.com/bokkypoobah/FindGNTTokenTrader .
Here is some sample output from https://github.com/bokkypoobah/FindGNTTokenTrader/blob/master/findGNTTokenTraderOutput_20161116_005815UTC.csv:
\#,TokenTraderAddress,SellsTokens,EtherPer1000Tokens,TokenBalance
26,0x4b17f65fc6450cbcced9e893dd84123a5fc13362,TRUE,1.45,110624.7596
27,0x1e00980cb7b109d290fcf6c4e579debb8c836c39,TRUE,1.45,164700.3448
24,0x1a22bb6827dbb7df60a6de726519c2a509271695,TRUE,1.5,499660.2167
6,0xc0081f0e16cbceec6df8e63986212a52ee493540,TRUE,1.88,102821.2909
23,0x406a65de7a2e94ef19597a79296e269fada85a71,TRUE,1.9,136166.8742
15,0x5eb860c816789bb52300a0675300701eca203cf8,TRUE,1.95,158854.1026
0,0x399156ee3339f4b29a53e307b98cce09fda3bac7,TRUE,2,5430.015
10,0xa7f8da2594eaf1e8573a5974be6028f64157cd7a,TRUE,2,713516
22,0xf31057bc0ff5e3e3b32652b29c0451624392567c,TRUE,2,100050
25,0xffd41efe3d3c073f4c7dbf2cec7c19111fc7523e,TRUE,2,4250
17,0x6e3f7ad4d9accb12452744fb2785ecac31ea8026,TRUE,2.05,50000
18,0x4b34da26bfb35d3089c455cb483a5fff8695d447,TRUE,2.11,200000
11,0x42be3b481f25b0148cd1a144d8ca22cda5b677e7,TRUE,2.33,9.00E-12
2,0x4104e4b12e73bc99dd4f20a39525d07aa395c0d4,TRUE,3,1794.833333
19,0x593fd4a14f64282891a1369442462361a1908b01,TRUE,3.75,900
View the GNTTokenTraderFactory contract in Ethereum Wallet (see above). You may have to click on SHOW CONTRACT INFO. In the READ FROM CONTRACT section, enter the address of the GNTTokenTrader contract you want to verify. I have used 0x1a22bb6827dbb7df60a6de726519c2a509271695
in the following screen. The status of the contract at the address entered will be displayed.
Navigate to https://etherscan.io/ and enter the GNTTokenTrader contract into the search box. In this example I have used the address 0xaf4ace80410fe1274a2244a3714d387c11b020a8. You can view the ether balance in the ETH Balance field. You can view the token balance in the View Token Balances dropdown. Only the Golem token balance is relevant to this GNTTokenTrader contract.
Click on the first address in the Contract Creator field - this should be the GNTTokenTraderFactory contract at address 0xc4af56cd5254aef959d4bce2f75874007808b701. Click on the Read Contract tab. In the verify field, enter the address of the GNTTokenTrader contract to be verified. In this example I have used the address 0xaf4ace80410fe1274a2244a3714d387c11b020a8
and the results show that this contract is a valid GNTTokenTrader contract with a selling price of 194 / 100000 = 0.00194
ETH per GNT.
In Ethereum Wallet / Mist, select the CONTRACTS tab and click WATCH CONTRACT to open the Watch contract window. Then:
-
Under CONTRACT NAME, enter
{GNTTokenTrader identifying information}
, e.g.,GNTTT 1.94
-
Under CONTRACT ADDRESS, enter the contract address as you have found and verified in the section above.
-
Copy the Application Binary Interface below and paste it into the JSON INTERFACE text box
[{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"withdraw","outputs":[{"name":"ok","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"asset","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"sellPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"sellsTokens","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"withdrawAsset","outputs":[{"name":"ok","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"units","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_value","type":"uint256"}],"name":"withdrawToken","outputs":[{"name":"ok","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"buy","outputs":[],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_sellsTokens","type":"bool"}],"name":"activate","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"type":"function"},{"inputs":[{"name":"_asset","type":"address"},{"name":"_sellPrice","type":"uint256"},{"name":"_units","type":"uint256"},{"name":"_sellsTokens","type":"bool"}],"type":"constructor","payable":true},{"payable":true,"type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sells","type":"bool"}],"name":"ActivatedEvent","type":"event"},{"anonymous":false,"inputs":[],"name":"UpdateEvent","type":"event"}]
-
Click OK
If you now click on the newly created Watch Contract entry, you will see a screen like the following:
The Golem Network Token balance requires that you have created a Watch Token entry for the Golem Network Token as described in How To Watch The GNT Token In Ethereum Wallet / Mist.
Click on the SHOW CONTRACT INFO button. You can now see the functions the Market Maker and Market Taker are able to execute - the details are described in the next two sections.
Following is the source code for the TokenTraderFactory contract (which includes TokenTrader) on:
pragma solidity ^0.4.0;
//https://github.com/nexusdev/erc20/blob/master/contracts/erc20.sol
contract ERC20Constant {
function balanceOf( address who ) constant returns (uint value);
}
contract ERC20Stateful {
function transfer( address to, uint value) returns (bool ok);
}
contract ERC20Events {
event Transfer(address indexed from, address indexed to, uint value);
}
contract ERC20 is ERC20Constant, ERC20Stateful, ERC20Events {}
contract owned {
address public owner;
function owned() {
owner = msg.sender;
}
modifier onlyOwner {
if (msg.sender != owner) throw;
_;
}
function transferOwnership(address newOwner) onlyOwner {
owner = newOwner;
}
}
// contract can sell tokens for ETH
// prices are in amount of wei per batch of token units
contract TokenTrader is owned {
address public asset; // address of token
uint256 public sellPrice; // contract sells lots of tokens at this price
uint256 public units; // lot size (token-wei)
bool public sellsTokens; // is contract selling
event ActivatedEvent(bool sells);
event UpdateEvent();
function TokenTrader (
address _asset,
uint256 _sellPrice,
uint256 _units,
bool _sellsTokens
)
{
asset = _asset;
sellPrice = _sellPrice;
units = _units;
sellsTokens = _sellsTokens;
ActivatedEvent(sellsTokens);
}
// modify trading behavior
function activate (
bool _sellsTokens
) onlyOwner
{
sellsTokens = _sellsTokens;
ActivatedEvent(sellsTokens);
}
// allow owner to remove trade token
function withdrawAsset(uint256 _value) onlyOwner returns (bool ok)
{
return ERC20(asset).transfer(owner,_value);
UpdateEvent();
}
// allow owner to remove arbitrary tokens
// included just in case contract receives wrong token
function withdrawToken(address _token, uint256 _value) onlyOwner returns (bool ok)
{
return ERC20(_token).transfer(owner,_value);
UpdateEvent();
}
// allow owner to remove ETH
function withdraw(uint256 _value) onlyOwner returns (bool ok)
{
if(this.balance >= _value) {
return owner.send(_value);
}
UpdateEvent();
}
//user buys token with ETH
function buy() payable {
if(sellsTokens || msg.sender == owner)
{
uint order = msg.value / sellPrice;
uint can_sell = ERC20(asset).balanceOf(address(this)) / units;
if(order > can_sell)
{
uint256 change = msg.value - (can_sell * sellPrice);
order = can_sell;
if(!msg.sender.send(change)) throw;
}
if(order > 0) {
if(!ERC20(asset).transfer(msg.sender,order * units)) throw;
}
UpdateEvent();
}
else if(!msg.sender.send(msg.value)) throw; // return user funds if the contract is not selling
}
// sending ETH to contract sells GNT to user
function () payable {
buy();
}
}
// This contract deploys TokenTrader contracts and logs the event
// trade pairs are identified with sha3(asset,units)
contract TokenTraderFactory {
event TradeListing(bytes32 bookid, address owner, address addr);
event NewBook(bytes32 bookid, address asset, uint256 units);
mapping( address => bool ) _verify;
mapping( bytes32 => bool ) pairExits;
function verify(address tradeContract) constant returns (
bool valid,
address asset,
uint256 sellPrice,
uint256 units,
bool sellsTokens
) {
valid = _verify[tradeContract];
if(valid) {
TokenTrader t = TokenTrader(tradeContract);
asset = t.asset();
sellPrice = t.sellPrice();
units = t.units();
sellsTokens = t.sellsTokens();
}
}
function createTradeContract(
address _asset,
uint256 _sellPrice,
uint256 _units,
bool _sellsTokens
) returns (address)
{
if(_units == 0) throw; // can't sell zero units
address trader = new TokenTrader (
_asset,
_sellPrice,
_units,
_sellsTokens);
var bookid = sha3(_asset,_units);
_verify[trader] = true; // record that this factory created the trader
TokenTrader(trader).transferOwnership(msg.sender); // set the owner to whoever called the function
if(pairExits[bookid] == false) {
pairExits[bookid] = true;
NewBook(bookid, _asset, _units);
}
TradeListing(bookid,msg.sender,trader);
}
function () {
throw; // Prevents accidental sending of ether to the factory
}
}
Most of this wiki is currently work in progress. GNTTokenTrader & Factory, GNT ‐ Golem Network Token and Bug Bounty are complete.
- 1ST ‐ First Blood
- AMIS ‐ AMIS
- ARC ‐ Arcade City
- BARF ‐ BARF (discontinued)
- BERP ‐ BokkyPooBah´s Ether Refundable Prize
- DAO ‐ The DAO
- DGD ‐ Digix DAO
- DGDb ‐ Digix DAO Badge
- DICE ‐ Etheroll
- EDG ‐ Edgeless
- EMV ‐ Ethereum Movie Venture
- ETB ‐ Ethbits
- GNO ‐ Gnosis Token
- GNT ‐ Golem Network Token
- GNTW ‐ Wrapped Golem Network Token
- GUP ‐ Matchpool Guppy
- HKG ‐ Hacker Gold
- HMQ ‐ Humaniq
- ICN ‐ Iconomi
- INC ‐ Incent
- LOVE - I Love You
- LUN ‐ Lunyr-Token
- MKR ‐ Maker DAO
- MLN ‐ Melon Token
- PLU ‐ Pluton
- RBX ‐ Ripto Bux
- REP ‐ Augur
- RLC ‐ iEx.ec Network Token
- SNGLS ‐ SingularDTV
- SWT ‐ Swarm City
- TAAS ‐ Token-as-a-Service
- TIME ‐ Chronobank
- TKN ‐ TokenCard
- TRST ‐ WeTrust
- UNI - Unicorn 🦄
- VSL - vSlice
- WAV ‐ Waves Token
- WBC ‐ Waves Bitcoin Token
- WCT ‐ Waves Community Token
- WINGS ‐ WINGS
- XAUR ‐ Xaurum