├── README.md ├── blockbunies.hpp └── blockbunies.cpp /README.md: -------------------------------------------------------------------------------- 1 | # WAX P2E Game NFT Staking 2 | 3 | staking, unstaking, claim, with NFT, NFT pack 4 | -------------------------------------------------------------------------------- /blockbunies.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace eosio; 10 | using namespace std; 11 | 12 | CONTRACT blockbunies : public contract 13 | { 14 | public: 15 | using contract::contract; 16 | 17 | blockbunies(eosio::name self):eosio::contract(self) 18 | { 19 | crewPower.clear(); 20 | toolPercent.clear(); 21 | 22 | crewPower[204519] = 0.2; crewPower[204521] = 0.2; crewPower[204523] = 0.66; crewPower[204523] = 0.66; 23 | crewPower[204528] = 2.18; crewPower[204529] = 7.19; crewPower[204531] = 23.72; crewPower[204532] = 78.27; 24 | crewPower[204535] = 258.29; 25 | 26 | toolPercent[232860] = 1; toolPercent[232861] = 1; toolPercent[232862] = 1; toolPercent[232864] = 2; 27 | toolPercent[232887] = 4; toolPercent[232892] = 2; toolPercent[232893] = 4; toolPercent[232894] = 2; 28 | toolPercent[233274] = 4; 29 | } 30 | 31 | 32 | const uint32_t periodReward = 4*60*60; 33 | const name collection_name = name("blockbunnie1"); 34 | const name schema_name = name("blockbunnie1"); 35 | 36 | struct imeta 37 | { 38 | name username; 39 | string collection_name; 40 | uint64_t template_id; 41 | uint64_t assets_id; 42 | }; 43 | 44 | struct rewardmachine 45 | { 46 | string machine; 47 | vector crew_nfts; 48 | vector tool_nfts; 49 | float rewardAmount; 50 | float totalReward; 51 | uint64_t last_updated; 52 | uint64_t next_run; 53 | }; 54 | 55 | ACTION banstaker(const name username); 56 | ACTION stake(const name username, vector crew_nfts, vector tool_nfts, string memo); 57 | ACTION unstake(const name username, string memo); 58 | ACTION claim(const name username, string memo); 59 | ACTION burn(const name username, uint64_t assets_id, string memo); 60 | 61 | [[eosio::on_notify("atomicassets::transfer")]] void regstaker( 62 | name from, 63 | name to, 64 | vector asset_ids, 65 | string memo); 66 | 67 | private: 68 | 69 | map crewPower; 70 | map toolPercent; 71 | 72 | TABLE staker_t 73 | { 74 | name username; 75 | vector stakedNFTs; 76 | auto primary_key() const { return username.value; } 77 | }; 78 | 79 | TABLE ban_t 80 | { 81 | name username; 82 | string desc; 83 | auto primary_key() const { return username.value; } 84 | }; 85 | 86 | TABLE admin_t { 87 | name username; 88 | string desc; 89 | auto primary_key() const { return username.value; } 90 | }; 91 | 92 | typedef eosio::multi_index staker_s; 93 | typedef eosio::multi_index ban_s; 94 | typedef eosio::multi_index admin_s; 95 | 96 | staker_s stakes = staker_s(get_self(), get_self().value); 97 | ban_s bans = ban_s(get_self(), get_self().value); 98 | admin_s admins = admin_s(get_self(), get_self().value); 99 | 100 | void in_contract_transfer(name recipient, vector assets_id, string msg); 101 | 102 | }; -------------------------------------------------------------------------------- /blockbunies.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace eosio; 4 | static inline time_point_sec current_time_point_sec() { return time_point_sec(current_time_point()); }; 5 | 6 | 7 | void blockbunies::regstaker( 8 | name from, 9 | name to, 10 | vector asset_ids, 11 | string memo) 12 | { 13 | if (from == get_self() || to != get_self()) 14 | return; 15 | 16 | auto it_ban = bans.find(from.value); 17 | check(it_ban == bans.end(), "You were banned, please see your administrator"); 18 | } 19 | 20 | ACTION blockbunies::stake(const name username, vector crew_nfts, vector tool_nfts, string memo) 21 | { 22 | check(has_auth(username), "No authority"); 23 | auto itr = stakes.find(username.value); 24 | 25 | float amount = 0; 26 | int percent = 0; 27 | 28 | for (uint8_t i = 0; i < crew_nfts.size(); ++i) 29 | { 30 | amount += crewPower[crew_nfts[i].template_id]; 31 | percent += toolPercent[tool_nfts[i].template_id]; 32 | } 33 | 34 | amount += amount * percent * 1.0 / 100.0; 35 | 36 | rewardmachine rm; 37 | rm.crew_nfts = crew_nfts; 38 | rm.tool_nfts = tool_nfts; 39 | rm.last_updated = current_time_point_sec().utc_seconds; 40 | rm.next_run = current_time_point_sec().utc_seconds + periodReward; 41 | rm.machine = memo; 42 | rm.rewardAmount = amount; 43 | rm.totalReward = 0; 44 | 45 | if(itr == stakes.end()) { // add staker 46 | stakes.emplace(get_self(), [&](auto &v) { 47 | v.username = username; 48 | v.stakedNFTs.push_back(rm); 49 | 50 | }); 51 | } 52 | else { // update staker 53 | stakes.modify(itr, get_self(), [&](auto &v) { 54 | v.username = username; 55 | v.stakedNFTs.push_back(rm); 56 | }); 57 | } 58 | 59 | } 60 | 61 | 62 | ACTION blockbunies::unstake(const name username, string memo) 63 | { 64 | check(has_auth(username), "No authority"); 65 | auto itr = stakes.require_find(username.value, "Your are not a staker, please register first"); 66 | vector total_nfts; 67 | 68 | for (uint8_t i = 0; i < itr->stakedNFTs.size(); i++) 69 | { 70 | for (uint8_t j = 0; j < itr->stakedNFTs[i].crew_nfts.size(); j++) 71 | { 72 | total_nfts.push_back(itr->stakedNFTs[i].crew_nfts[j].assets_id); 73 | } 74 | 75 | for (uint8_t j = 0; j < itr->stakedNFTs[i].tool_nfts.size(); j++) 76 | { 77 | total_nfts.push_back(itr->stakedNFTs[i].tool_nfts[j].assets_id); 78 | } 79 | } 80 | in_contract_transfer(username, total_nfts, string("Your NFT_staked have been unstaked")); 81 | stakes.erase(itr); 82 | } 83 | 84 | 85 | 86 | ACTION blockbunies::claim(const name username, string memo) 87 | { 88 | check(has_auth(username), "No authority"); 89 | auto itr = stakes.require_find(username.value, "Your are not a staker, please register first"); 90 | 91 | check(itr != stakes.end(), "You don't have staked NFTs"); 92 | 93 | for(auto& item : stakes) { 94 | for (int i = 0; i < item.stakedNFTs.size(); i ++) { 95 | if(item.stakedNFTs[i].next_run < current_time_point_sec().utc_seconds) { 96 | stakes.modify(item, _self, [&](auto &a) { 97 | a.stakedNFTs[i].totalReward += a.stakedNFTs[i].rewardAmount; 98 | a.stakedNFTs[i].last_updated += current_time_point_sec().utc_seconds; 99 | a.stakedNFTs[i].next_run += a.stakedNFTs[i].last_updated + periodReward; 100 | }); 101 | } 102 | } 103 | } 104 | } 105 | 106 | ACTION blockbunies::banstaker(const name username) 107 | { 108 | 109 | } 110 | 111 | ACTION burn(const name username, uint64_t assets_id, string memo) 112 | { 113 | 114 | } 115 | 116 | void blockbunies::in_contract_transfer(name recipient, vector assets_id, string msg) 117 | { 118 | auto memo = " withdrawn by " + recipient.to_string(); 119 | action(permission_level{get_self(), name("active")}, 120 | "atomicassets"_n, name("transfer"), 121 | std::make_tuple(get_self(), recipient, assets_id, memo)) 122 | .send(); 123 | } --------------------------------------------------------------------------------