Skip to content

Commit

Permalink
A0-1159: The Pressiah Cometh (#586)
Browse files Browse the repository at this point in the history
  • Loading branch information
h4nsu committed Aug 16, 2022
1 parent 5215e27 commit a52e372
Show file tree
Hide file tree
Showing 16 changed files with 1,471 additions and 114 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/e2e-tests-contracts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
with:
target-key: e2e-contracts
cargo-key: e2e-contracts
cache-version: v2
cache-version: v3
cargo-targets: e2e-tests-contracts/target/

- name: Install cargo-contract
Expand Down
6 changes: 3 additions & 3 deletions contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ score = deadline - now

There are two built-in incentives:
* playing for the score: If you clicked in the 10th second of TheButton's life, which is set for example to 900 blocks, you get rewarded based on the score of 900-10=890 (and the button's life now will end at block 910).
* playing to be ThePressiah: the last player to click gets 50% of the total reward pool.
* playing to be ThePressiah: the last player to click gets 20% of the total reward pool (1/4 of the sum of all the rewards paid for pressing the button)

## BackToTheFuture

Expand All @@ -35,7 +35,7 @@ In this scenario the rewards are reversed - players get rewarded for extending t
score = now - start
```

The Pressiah gets 50% of the total reward pool.
The Pressiah gets 20% of the total reward pool.

## ThePressiahCometh

Expand All @@ -47,7 +47,7 @@ Game continues in perpetuity (but in practice as long as there are accounts that
- Players are rewarded for playing, with the ultimate goal of being the Pressiah (the last person to click the button)
- Reward rules:
- If you’re not ThePressiah, you get _k_ tokens if you pressed the button as the _k-th_ person in a row.
- ThePressiah of the iteration with _k_ button presses gets [k*(k+1)]/2 tokens.
- ThePressiah gets 20% of the total reward pool.

# Development

Expand Down
12 changes: 6 additions & 6 deletions contracts/access_control/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ publish = false
license = "Apache 2.0"

[dependencies]
ink_env = { version = "3.2.0", default-features = false }
ink_lang = { version = "3.2.0", default-features = false }
ink_lang_codegen = { version = "3.2.0", default-features = false }
ink_metadata = { version = "3.2.0", default-features = false, features = ["derive"], optional = true }
ink_primitives = { version = "3.2.0", default-features = false }
ink_storage = { version = "3.2.0", default-features = false }
ink_env = { version = "~3.3.0", default-features = false }
ink_lang = { version = "~3.3.0", default-features = false }
ink_lang_codegen = { version = "~3.3.0", default-features = false }
ink_metadata = { version = "~3.3.0", default-features = false, features = ["derive"], optional = true }
ink_primitives = { version = "~3.3.0", default-features = false }
ink_storage = { version = "~3.3.0", default-features = false }

scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
scale-info = { version = "2", default-features = false, features = ["derive"], optional = true }
Expand Down
13 changes: 0 additions & 13 deletions contracts/back_to_the_future/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions contracts/back_to_the_future/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ edition = "2021"
license = "Apache 2.0"

[dependencies]
ink_env = { version = "3.2.0", default-features = false }
ink_lang = { version = "3.2.0", default-features = false }
ink_lang_codegen = { version = "3.2.0", default-features = false }
ink_metadata = { version = "3.2.0", default-features = false, features = ["derive"], optional = true }
ink_prelude = { version = "3.2.0", default-features = false }
ink_primitives = { version = "3.2.0", default-features = false }
ink_storage = { version = "3.2.0", default-features = false }
ink_env = { version = "~3.3.0", default-features = false }
ink_lang = { version = "~3.3.0", default-features = false }
ink_lang_codegen = { version = "~3.3.0", default-features = false }
ink_metadata = { version = "~3.3.0", default-features = false, features = ["derive"], optional = true }
ink_prelude = { version = "~3.3.0", default-features = false }
ink_primitives = { version = "~3.3.0", default-features = false }
ink_storage = { version = "~3.3.0", default-features = false }

scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
scale-info = { version = "2", default-features = false, features = ["derive"], optional = true }
Expand Down
23 changes: 11 additions & 12 deletions contracts/back_to_the_future/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@ use ink_lang as ink;
/// This is the BackToTheFuture
///
/// Larger rewards are distributed for postponing playing for as long as possible, but without letting TheButton die:
/// user_score = now - start
/// ThePressiah (the last player to click) still gets 50% of the tokens.
/// user_score = now - previous_press
/// ThePressiah (the last player to click) gets 20% of the tokens.

#[ink::contract(env = button::ButtonGameEnvironment)]
#[ink::contract]
mod back_to_the_future {

use access_control::{traits::AccessControlled, Role, ACCESS_CONTROL_PUBKEY};
use button::{
ButtonData, ButtonGame, ButtonGameEnvironment, ButtonResult, GameError, IButtonGame,
};
use ink_env::Error as InkEnvError;
use button::{ButtonData, ButtonGame, ButtonResult, GameError, IButtonGame};
use ink_env::{DefaultEnvironment, Error as InkEnvError};
use ink_lang::{
codegen::{initialize_contract, EmitEvent},
reflect::ContractEventBase,
Expand All @@ -31,6 +29,7 @@ mod back_to_the_future {
pub struct ButtonCreated {
#[ink(topic)]
reward_token: AccountId,
#[ink(topic)]
ticket_token: AccountId,
start: BlockNumber,
deadline: BlockNumber,
Expand Down Expand Up @@ -76,11 +75,11 @@ mod back_to_the_future {
}
}

// becasue ink! does not allow generics or trait default implementations
// because ink! does not allow generics or trait default implementations
impl IButtonGame for BackToTheFuture {
#[ink(message)]
fn is_dead(&self) -> bool {
let now = Self::env().block_number();
let now = self.env().block_number();
ButtonGame::is_dead(self, now)
}

Expand All @@ -90,7 +89,7 @@ mod back_to_the_future {
let now = Self::env().block_number();
let this = self.env().account_id();

ButtonGame::press::<ButtonGameEnvironment>(self, now, caller, this)?;
ButtonGame::press::<DefaultEnvironment>(self, now, caller, this)?;

Self::emit_event(
self.env(),
Expand All @@ -107,7 +106,7 @@ mod back_to_the_future {
fn reset(&mut self) -> ButtonResult<()> {
let now = Self::env().block_number();

ButtonGame::reset::<ButtonGameEnvironment>(self, now)?;
ButtonGame::reset::<DefaultEnvironment>(self, now)?;

Self::emit_event(self.env(), Event::GameReset(GameReset { when: now }));
Ok(())
Expand Down Expand Up @@ -141,7 +140,7 @@ mod back_to_the_future {
#[ink(message)]
fn balance(&self) -> ButtonResult<Balance> {
let this = self.env().account_id();
ButtonGame::balance::<ButtonGameEnvironment>(self, this)
ButtonGame::balance::<DefaultEnvironment>(self, this)
}

#[ink(message)]
Expand Down
15 changes: 7 additions & 8 deletions contracts/button/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ authors = ["Cardinal Cryptography"]
edition = "2021"

[dependencies]
ink_env = { version = "3.0", default-features = false }
ink_lang = { version = "3.0", default-features = false }
ink_metadata = { version = "3.0", default-features = false, features = ["derive"], optional = true }
ink_prelude = { version = "3.2.0", default-features = false }
ink_primitives = { version = "3.0", default-features = false }
ink_storage = { version = "3.0", default-features = false }
ink_env = { version = "~3.3.0", default-features = false }
ink_lang = { version = "~3.3.0", default-features = false }
ink_metadata = { version = "~3.3.0", default-features = false, features = ["derive"], optional = true }
ink_prelude = { version = "~3.3.0", default-features = false }
ink_primitives = { version = "~3.3.0", default-features = false }
ink_storage = { version = "~3.3.0", default-features = false }

scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
scale-info = { version = "2", default-features = false, features = ["derive"], optional = true }
Expand Down Expand Up @@ -38,7 +38,6 @@ std = [
"ink_primitives/std",
"ink_storage/std",
"scale-info/std",
"scale/std",
"num/std"
"scale/std"
]
ink-as-dependency = []
44 changes: 12 additions & 32 deletions contracts/button/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#![cfg_attr(not(feature = "std"), no_std)]

use core::mem::swap;

use access_control::{traits::AccessControlled, Role};
use game_token::MINT_TO_SELECTOR;
use ink_env::{
Expand All @@ -14,23 +12,10 @@ use ink_storage::traits::{SpreadAllocate, SpreadLayout};
use openbrush::contracts::psp22::PSP22Error;
use ticket_token::{BALANCE_OF_SELECTOR, TRANSFER_FROM_SELECTOR};

pub type BlockNumber = <ButtonGameEnvironment as ink_env::Environment>::BlockNumber;
pub type Balance = <ButtonGameEnvironment as ink_env::Environment>::Balance;
pub type BlockNumber = <DefaultEnvironment as ink_env::Environment>::BlockNumber;
pub type Balance = <DefaultEnvironment as ink_env::Environment>::Balance;
pub type ButtonResult<T> = core::result::Result<T, GameError>;

pub enum ButtonGameEnvironment {}

impl Environment for ButtonGameEnvironment {
const MAX_EVENT_TOPICS: usize = <DefaultEnvironment as Environment>::MAX_EVENT_TOPICS;

type AccountId = <DefaultEnvironment as Environment>::AccountId;
type Balance = <DefaultEnvironment as Environment>::Balance;
type Hash = <DefaultEnvironment as Environment>::Hash;
type BlockNumber = u64;
type Timestamp = <DefaultEnvironment as Environment>::Timestamp;
type ChainExtension = <DefaultEnvironment as Environment>::ChainExtension;
}

/// GameError types
#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
Expand Down Expand Up @@ -128,6 +113,8 @@ pub struct ButtonData {
pub last_presser: Option<AccountId>,
/// block number of the last press, set to current block number at button start/reset
pub last_press: BlockNumber,
/// sum of rewards paid to players in the current iteration
pub total_rewards: u128,
/// counter for the number of presses
pub presses: u128,
/// AccountId of the PSP22 ButtonToken instance on-chain
Expand Down Expand Up @@ -157,12 +144,10 @@ pub trait ButtonGame {

/// Logic for calculating pressiah score
///
/// By defaul the pressiah score is defined as k * sqrt(k)
/// where k is the number of players that participated until the button has died
/// By default the pressiah gets 20% of the total rewards paid in the current game iteration
/// Can be overriden to some other custom calculation
fn pressiah_score(&self) -> Balance {
let presses = self.get().presses;
(presses * num::integer::sqrt(presses)) as Balance
(self.get().total_rewards / 4) as Balance
}

fn is_dead(&self, now: BlockNumber) -> bool {
Expand Down Expand Up @@ -286,27 +271,23 @@ pub trait ButtonGame {
return Err(GameError::AfterDeadline);
}

let ButtonData { presses, .. } = self.get();

// transfers 1 ticket token from the caller to self
// tx will fail if user did not give allowance to the game contract
// or does not have enough balance
self.transfer_from_tx::<E>(caller, this, 1u128)??;

let root_key = ::ink_primitives::Key::from([0x00; 32]);
let mut state = ::ink_storage::traits::pull_spread_root::<ButtonData>(&root_key);

let score = self.score(now);

// mints reward tokens to pay out the reward
// contract needs to have a Minter role on the reward token contract
self.mint_tx::<E>(caller, score)??;

state.presses = presses + 1;
let mut state = self.get_mut();

state.presses += 1;
state.last_presser = Some(caller);
state.last_press = now;

swap(self.get_mut(), &mut state);
state.total_rewards += score;

Ok(())
}
Expand All @@ -333,13 +314,12 @@ pub trait ButtonGame {
};

// zero the counters in storage
let root_key = ::ink_primitives::Key::from([0x00; 32]);
let mut state = ::ink_storage::traits::pull_spread_root::<ButtonData>(&root_key);
let mut state = self.get_mut();

state.presses = 0;
state.last_presser = None;
state.last_press = now;
swap(self.get_mut(), &mut state);
state.total_rewards = 0;

Ok(())
}
Expand Down
13 changes: 0 additions & 13 deletions contracts/early_bird_special/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions contracts/early_bird_special/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ edition = "2021"
license = "Apache 2.0"

[dependencies]
ink_env = { version = "3.2.0", default-features = false }
ink_lang = { version = "3.2.0", default-features = false }
ink_lang_codegen = { version = "3.2.0", default-features = false }
ink_metadata = { version = "3.2.0", default-features = false, features = ["derive"], optional = true }
ink_prelude = { version = "3.2.0", default-features = false }
ink_primitives = { version = "3.2.0", default-features = false }
ink_storage = { version = "3.2.0", default-features = false }
ink_env = { version = "~3.3.0", default-features = false }
ink_lang = { version = "~3.3.0", default-features = false }
ink_lang_codegen = { version = "~3.3.0", default-features = false }
ink_metadata = { version = "~3.3.0", default-features = false, features = ["derive"], optional = true }
ink_prelude = { version = "~3.3.0", default-features = false }
ink_primitives = { version = "~3.3.0", default-features = false }
ink_storage = { version = "~3.3.0", default-features = false }

scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
scale-info = { version = "2", default-features = false, features = ["derive"], optional = true }
Expand Down
Loading

0 comments on commit a52e372

Please sign in to comment.