1、功能:
Exchange 合约提供了创建和交易货币的能力。
使用户能够在任何一对之间创建交换标准货币类型。通过为订单簿的双方提供相同的价值并为发行人提供该订单簿中的初始份额来创建新的交易所。
为防止过多的舍入错误,初始存款应包括相当数量的基础货币和报价货币,交换股份的数量应为最大初始存款数量的100倍。
用户必须先将资金存入交易所,然后才能在交易所进行交易。
每次创建交易所时,也会创建该交易所做市商的新货币。 此货币供应和符号必须是唯一的,并使用货币合约的表来管理它。
2、exchange/exchange.hpp
2.1 头文件
//类型
\#include <eosiolib/types.hpp>
//货币头文件
\#include <eosiolib/currency.hpp>
\#include <boost/container/flat_map.hpp>
\#include \<\cmath>
//销售状态
\#include <exchange/market_state.hpp>
2.2 构造函数
class exchange {
private:
account_name _this_contract;
currency _excurrencies;
exchange_accounts _accounts;
public:
exchange( account_name self ):_this_contract(self),
2.2 功能函数
piblic:
//创建交易
void createx( account_name creator,
asset initial_supply,
uint32_t fee,
extended_asset base_deposit,
extended_asset quote_deposit
);
//处理存款
void deposit( account_name from, extended_asset quantity );
//取款
void withdraw( account_name from, extended_asset quantity );
//借贷
void lend( account_name lender, symbol_type market, extended_asset quantity );
3、exchange/exchange.cpp
3.1 apply方法:每次action 运行时,在合约实现中调用apply()响应次操作。
extern "C" {
//noreturn:执行完成后不会返回调用者
[[noreturn]] void apply( uint64_t receiver, uint64_t code, uint64_t action ) {
//创建exchange对象
eosio::exchange ex( receiver );
//调用apply方法
ex.apply( code, action );
//退出程序
eosio_exit(0);
}
apply
void exchange::apply( account_name contract, account_name act ) {
//操作是transfer类型的处理
if( act == N(transfer) ) {
on( unpack_action_data<currency::transfer>(), contract );
return;
}
//合约不是当前合约返回
if( contract != _this_contract )
return;
//执行exchange合约的各种action
auto& thiscontract = *this;
switch( act ) {
EOSIO_API( exchange, (createx)(deposit)(withdraw)(lend)(unlend) )
};
//对exchange处理后不同的action进行操作
switch( act ) {
case N(trade):
on( unpack_action_data<trade>() );
return;
case N(upmargin):
on( unpack_action_data<upmargin>() );
return;
case N(covermargin):
on( unpack_action_data<covermargin>() );
return;
default:
_excurrencies.apply( contract, act );
return;
}
}
3.2 创建交易
void exchange::createx( account_name creator,
asset initial_supply,
uint32_t /* fee */,
extended_asset base_deposit,
extended_asset quote_deposit
) {
//需要creator的授权
require_auth( creator );
//检验初始发行量是否有效、是否大于0
eosio_assert( initial_supply.is_valid(), "invalid initial supply" );
eosio_assert( initial_supply.amount > 0, "initial supply must be positive" );
//检验基础存款
eosio_assert( base_deposit.is_valid(), "invalid base deposit" );
eosio_assert( base_deposit.amount > 0, "base deposit must be positive" );
//检验引用存款
eosio_assert( quote_deposit.is_valid(), "invalid quote deposit" );
eosio_assert( quote_deposit.amount > 0, "quote deposit must be positive" );
//检验两种资产是否是同种货币
eosio_assert( base_deposit.get_extended_symbol() != quote_deposit.get_extended_symbol(),
"must exchange between two different currencies" );
print( "base: ", base_deposit.get_extended_symbol() );
print( "quote: ",quote_deposit.get_extended_symbol() );
auto exchange_symbol = initial_supply.symbol.name();
print( "marketid: ", exchange_symbol, " \n " );
//这样并不是直接建立了一个新表,而是让 C++ 程序与数据库对应的表之间建立了数据传输的通道
markets exstates( _this_contract, exchange_symbol );
//在数据表中查找交易符号
auto existing = exstates.find( exchange_symbol );
eosio_assert( existing == exstates.end(), "market already exists" );
exstates.emplace( creator, [&]( auto& s ) {
s.manager = creator;
s.supply = extended_asset(initial_supply, _this_contract);
s.base.balance = base_deposit;
s.quote.balance = quote_deposit;
s.base.peer_margin.total_lent.symbol = base_deposit.symbol;
s.base.peer_margin.total_lent.contract = base_deposit.contract;
s.base.peer_margin.total_lendable.symbol = base_deposit.symbol;
s.base.peer_margin.total_lendable.contract = base_deposit.contract;
s.quote.peer_margin.total_lent.symbol = quote_deposit.symbol;
s.quote.peer_margin.total_lent.contract = quote_deposit.contract;
s.quote.peer_margin.total_lendable.symbol = quote_deposit.symbol;
s.quote.peer_margin.total_lendable.contract = quote_deposit.contract;
});
_excurrencies.create_currency( { .issuer = _this_contract,
// TODO: After currency contract respects maximum supply limits, the maximum supply here needs to be set appropriately.
.maximum_supply = asset( 0, initial_supply.symbol ),
.issuer_can_freeze = false,
.issuer_can_whitelist = false,
.issuer_can_recall = false } );
_excurrencies.issue_currency( { .to = _this_contract,
.quantity = initial_supply,
.memo = string("initial exchange tokens") } );
_accounts.adjust_balance( creator, extended_asset( initial_supply, _this_contract ), "new exchange issue" );
_accounts.adjust_balance( creator, -base_deposit, "new exchange deposit" );
_accounts.adjust_balance( creator, -quote_deposit, "new exchange deposit" );
}