CDT  v4.2.0
инструменты разработчика
asset.hpp
См. документацию.
1#pragma once
2
3#include "serialize.hpp"
4#include "print.hpp"
5#include "check.hpp"
6#include "symbol.hpp"
7
8#include <tuple>
9#include <limits>
10
11namespace eosio {
12
13 char* write_decimal( char* begin, char* end, bool dry_run, uint64_t number, uint8_t num_decimal_places, bool negative );
14
26 struct asset {
30 int64_t amount = 0;
31
36
40 static constexpr int64_t max_amount = (1LL << 62) - 1;
41
42 asset() {}
43
50 asset( int64_t a, class symbol s )
51 :amount(a),symbol{s}
52 {
53 eosio::check( is_amount_within_range(), "magnitude of asset amount must be less than 2^62" );
54 eosio::check( symbol.is_valid(), "invalid symbol name" );
55 }
56
63 bool is_amount_within_range()const { return -max_amount <= amount && amount <= max_amount; }
64
71 bool is_valid()const { return is_amount_within_range() && symbol.is_valid(); }
72
78 void set_amount( int64_t a ) {
79 amount = a;
80 eosio::check( is_amount_within_range(), "magnitude of asset amount must be less than 2^62" );
81 }
82
84
90 asset operator-()const {
91 asset r = *this;
92 r.amount = -r.amount;
93 return r;
94 }
95
103 asset& operator-=( const asset& a ) {
104 eosio::check( a.symbol == symbol, "attempt to subtract asset with different symbol" );
105 amount -= a.amount;
106 eosio::check( -max_amount <= amount, "subtraction underflow" );
107 eosio::check( amount <= max_amount, "subtraction overflow" );
108 return *this;
109 }
110
118 asset& operator+=( const asset& a ) {
119 eosio::check( a.symbol == symbol, "attempt to add asset with different symbol" );
120 amount += a.amount;
121 eosio::check( -max_amount <= amount, "addition underflow" );
122 eosio::check( amount <= max_amount, "addition overflow" );
123 return *this;
124 }
125
133 inline friend asset operator+( const asset& a, const asset& b ) {
134 asset result = a;
135 result += b;
136 return result;
137 }
138
146 inline friend asset operator-( const asset& a, const asset& b ) {
147 asset result = a;
148 result -= b;
149 return result;
150 }
151
160 asset& operator*=( int64_t a ) {
161 int128_t tmp = (int128_t)amount * (int128_t)a;
162 eosio::check( tmp <= max_amount, "multiplication overflow" );
163 eosio::check( tmp >= -max_amount, "multiplication underflow" );
164 amount = (int64_t)tmp;
165 return *this;
166 }
167
176 friend asset operator*( const asset& a, int64_t b ) {
177 asset result = a;
178 result *= b;
179 return result;
180 }
181
182
190 friend asset operator*( int64_t b, const asset& a ) {
191 asset result = a;
192 result *= b;
193 return result;
194 }
195
204 asset& operator/=( int64_t a ) {
205 eosio::check( a != 0, "divide by zero" );
206 eosio::check( !(amount == std::numeric_limits<int64_t>::min() && a == -1), "signed division overflow" );
207 amount /= a;
208 return *this;
209 }
210
218 friend asset operator/( const asset& a, int64_t b ) {
219 asset result = a;
220 result /= b;
221 return result;
222 }
223
232 friend int64_t operator/( const asset& a, const asset& b ) {
233 eosio::check( b.amount != 0, "divide by zero" );
234 eosio::check( a.symbol == b.symbol, "attempt to divide assets with different symbol" );
235 return a.amount / b.amount;
236 }
237
247 friend bool operator==( const asset& a, const asset& b ) {
248 eosio::check( a.symbol == b.symbol, "comparison of assets with different symbols is not allowed" );
249 return a.amount == b.amount;
250 }
251
261 friend bool operator!=( const asset& a, const asset& b ) {
262 return !( a == b);
263 }
264
274 friend bool operator<( const asset& a, const asset& b ) {
275 eosio::check( a.symbol == b.symbol, "comparison of assets with different symbols is not allowed" );
276 return a.amount < b.amount;
277 }
278
288 friend bool operator<=( const asset& a, const asset& b ) {
289 eosio::check( a.symbol == b.symbol, "comparison of assets with different symbols is not allowed" );
290 return a.amount <= b.amount;
291 }
292
302 friend bool operator>( const asset& a, const asset& b ) {
303 eosio::check( a.symbol == b.symbol, "comparison of assets with different symbols is not allowed" );
304 return a.amount > b.amount;
305 }
306
316 friend bool operator>=( const asset& a, const asset& b ) {
317 eosio::check( a.symbol == b.symbol, "comparison of assets with different symbols is not allowed" );
318 return a.amount >= b.amount;
319 }
320
322
335 char* write_as_string( char* begin, char* end, bool dry_run = false )const {
336 bool negative = (amount < 0);
337 uint64_t abs_amount = static_cast<uint64_t>(negative ? -amount : amount);
338 // 0 <= abs_amount <= std::numeric_limits<int64_t>::max() < 10^19 < std::numeric_limits<uint64_t>::max()
339
340 uint8_t precision = symbol.precision();
341
342 int sufficient_size = std::max(static_cast<int>(precision), 19) + 11;
343 if( dry_run || (begin + sufficient_size < begin) || (begin + sufficient_size > end) ) {
344 char* start_of_symbol = write_decimal( begin, end, true, abs_amount, precision, negative ) + 1;
345 char* actual_end = symbol.code().write_as_string( start_of_symbol, end, true );
346 if( dry_run || (actual_end < begin) || (actual_end > end) ) return actual_end;
347 }
348
349 char* end_of_number = write_decimal( begin, end, false, abs_amount, precision, negative );
350 *(end_of_number) = ' ';
351
352 return symbol.code().write_as_string( end_of_number + 1, end );
353 }
354
360 std::string to_string()const {
361 int buffer_size = std::max(static_cast<int>(symbol.precision()), 19) + 11;
362 char buffer[buffer_size];
363 char* end = write_as_string( buffer, buffer + buffer_size );
364 check( end <= buffer + buffer_size, "insufficient space in buffer" ); // should never fail
365
366 return {buffer, end};
367 }
368
374 void print()const {
375 int buffer_size = std::max(static_cast<int>(symbol.precision()), 19) + 11;
376 char buffer[buffer_size];
377 char* end = write_as_string( buffer, buffer + buffer_size );
378 check( end <= buffer + buffer_size, "insufficient space in buffer" ); // should never fail
379
380 if( buffer < end )
381 printl( buffer, (end-buffer) );
382 }
383
385 };
386
397
402
409
413 extended_asset() = default;
414
418 extended_asset( int64_t v, extended_symbol s ):quantity(v,s.get_symbol()),contract(s.get_contract()){}
423
427 void print()const {
428 quantity.print();
430 }
431
433
434 // Унарный минус
435 extended_asset operator-()const {
436 return {-quantity, contract};
437 }
438
439 // Оператор вычитания
440 friend extended_asset operator - ( const extended_asset& a, const extended_asset& b ) {
441 eosio::check( a.contract == b.contract, "type mismatch" );
442 return {a.quantity - b.quantity, a.contract};
443 }
444
445 // Оператор сложения
446 friend extended_asset operator + ( const extended_asset& a, const extended_asset& b ) {
447 eosio::check( a.contract == b.contract, "type mismatch" );
448 return {a.quantity + b.quantity, a.contract};
449 }
450
452 friend extended_asset& operator+=( extended_asset& a, const extended_asset& b ) {
453 eosio::check( a.contract == b.contract, "type mismatch" );
454 a.quantity += b.quantity;
455 return a;
456 }
457
459 friend extended_asset& operator-=( extended_asset& a, const extended_asset& b ) {
460 eosio::check( a.contract == b.contract, "type mismatch" );
461 a.quantity -= b.quantity;
462 return a;
463 }
464
466 extended_asset& operator*=( int64_t b ) {
467 quantity *= b;
468 return *this;
469 }
470
472 friend extended_asset operator*( const extended_asset& a, int64_t b ) {
473 return {a.quantity * b, a.contract};
474 }
475
477 friend extended_asset operator*( int64_t a, const extended_asset& b ) {
478 return {a * b.quantity, b.contract};
479 }
480
482 friend int64_t operator/( const extended_asset& a, const extended_asset& b ) {
483 eosio::check( a.contract == b.contract, "type mismatch" );
484 return a.quantity / b.quantity;
485 }
486
488 extended_asset& operator/=( int64_t b ) {
489 quantity /= b;
490 return *this;
491 }
492
494 friend extended_asset operator/( const extended_asset& a, int64_t b ) {
495 return {a.quantity / b, a.contract};
496 }
497
498
500 friend bool operator<( const extended_asset& a, const extended_asset& b ) {
501 eosio::check( a.contract == b.contract, "type mismatch" );
502 return a.quantity < b.quantity;
503 }
504
506 friend bool operator>( const extended_asset& a, const extended_asset& b ) {
507 eosio::check( a.contract == b.contract, "type mismatch" );
508 return a.quantity > b.quantity;
509 }
510
512 friend bool operator==( const extended_asset& a, const extended_asset& b ) {
513 return std::tie(a.quantity, a.contract) == std::tie(b.quantity, b.contract);
514 }
515
517 friend bool operator!=( const extended_asset& a, const extended_asset& b ) {
518 return std::tie(a.quantity, a.contract) != std::tie(b.quantity, b.contract);
519 }
520
522 friend bool operator<=( const extended_asset& a, const extended_asset& b ) {
523 eosio::check( a.contract == b.contract, "type mismatch" );
524 return a.quantity <= b.quantity;
525 }
526
528 friend bool operator>=( const extended_asset& a, const extended_asset& b ) {
529 eosio::check( a.contract == b.contract, "type mismatch" );
530 return a.quantity >= b.quantity;
531 }
532
534
536 };
537}