Skip to content

Commit

Permalink
restrict client from trying to set starting entropy before valid bloc…
Browse files Browse the repository at this point in the history
…k hash is available
  • Loading branch information
loothero committed Mar 8, 2024
1 parent 832c89d commit fd846d2
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 5 deletions.
1 change: 1 addition & 0 deletions contracts/game/src/game/constants.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ mod messages {
const STARTING_ENTROPY_ZERO: felt252 = 'block hash should not be zero';
const GAME_ALREADY_STARTED: felt252 = 'game already started';
const STARTING_ENTROPY_IS_VALID: felt252 = 'starting entropy is valid';
const VALID_BLOCK_HASH_UNAVAILABLE: felt252 = 'valid hash not yet available';
}

// TODO: Update for mainnet
Expand Down
27 changes: 22 additions & 5 deletions contracts/game/src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ mod Game {
// player can only call this before starting game (defeating starter beast)
assert(_load_adventurer(@self, adventurer_id).xp == 0, messages::GAME_ALREADY_STARTED);

// prevent client from trying to set start entropy prior to valid block hash being available
_assert_valid_block_hash_available(@self, adventurer_id);

// verify the block_hash is not zero
assert(block_hash != 0, messages::STARTING_ENTROPY_ZERO);

Expand Down Expand Up @@ -728,7 +731,9 @@ mod Game {
) -> felt252 {
self._starting_entropy.read(adventurer_id)
}
fn get_contract_calculated_entropy(self: @ContractState, adventurer_id: felt252) -> felt252 {
fn get_contract_calculated_entropy(
self: @ContractState, adventurer_id: felt252
) -> felt252 {
_get_starting_block_hash(self, adventurer_id)
}
fn get_adventurer_entropy(self: @ContractState, adventurer_id: felt252) -> felt252 {
Expand Down Expand Up @@ -1322,15 +1327,27 @@ mod Game {
);
}

// @title Assert Valid Block Hash Availability
// @notice This function asserts that a valid block hash is available for the given adventurer.
// @dev If this function is called prior to 2 blocks from the start of the game for the given adventurer, an exception will be thrown.
// @param adventurer_id The ID of the adventurer for which to check the block hash availability.
fn _assert_valid_block_hash_available(self: @ContractState, adventurer_id: felt252) {
let current_block = starknet::get_block_info().unbox().block_number;
let adventurer_start_block = _load_adventurer_metadata(self, adventurer_id).start_block;
let block_hash_available = adventurer_start_block + 2;
assert(current_block >= block_hash_available, messages::VALID_BLOCK_HASH_UNAVAILABLE);
}

// @title Check if starting entropy is valid
// @notice This function checks if the starting entropy provided to the contract is equal to the entropy generated by the contract based on the block hash of the block after the player committed to playing the game.
// @dev If no manual starting entropy was provided, the starting entropy is considered valid. If a starting entropy was manually provided, it is compared with the block hash of the block after the player committed to playing the game.
// @param adventurer_id The ID of the adventurer for which to check the starting entropy.
// @return Returns true if the starting entropy is valid, false otherwise.
fn _is_starting_entropy_valid(self: @ContractState, adventurer_id: felt252) -> bool {
// get starting entropy manually provided to the contract
let starting_entropy = self._starting_entropy.read(adventurer_id);
if starting_entropy == 0 {
// if no manual starting entropy was provided, the starting entropy is valid
true
} else {
// if a starting entropy was manually provided
// compare it with the block hash of the block after the player committed to playing the game
starting_entropy == _get_starting_block_hash(self, adventurer_id)
}
}
Expand Down
16 changes: 16 additions & 0 deletions contracts/game/src/tests/test_game.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ mod tests {
let mut game = new_adventurer(starting_block, starting_time);

if (starting_entropy != 0) {
testing::set_block_number(starting_block + 2);
game.set_starting_entropy(ADVENTURER_ID, starting_entropy);
}

Expand Down Expand Up @@ -2324,6 +2325,7 @@ mod tests {
#[should_panic(expected: ('Not authorized to act', 'ENTRYPOINT_FAILED'))]
fn test_set_starting_entropy_not_owner() {
let mut game = new_adventurer(1000, 1696201757);
testing::set_block_number(1002);
// change to different caller
testing::set_contract_address(contract_address_const::<50>());
// try to set starting entropy, should revert
Expand All @@ -2334,16 +2336,27 @@ mod tests {
#[should_panic(expected: ('game already started', 'ENTRYPOINT_FAILED'))]
fn test_set_starting_entropy_game_started() {
let mut game = new_adventurer(1000, 1696201757);
testing::set_block_number(1002);
// defeat starter beast
game.attack(ADVENTURER_ID, true);
// then attempt to set starting entropy, should revert
game.set_starting_entropy(ADVENTURER_ID, 1);
}


#[test]
#[should_panic(expected: ('valid hash not yet available', 'ENTRYPOINT_FAILED'))]
fn test_set_starting_entropy_before_hash_available() {
let mut game = new_adventurer(1000, 1696201757);
// attempt to set starting entropy before hash is available, should revert
game.set_starting_entropy(ADVENTURER_ID, 1);
}

#[test]
#[should_panic(expected: ('block hash should not be zero', 'ENTRYPOINT_FAILED'))]
fn test_set_starting_entropy_zero_hash() {
let mut game = new_adventurer(1000, 1696201757);
testing::set_block_number(1002);
// attempt to pass in 0 for starting entropy hash, should revert
game.set_starting_entropy(ADVENTURER_ID, 0);
}
Expand All @@ -2352,6 +2365,7 @@ mod tests {
#[should_panic(expected: ('starting entropy already set', 'ENTRYPOINT_FAILED'))]
fn test_set_starting_entropy_double_call() {
let mut game = new_adventurer(1000, 1696201757);
testing::set_block_number(1002);
// attempt to set starting entropy twice, should revert
game.set_starting_entropy(ADVENTURER_ID, 1);
game.set_starting_entropy(ADVENTURER_ID, 1);
Expand All @@ -2360,6 +2374,7 @@ mod tests {
#[test]
fn test_set_starting_entropy_basic() {
let mut game = new_adventurer(1000, 1696201757);
testing::set_block_number(1002);
game.set_starting_entropy(ADVENTURER_ID, 123);
// verify starting entropy was set
assert(
Expand All @@ -2373,6 +2388,7 @@ mod tests {
fn test_set_starting_entropy_wrong_hash() {
let wrong_starting_entropy = 12345678910112;
let mut game = new_adventurer_lvl3(1000, 1696201757, wrong_starting_entropy);
testing::set_block_number(1002);

// go out exploring till beast
game.explore(ADVENTURER_ID, true);
Expand Down

0 comments on commit fd846d2

Please sign in to comment.