├── README.md ├── eos_button.abi ├── eos_button.cpp ├── eos_button.hpp ├── eos_button.wasm └── eos_button.wast /README.md: -------------------------------------------------------------------------------- 1 | # eosbutton-contract 2 | EOS Button Contract\ 3 | EOS account: theeosbutton\ 4 | Website: https://eosbutton.io \ 5 | Discord: https://discord.gg/ZhyK6xU 6 | -------------------------------------------------------------------------------- /eos_button.abi: -------------------------------------------------------------------------------- 1 | { 2 | "____comment": "This file was generated by eosio-abigen. DO NOT EDIT - 2018-07-21T11:15:38", 3 | "version": "eosio::abi/1.0", 4 | "types": [{ 5 | "new_type_name": "time", 6 | "type": "uint32" 7 | } 8 | ], 9 | "structs": [{ 10 | "name": "account", 11 | "base": "", 12 | "fields": [{ 13 | "name": "balance", 14 | "type": "asset" 15 | } 16 | ] 17 | },{ 18 | "name": "cur_stats", 19 | "base": "", 20 | "fields": [{ 21 | "name": "supply", 22 | "type": "asset" 23 | },{ 24 | "name": "max_supply", 25 | "type": "asset" 26 | },{ 27 | "name": "issuer", 28 | "type": "name" 29 | } 30 | ] 31 | },{ 32 | "name": "ebtgame", 33 | "base": "", 34 | "fields": [{ 35 | "name": "id", 36 | "type": "uint64" 37 | },{ 38 | "name": "round", 39 | "type": "uint64" 40 | },{ 41 | "name": "last_full_press_shares", 42 | "type": "uint64" 43 | },{ 44 | "name": "shares", 45 | "type": "uint64" 46 | },{ 47 | "name": "total_shares", 48 | "type": "uint64" 49 | },{ 50 | "name": "pot", 51 | "type": "asset" 52 | },{ 53 | "name": "final_prize", 54 | "type": "asset" 55 | },{ 56 | "name": "token_reserved_for_next_round", 57 | "type": "asset" 58 | },{ 59 | "name": "dev_fee", 60 | "type": "asset" 61 | },{ 62 | "name": "last_full_press_player", 63 | "type": "name" 64 | },{ 65 | "name": "start_time", 66 | "type": "time" 67 | },{ 68 | "name": "last_full_press_time", 69 | "type": "time" 70 | },{ 71 | "name": "last_full_press_remaining_time", 72 | "type": "time" 73 | } 74 | ] 75 | },{ 76 | "name": "eosgame", 77 | "base": "", 78 | "fields": [{ 79 | "name": "id", 80 | "type": "uint64" 81 | },{ 82 | "name": "round", 83 | "type": "uint64" 84 | },{ 85 | "name": "last_full_press_shares", 86 | "type": "uint64" 87 | },{ 88 | "name": "shares", 89 | "type": "uint64" 90 | },{ 91 | "name": "total_shares", 92 | "type": "uint64" 93 | },{ 94 | "name": "pot", 95 | "type": "asset" 96 | },{ 97 | "name": "final_prize", 98 | "type": "asset" 99 | },{ 100 | "name": "token_reserved_for_next_round", 101 | "type": "asset" 102 | },{ 103 | "name": "dev_fee", 104 | "type": "asset" 105 | },{ 106 | "name": "last_full_press_player", 107 | "type": "name" 108 | },{ 109 | "name": "start_time", 110 | "type": "time" 111 | },{ 112 | "name": "last_full_press_time", 113 | "type": "time" 114 | },{ 115 | "name": "last_full_press_remaining_time", 116 | "type": "time" 117 | } 118 | ] 119 | },{ 120 | "name": "ebtplayer", 121 | "base": "", 122 | "fields": [{ 123 | "name": "account", 124 | "type": "name" 125 | },{ 126 | "name": "shares", 127 | "type": "uint64" 128 | },{ 129 | "name": "last_press_shares", 130 | "type": "uint64" 131 | },{ 132 | "name": "last_press_info", 133 | "type": "uint64" 134 | },{ 135 | "name": "last_press_remaining_time", 136 | "type": "time" 137 | } 138 | ] 139 | },{ 140 | "name": "eosplayer", 141 | "base": "", 142 | "fields": [{ 143 | "name": "account", 144 | "type": "name" 145 | },{ 146 | "name": "shares", 147 | "type": "uint64" 148 | },{ 149 | "name": "last_press_shares", 150 | "type": "uint64" 151 | },{ 152 | "name": "last_press_info", 153 | "type": "uint64" 154 | },{ 155 | "name": "last_press_remaining_time", 156 | "type": "time" 157 | } 158 | ] 159 | },{ 160 | "name": "accstate", 161 | "base": "", 162 | "fields": [{ 163 | "name": "account", 164 | "type": "name" 165 | },{ 166 | "name": "last_airdrop_claim_time", 167 | "type": "time" 168 | },{ 169 | "name": "eos_balance", 170 | "type": "asset" 171 | } 172 | ] 173 | },{ 174 | "name": "ebtpress", 175 | "base": "", 176 | "fields": [{ 177 | "name": "account", 178 | "type": "name" 179 | },{ 180 | "name": "quantity", 181 | "type": "asset" 182 | },{ 183 | "name": "protection", 184 | "type": "bool" 185 | },{ 186 | "name": "referrer", 187 | "type": "name" 188 | } 189 | ] 190 | },{ 191 | "name": "claimad", 192 | "base": "", 193 | "fields": [{ 194 | "name": "account", 195 | "type": "name" 196 | } 197 | ] 198 | } 199 | ], 200 | "actions": [{ 201 | "name": "ebtpress", 202 | "type": "ebtpress", 203 | "ricardian_contract": "" 204 | },{ 205 | "name": "claimad", 206 | "type": "claimad", 207 | "ricardian_contract": "" 208 | } 209 | ], 210 | "tables": [{ 211 | "name": "accounts", 212 | "index_type": "i64", 213 | "key_names": [ 214 | "balance" 215 | ], 216 | "key_types": [ 217 | "asset" 218 | ], 219 | "type": "account" 220 | },{ 221 | "name": "stat", 222 | "index_type": "i64", 223 | "key_names": [ 224 | "supply" 225 | ], 226 | "key_types": [ 227 | "asset" 228 | ], 229 | "type": "cur_stats" 230 | },{ 231 | "name": "ebtgames", 232 | "index_type": "i64", 233 | "key_names": [ 234 | "id" 235 | ], 236 | "key_types": [ 237 | "uint64" 238 | ], 239 | "type": "ebtgame" 240 | },{ 241 | "name": "eosgames", 242 | "index_type": "i64", 243 | "key_names": [ 244 | "id" 245 | ], 246 | "key_types": [ 247 | "uint64" 248 | ], 249 | "type": "eosgame" 250 | },{ 251 | "name": "ebtplayers", 252 | "index_type": "i64", 253 | "key_names": [ 254 | "account" 255 | ], 256 | "key_types": [ 257 | "name" 258 | ], 259 | "type": "ebtplayer" 260 | },{ 261 | "name": "eosplayers", 262 | "index_type": "i64", 263 | "key_names": [ 264 | "account" 265 | ], 266 | "key_types": [ 267 | "name" 268 | ], 269 | "type": "eosplayer" 270 | },{ 271 | "name": "accstates", 272 | "index_type": "i64", 273 | "key_names": [ 274 | "account" 275 | ], 276 | "key_types": [ 277 | "name" 278 | ], 279 | "type": "accstate" 280 | } 281 | ], 282 | "ricardian_clauses": [], 283 | "error_messages": [], 284 | "abi_extensions": [] 285 | } -------------------------------------------------------------------------------- /eos_button.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @copyright defined in eos/LICENSE.txt 4 | */ 5 | 6 | #include "eos_button.hpp" 7 | 8 | namespace ebt { 9 | 10 | //Standard token members - Start 11 | 12 | /* 13 | void eos_button::create( account_name issuer, 14 | asset maximum_supply ) 15 | { 16 | require_auth( _self ); 17 | 18 | auto sym = maximum_supply.symbol; 19 | eosio_assert( sym.is_valid(), "invalid symbol name" ); 20 | eosio_assert( maximum_supply.is_valid(), "invalid supply"); 21 | eosio_assert( maximum_supply.amount > 0, "max-supply must be positive"); 22 | 23 | stats statstable( _self, sym.name() ); 24 | auto existing = statstable.find( sym.name() ); 25 | eosio_assert( existing == statstable.end(), "token with symbol already exists" ); 26 | 27 | statstable.emplace( _self, [&]( auto& s ) { 28 | s.supply.symbol = maximum_supply.symbol; 29 | s.max_supply = maximum_supply; 30 | s.issuer = issuer; 31 | }); 32 | } 33 | */ 34 | 35 | /* 36 | void eos_button::issue( account_name to, asset quantity, string memo ) 37 | { 38 | auto sym = quantity.symbol; 39 | eosio_assert( sym.is_valid(), "invalid symbol name" ); 40 | eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" ); 41 | 42 | auto sym_name = sym.name(); 43 | stats statstable( _self, sym_name ); 44 | auto existing = statstable.find( sym_name ); 45 | eosio_assert( existing != statstable.end(), "token with symbol does not exist, create token before issue" ); 46 | const auto& st = *existing; 47 | 48 | require_auth( st.issuer ); 49 | eosio_assert( quantity.is_valid(), "invalid quantity" ); 50 | eosio_assert( quantity.amount > 0, "must issue positive quantity" ); 51 | 52 | eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); 53 | eosio_assert( quantity.amount <= st.max_supply.amount - st.supply.amount, "quantity exceeds available supply"); 54 | 55 | statstable.modify( st, 0, [&]( auto& s ) { 56 | s.supply += quantity; 57 | }); 58 | 59 | add_balance( st.issuer, quantity, st.issuer ); 60 | 61 | if( to != st.issuer ) { 62 | SEND_INLINE_ACTION( *this, transfer, {st.issuer,N(active)}, {st.issuer, to, quantity, memo} ); 63 | } 64 | } 65 | */ 66 | 67 | /* 68 | void eos_button::transfer( account_name from, 69 | account_name to, 70 | asset quantity, 71 | string memo ) 72 | { 73 | eosio_assert( from != to, "cannot transfer to self" ); 74 | require_auth( from ); 75 | eosio_assert( is_account( to ), "to account does not exist"); 76 | auto sym = quantity.symbol.name(); 77 | stats statstable( _self, sym ); 78 | const auto& st = statstable.get( sym ); 79 | 80 | require_recipient( from ); 81 | require_recipient( to ); 82 | 83 | eosio_assert( quantity.is_valid(), "invalid quantity" ); 84 | eosio_assert( quantity.amount > 0, "must transfer positive quantity" ); 85 | eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); 86 | eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" ); 87 | 88 | 89 | sub_balance( from, quantity ); 90 | add_balance( to, quantity, from ); 91 | } 92 | 93 | void eos_button::sub_balance( account_name owner, asset value ) { 94 | accounts from_acnts( _self, owner ); 95 | 96 | const auto& from = from_acnts.get( value.symbol.name(), "no balance object found" ); 97 | eosio_assert( from.balance.amount >= value.amount, "overdrawn balance" ); 98 | 99 | 100 | if( from.balance.amount == value.amount ) { 101 | from_acnts.erase( from ); 102 | } else { 103 | from_acnts.modify( from, owner, [&]( auto& a ) { 104 | a.balance -= value; 105 | }); 106 | } 107 | } 108 | 109 | void eos_button::add_balance( account_name owner, asset value, account_name ram_payer ) 110 | { 111 | accounts to_acnts( _self, owner ); 112 | auto to = to_acnts.find( value.symbol.name() ); 113 | if( to == to_acnts.end() ) { 114 | to_acnts.emplace( ram_payer, [&]( auto& a ){ 115 | a.balance = value; 116 | }); 117 | } else { 118 | to_acnts.modify( to, 0, [&]( auto& a ) { 119 | a.balance += value; 120 | }); 121 | } 122 | } 123 | */ 124 | 125 | //Standard token members - End 126 | 127 | //Game members - Start 128 | 129 | void eos_button::ebtpress( account_name account, asset quantity, bool protection, account_name referrer) 130 | { 131 | eosio_assert( quantity.symbol == string_to_symbol(4, "EBT"), "unsupported symbol name" ); 132 | handle_press(account, quantity, protection, referrer); 133 | } 134 | 135 | /* 136 | void eos_button::eospress( account_name account, asset quantity, bool protection, account_name referrer) 137 | { 138 | eosio_assert( quantity.symbol == string_to_symbol(4, "EOS"), "unsupported symbol name" ); 139 | handle_press(account, quantity, protection, referrer); 140 | } 141 | */ 142 | 143 | template 144 | void eos_button::handle_press( account_name account, asset quantity, bool protection, account_name referrer) 145 | { 146 | //print("handle_press (", quantity, ") - Start |"); 147 | 148 | /* 149 | //Erase records when required (for testing on testnet) 150 | if (quantity.amount == 0) { 151 | ebtgames table( _self, _self ); 152 | auto itr = table.find(0); 153 | if ( itr != table.end() ) { 154 | table.erase(itr); 155 | } 156 | } 157 | if (quantity.amount == 0) { 158 | eosgames table( _self, _self ); 159 | auto itr = table.find(0); 160 | if ( itr != table.end() ) { 161 | table.erase(itr); 162 | } 163 | } 164 | if (quantity.amount == 0) { 165 | ebtplayers table( _self, _self ); 166 | for (auto itr = table.begin(); itr != table.end(); ) { 167 | itr = table.erase(itr); 168 | } 169 | } 170 | if (quantity.amount == 0) { 171 | eosplayers table( _self, _self ); 172 | for (auto itr = table.begin(); itr != table.end(); ) { 173 | itr = table.erase(itr); 174 | } 175 | } 176 | return; 177 | */ 178 | 179 | require_auth( account ); 180 | 181 | const time countdown_cap = 120; //2 minutes countdown cap 182 | const time countdown_increase_step = 120; //Increase 2 minutes per share when pressed 183 | const time round_interval = 600; //10 minutes between each round 184 | const uint64_t shares_for_first_press = 10000; //10000 means 1 share 185 | const uint64_t referrer_percent = 5; 186 | const uint64_t referee_percent = 5; 187 | const uint64_t dev_fee_percent = 2; 188 | const uint64_t token_reserve_percent = 1; 189 | const uint64_t last_player_reward_percent = 5; 190 | const uint64_t start_protection_seconds = 5; 191 | const uint64_t protection_seconds = 0; //Protection is disabled for now 192 | const uint64_t protection_fee_percent = 50; 193 | 194 | //Check game_command 195 | /* 196 | uint64_t game_command; 197 | systemstates systemstates_table( _self, _self ); 198 | auto systemstates_itr = systemstates_table.find(0); 199 | if ( systemstates_itr == systemstates_table.end() ) { 200 | game_command = 0; 201 | } else { 202 | if (quantity.symbol == string_to_symbol(4, "EBT")) { 203 | game_command = systemstates_itr->ebtgame_command; 204 | } else { 205 | game_command = systemstates_itr->eosgame_command; 206 | } 207 | } 208 | */ 209 | 210 | //Check if referrer is valid 211 | bool referrer_is_valid = false; 212 | if (is_account(referrer) && referrer != account) { 213 | if (quantity.symbol == string_to_symbol(4, "EBT")) { 214 | accounts accounts_table( _self, referrer ); 215 | auto accounts_itr = accounts_table.find(quantity.symbol.name()); 216 | if (accounts_itr != accounts_table.end()) { 217 | if (accounts_itr->balance.amount > 0) { 218 | referrer_is_valid = true; 219 | } 220 | } 221 | } else { 222 | accstates accstates_table( _self, _self ); 223 | auto accstates_itr = accstates_table.find(referrer); 224 | if (accstates_itr != accstates_table.end()) { 225 | if (accstates_itr->eos_balance.amount > 0) { 226 | referrer_is_valid = true; 227 | } 228 | } 229 | } 230 | } 231 | 232 | games_table_type games_table( _self, _self ); 233 | auto games_itr = games_table.find(0); 234 | if ( games_itr == games_table.end() ) { 235 | games_itr = games_table.emplace(account, [&](auto& g){ 236 | //It is important to initialize all asset type columns with the correct symbol, so that they can be used in future calculations 237 | g.pot = asset(0, quantity.symbol); 238 | g.final_prize = asset(0, quantity.symbol); 239 | g.token_reserved_for_next_round = asset(0, quantity.symbol); 240 | g.dev_fee = asset(0, quantity.symbol); 241 | }); 242 | } 243 | players_table_type players_table( _self, _self ); 244 | 245 | time remaining_time_right_after_last_full_press = std::min