diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7a287b1f4..67070cfed 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -66,20 +66,6 @@ jobs: run: | cd contracts/market && scarb build && scarb cairo-test - build-pack: - name: Build Pack - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Setup Scarb - run: | - curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | bash -s -- -v ${{ env.SCARB_VERSION }} - - - name: Scarb build - run: | - cd contracts/pack && scarb build && scarb cairo-test - build-obstacles: name: Build Obstacles runs-on: ubuntu-latest diff --git a/contracts/adventurer/Scarb.toml b/contracts/adventurer/Scarb.toml index c3067f82f..b245dd882 100644 --- a/contracts/adventurer/Scarb.toml +++ b/contracts/adventurer/Scarb.toml @@ -5,7 +5,6 @@ version = "0.1.0" # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest [dependencies] -pack = { path = "../pack" } lootitems = { path = "../loot" } obstacles = { path = "../obstacles" } combat = { path = "../combat" } diff --git a/contracts/adventurer/src/adventurer.cairo b/contracts/adventurer/src/adventurer.cairo index 9b4e269ee..0e4414141 100644 --- a/contracts/adventurer/src/adventurer.cairo +++ b/contracts/adventurer/src/adventurer.cairo @@ -1,4 +1,7 @@ +use starknet::{StorePacking}; use core::result::ResultTrait; +use core::integer::u256_try_as_non_zero; +use zeroable::NonZeroIntoImpl; use integer::{u8_overflowing_add, u16_overflowing_add, u16_overflowing_sub}; use traits::{TryInto, Into}; use option::OptionTrait; @@ -6,9 +9,9 @@ use poseidon::poseidon_hash_span; use array::ArrayTrait; use super::{ - item_meta::{ItemSpecials, ItemSpecialsStorage, ImplItemSpecials}, adventurer_stats::Stats, - item_primitive::ItemPrimitive, adventurer_utils::{AdventurerUtils}, exploration::ExploreUtils, - bag::{Bag, IBag, ImplBag}, + item_meta::{ItemSpecials, ItemSpecialsStorage, ImplItemSpecials}, + adventurer_stats::{Stats, StatsPacking}, item_primitive::{ItemPrimitive, ItemPrimitivePacking}, + adventurer_utils::{AdventurerUtils}, exploration::ExploreUtils, bag::{Bag, IBag, ImplBag}, constants::{ adventurer_constants::{ STARTING_GOLD, StatisticIndex, POTION_PRICE, STARTING_HEALTH, CHARISMA_POTION_DISCOUNT, @@ -20,15 +23,12 @@ use super::{ JEWELRY_BONUS_BEAST_GOLD_PERCENT, JEWELRY_BONUS_CRITICAL_HIT_PERCENT_PER_GREATNESS, JEWELRY_BONUS_NAME_MATCH_PERCENT_PER_GREATNESS, NECKLACE_ARMOR_BONUS, MINIMUM_DAMAGE_FROM_BEASTS, OBSTACLE_CRITICAL_HIT_CHANCE, BEAST_CRITICAL_HIT_CHANCE, - SILVER_RING_LUCK_BONUS_PER_GREATNESS, MINIMUM_DAMAGE_FROM_OBSTACLES, MINIMUM_DAMAGE_TO_BEASTS + SILVER_RING_LUCK_BONUS_PER_GREATNESS, MINIMUM_DAMAGE_FROM_OBSTACLES, + MINIMUM_DAMAGE_TO_BEASTS }, discovery_constants::DiscoveryEnums::{ExploreResult, DiscoveryType} } }; -use pack::{ - pack::{Packing, rshift_split}, constants, - constants::{MASK_16, pow, MASK_8, MASK_3, MASK_BOOL, mask, U128_MASK_8, u128_pow} -}; use lootitems::{ loot::{Loot, ILoot, ImplLoot}, constants::{ItemSuffix, ItemId, NamePrefixLength, NameSuffixLength} @@ -60,71 +60,89 @@ struct Adventurer { mutated: bool, // not packed } -impl AdventurerPacking of Packing { - fn pack(self: Adventurer) -> felt252 { - (self.last_action.into() - + self.health.into() * pow::TWO_POW_9 - + self.xp.into() * pow::TWO_POW_18 - + self.stats.pack().into() * pow::TWO_POW_31 - + self.gold.into() * pow::TWO_POW_61 - + self.weapon.pack().into() * pow::TWO_POW_70 - + self.chest.pack().into() * pow::TWO_POW_91 - + self.head.pack().into() * pow::TWO_POW_112 - + self.waist.pack().into() * pow::TWO_POW_133 - + self.foot.pack().into() * pow::TWO_POW_154 - + self.hand.pack().into() * pow::TWO_POW_175 - + self.neck.pack().into() * pow::TWO_POW_196 - + self.ring.pack().into() * pow::TWO_POW_217 - + self.beast_health.into() * pow::TWO_POW_238 - + self.stat_points_available.into() * pow::TWO_POW_247) +const TWO_POW_3: u256 = 0x8; +const TWO_POW_9: u256 = 0x200; +const TWO_POW_13: u256 = 0x2000; +const TWO_POW_18: u256 = 0x40000; +const TWO_POW_21: u256 = 0x200000; +const TWO_POW_30: u256 = 0x40000000; +const TWO_POW_31: u256 = 0x80000000; +const TWO_POW_61: u256 = 0x2000000000000000; +const TWO_POW_70: u256 = 0x400000000000000000; +const TWO_POW_91: u256 = 0x80000000000000000000000; +const TWO_POW_112: u256 = 0x10000000000000000000000000000; +const TWO_POW_133: u256 = 0x2000000000000000000000000000000000; +const TWO_POW_154: u256 = 0x400000000000000000000000000000000000000; +const TWO_POW_175: u256 = 0x80000000000000000000000000000000000000000000; +const TWO_POW_196: u256 = 0x10000000000000000000000000000000000000000000000000; +const TWO_POW_217: u256 = 0x2000000000000000000000000000000000000000000000000000000; +const TWO_POW_238: u256 = 0x400000000000000000000000000000000000000000000000000000000000; +const TWO_POW_247: u256 = 0x80000000000000000000000000000000000000000000000000000000000000; + +impl AdventurerPacking of StorePacking { + fn pack(value: Adventurer) -> felt252 { + (value.last_action.into() + + value.health.into() * TWO_POW_9 + + value.xp.into() * TWO_POW_18 + + StatsPacking::pack(value.stats).into() * TWO_POW_31 + + value.gold.into() * TWO_POW_61 + + ItemPrimitivePacking::pack(value.weapon).into() * TWO_POW_70 + + ItemPrimitivePacking::pack(value.chest).into() * TWO_POW_91 + + ItemPrimitivePacking::pack(value.head).into() * TWO_POW_112 + + ItemPrimitivePacking::pack(value.waist).into() * TWO_POW_133 + + ItemPrimitivePacking::pack(value.foot).into() * TWO_POW_154 + + ItemPrimitivePacking::pack(value.hand).into() * TWO_POW_175 + + ItemPrimitivePacking::pack(value.neck).into() * TWO_POW_196 + + ItemPrimitivePacking::pack(value.ring).into() * TWO_POW_217 + + value.beast_health.into() * TWO_POW_238 + + value.stat_points_available.into() * TWO_POW_247) .try_into() - .expect('pack Adventurer') - } - - fn unpack(packed: felt252) -> Adventurer { - let packed = packed.into(); - let (packed, last_action) = rshift_split(packed, pow::TWO_POW_9); - let (packed, health) = rshift_split(packed, pow::TWO_POW_9); - let (packed, xp) = rshift_split(packed, pow::TWO_POW_13); - let (packed, stats) = rshift_split(packed, pow::TWO_POW_30); - let (packed, gold) = rshift_split(packed, pow::TWO_POW_9); - let (packed, weapon) = rshift_split(packed, pow::TWO_POW_21); - let (packed, chest) = rshift_split(packed, pow::TWO_POW_21); - let (packed, head) = rshift_split(packed, pow::TWO_POW_21); - let (packed, waist) = rshift_split(packed, pow::TWO_POW_21); - let (packed, foot) = rshift_split(packed, pow::TWO_POW_21); - let (packed, hand) = rshift_split(packed, pow::TWO_POW_21); - let (packed, neck) = rshift_split(packed, pow::TWO_POW_21); - let (packed, ring) = rshift_split(packed, pow::TWO_POW_21); - let (packed, beast_health) = rshift_split(packed, pow::TWO_POW_9); - let (_, stat_points_available) = rshift_split(packed, pow::TWO_POW_3); + .unwrap() + } + + fn unpack(value: felt252) -> Adventurer { + let packed = value.into(); + let (packed, last_action) = integer::U256DivRem::div_rem( + packed, TWO_POW_9.try_into().unwrap() + ); + let (packed, health) = integer::U256DivRem::div_rem(packed, TWO_POW_9.try_into().unwrap()); + let (packed, xp) = integer::U256DivRem::div_rem(packed, TWO_POW_13.try_into().unwrap()); + let (packed, stats) = integer::U256DivRem::div_rem(packed, TWO_POW_30.try_into().unwrap()); + let (packed, gold) = integer::U256DivRem::div_rem(packed, TWO_POW_9.try_into().unwrap()); + let (packed, weapon) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, chest) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, head) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, waist) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, foot) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, hand) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, neck) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, ring) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, beast_health) = integer::U256DivRem::div_rem( + packed, TWO_POW_9.try_into().unwrap() + ); + let (_, stat_points_available) = integer::U256DivRem::div_rem( + packed, TWO_POW_3.try_into().unwrap() + ); Adventurer { - last_action: last_action.try_into().expect('unpack Adventurer last_action'), - health: health.try_into().expect('unpack Adventurer health'), - xp: xp.try_into().expect('unpack Adventurer xp'), - stats: Packing::unpack(stats.try_into().expect('unpack Adventurer stats')), - gold: gold.try_into().expect('unpack Adventurer gold'), - weapon: Packing::unpack(weapon.try_into().expect('unpack Adventurer weapon')), - chest: Packing::unpack(chest.try_into().expect('unpack Adventurer chest')), - head: Packing::unpack(head.try_into().expect('unpack Adventurer head')), - waist: Packing::unpack(waist.try_into().expect('unpack Adventurer waist')), - foot: Packing::unpack(foot.try_into().expect('unpack Adventurer foot')), - hand: Packing::unpack(hand.try_into().expect('unpack Adventurer hand')), - neck: Packing::unpack(neck.try_into().expect('unpack Adventurer neck')), - ring: Packing::unpack(ring.try_into().expect('unpack Adventurer ring')), - beast_health: beast_health.try_into().expect('unpack Adventurer beast_health'), - stat_points_available: stat_points_available - .try_into() - .expect('unpack Adventurer stat_upgrade'), + last_action: last_action.try_into().unwrap(), + health: health.try_into().unwrap(), + xp: xp.try_into().unwrap(), + stats: StatsPacking::unpack(stats.try_into().unwrap()), + gold: gold.try_into().unwrap(), + weapon: ItemPrimitivePacking::unpack(weapon.try_into().unwrap()), + chest: ItemPrimitivePacking::unpack(chest.try_into().unwrap()), + head: ItemPrimitivePacking::unpack(head.try_into().unwrap()), + waist: ItemPrimitivePacking::unpack(waist.try_into().unwrap()), + foot: ItemPrimitivePacking::unpack(foot.try_into().unwrap()), + hand: ItemPrimitivePacking::unpack(hand.try_into().unwrap()), + neck: ItemPrimitivePacking::unpack(neck.try_into().unwrap()), + ring: ItemPrimitivePacking::unpack(ring.try_into().unwrap()), + beast_health: beast_health.try_into().unwrap(), + stat_points_available: stat_points_available.try_into().unwrap(), mutated: false, } } - - // TODO: add overflow pack protection - fn overflow_pack_protection(self: Adventurer) -> Adventurer { - self - } } #[generate_trait] @@ -967,7 +985,7 @@ impl ImplAdventurer of IAdventurer { hash_span.append(self.xp.into()); hash_span.append(adventurer_entropy.into()); let poseidon = poseidon_hash_span(hash_span.span()); - let (d, r) = rshift_split(poseidon.into(), 340282366920938463463374607431768211455); + let (d, r) = integer::U256DivRem::div_rem(poseidon.into(), u256_try_as_non_zero(U128_MAX.into()).unwrap()); r.try_into().unwrap() } else { 0 @@ -1414,7 +1432,7 @@ impl ImplAdventurer of IAdventurer { hash_span.append(game_entropy.into()); let poseidon = poseidon_hash_span(hash_span.span()); - let (d, r) = rshift_split(poseidon.into(), U128_MAX.into()); + let (d, r) = integer::U256DivRem::div_rem(poseidon.into(), u256_try_as_non_zero(U128_MAX.into()).unwrap()); return (r.try_into().unwrap(), d.try_into().unwrap()); } @@ -1594,7 +1612,8 @@ impl ImplAdventurer of IAdventurer { .jewelry_armor_bonus(armor_details.item_type, combat_result.base_armor); // adjust damage for jewelry armor bonus - if combat_result.total_damage > (jewelry_armor_bonus + MINIMUM_DAMAGE_FROM_OBSTACLES.into()) { + if combat_result + .total_damage > (jewelry_armor_bonus + MINIMUM_DAMAGE_FROM_OBSTACLES.into()) { combat_result.total_damage -= jewelry_armor_bonus; } else { combat_result.total_damage = MINIMUM_DAMAGE_FROM_OBSTACLES.into(); @@ -1691,7 +1710,7 @@ mod tests { use combat::{constants::CombatEnums::{Slot, Type}}; use beasts::{beast::{ImplBeast, Beast}, constants::BeastSettings}; use survivor::{ - adventurer::{IAdventurer, ImplAdventurer, Adventurer}, + adventurer::{IAdventurer, ImplAdventurer, Adventurer, AdventurerPacking}, item_meta::{ItemSpecials, ItemSpecialsStorage, ImplItemSpecials}, adventurer_stats::Stats, item_primitive::ItemPrimitive, adventurer_utils::{AdventurerUtils}, bag::{Bag, ImplBag}, constants::{ @@ -1707,9 +1726,6 @@ mod tests { discovery_constants::DiscoveryEnums::{ExploreResult, DiscoveryType} } }; - use pack::{ - pack::{Packing, rshift_split}, constants, constants::{MASK_8, pow, MASK_3, MASK_BOOL, mask} - }; #[test] #[available_gas(505770)] @@ -2736,8 +2752,8 @@ mod tests { stat_points_available: 7, mutated: false }; - let packed = adventurer.pack(); - let unpacked: Adventurer = Packing::unpack(packed); + let packed = AdventurerPacking::pack(adventurer); + let unpacked: Adventurer = AdventurerPacking::unpack(packed); assert(adventurer.last_action == unpacked.last_action, 'last_action'); assert(adventurer.health == unpacked.health, 'health'); assert(adventurer.xp == unpacked.xp, 'xp'); @@ -2778,59 +2794,12 @@ mod tests { 'stat_points_available' ); } - - #[test] - #[available_gas(3000000)] - fn test_packing_stat_overflow_protection() { - // create an adventurer with stats at max u8 - let adventurer = Adventurer { - last_action: 511, - health: 511, - xp: 8191, - stats: Stats { - strength: 255, - dexterity: 255, - vitality: 255, - intelligence: 255, - wisdom: 255, - charisma: 255, - luck: 255 - }, - gold: 511, - weapon: ItemPrimitive { id: 127, xp: 511, metadata: 31, }, - chest: ItemPrimitive { id: 1, xp: 0, metadata: 0, }, - head: ItemPrimitive { id: 127, xp: 511, metadata: 31, }, - waist: ItemPrimitive { id: 87, xp: 511, metadata: 4, }, - foot: ItemPrimitive { id: 78, xp: 511, metadata: 5, }, - hand: ItemPrimitive { id: 34, xp: 511, metadata: 6, }, - neck: ItemPrimitive { id: 32, xp: 511, metadata: 7, }, - ring: ItemPrimitive { id: 1, xp: 511, metadata: 8, }, - beast_health: 511, - stat_points_available: 7, - mutated: false - }; - - // pack adventurer - let packed = adventurer.pack(); - - // unpack adventurer - let unpacked: Adventurer = Packing::unpack(packed); - - // verify packing function didn't overflow stats - // but instead set values to max - assert(unpacked.stats.strength == MAX_STAT_VALUE, 'strength'); - assert(unpacked.stats.dexterity == MAX_STAT_VALUE, 'dexterity'); - assert(unpacked.stats.vitality == MAX_STAT_VALUE, 'vitality'); - assert(unpacked.stats.intelligence == MAX_STAT_VALUE, 'intelligence'); - assert(unpacked.stats.wisdom == MAX_STAT_VALUE, 'wisdom'); - assert(unpacked.stats.charisma == MAX_STAT_VALUE, 'charisma'); - } - + #[test] #[available_gas(2000000)] fn test_new_adventurer() { let mut adventurer = ImplAdventurer::new(12, 0, 0, 0); - adventurer.pack(); + AdventurerPacking::pack(adventurer); assert(adventurer.health == STARTING_HEALTH, 'wrong starting health'); assert(adventurer.gold == STARTING_GOLD, 'wrong starting gold'); assert(adventurer.xp == 0, 'wrong starting xp'); @@ -2882,7 +2851,7 @@ mod tests { assert(adventurer.gold == MAX_GOLD, 'gold should be max'); // pack and unpack adventurer to test overflow in packing - let unpacked: Adventurer = Packing::unpack(adventurer.pack()); + let unpacked: Adventurer = AdventurerPacking::unpack(AdventurerPacking::pack(adventurer)); assert(unpacked.gold == MAX_GOLD, 'should still be max gold'); // extreme/overflow case @@ -2974,7 +2943,7 @@ mod tests { assert(adventurer.stat_points_available == MAX_STAT_UPGRADES, 'stat points should be max'); // pack and unpack at max value to ensure our max values are correct for packing - let unpacked: Adventurer = Packing::unpack(adventurer.pack()); + let unpacked: Adventurer = AdventurerPacking::unpack(AdventurerPacking::pack(adventurer)); assert( unpacked.stat_points_available == MAX_STAT_UPGRADES, 'stat point should still be max' ); diff --git a/contracts/adventurer/src/adventurer_meta.cairo b/contracts/adventurer/src/adventurer_meta.cairo index b1041f506..cadab6453 100644 --- a/contracts/adventurer/src/adventurer_meta.cairo +++ b/contracts/adventurer/src/adventurer_meta.cairo @@ -1,6 +1,5 @@ +use starknet::{StorePacking}; use traits::{TryInto, Into}; -use pack::constants::pow; -use pack::pack::{Packing, rshift_split}; #[derive(Drop, Copy, Serde)] struct AdventurerMetadata { @@ -8,40 +7,41 @@ struct AdventurerMetadata { entropy: u128, } -impl PackingAdventurerMetadata of Packing { - fn pack(self: AdventurerMetadata) -> felt252 { - (self.entropy.into() - + self.name.into() * pow::TWO_POW_128) - .try_into() - .expect('pack AdventurerMetadata') - } - fn unpack(packed: felt252) -> AdventurerMetadata { - let packed = packed.into(); - let (packed, entropy) = rshift_split(packed, pow::TWO_POW_128); - let (_, name) = rshift_split(packed, pow::TWO_POW_128); - AdventurerMetadata { - name: name.try_into().expect('unpack AdvMetadata name'), - entropy: entropy.try_into().expect('unpack AdvMetadata entropy') - } - } +const TWO_POW_128: u256 = 0x100000000000000000000000000000000; - // TODO: add overflow pack protection - fn overflow_pack_protection(self: AdventurerMetadata) -> AdventurerMetadata { - self +impl PackingAdventurerMetadata of StorePacking { + fn pack(value: AdventurerMetadata) -> felt252 { + (value.entropy.into() + value.name.into() * TWO_POW_128).try_into().unwrap() + } + fn unpack(value: felt252) -> AdventurerMetadata { + let packed = value.into(); + let (packed, entropy) = integer::U256DivRem::div_rem( + packed, TWO_POW_128.try_into().unwrap() + ); + let (_, name) = integer::U256DivRem::div_rem(packed, TWO_POW_128.try_into().unwrap()); + AdventurerMetadata { name: name.try_into().unwrap(), entropy: entropy.try_into().unwrap() } } } #[cfg(test)] #[test] -#[available_gas(96380)] +#[available_gas(116600)] fn test_pack_unpack_adventurer_meta() { - let meta = AdventurerMetadata { - name: 'abcdefghijklmno', - entropy: 340282366920938463463374607431768211455 - }; + // max value case + let max_u128 = 340282366920938463463374607431768211455; + let name_length = 'abcdefghijklmno'; - let packed = meta.pack(); - let unpacked: AdventurerMetadata = Packing::unpack(packed); - assert(meta.name == unpacked.name, 'name'); - assert(meta.entropy == unpacked.entropy, 'entropy'); -} + let meta = AdventurerMetadata { name: name_length, entropy: max_u128 }; + + let packed = PackingAdventurerMetadata::pack(meta); + let unpacked: AdventurerMetadata = PackingAdventurerMetadata::unpack(packed); + assert(meta.name == unpacked.name, 'name should be max'); + assert(meta.entropy == unpacked.entropy, 'entropy should be max u128'); + + // zero case + let meta = AdventurerMetadata { name: 0, entropy: 0 }; + let packed = PackingAdventurerMetadata::pack(meta); + let unpacked: AdventurerMetadata = PackingAdventurerMetadata::unpack(packed); + assert(unpacked.name == 0, 'name should be 0'); + assert(unpacked.entropy == 0, 'entropy should be 0'); +} \ No newline at end of file diff --git a/contracts/adventurer/src/adventurer_stats.cairo b/contracts/adventurer/src/adventurer_stats.cairo index 510c51053..07bd7dc6b 100644 --- a/contracts/adventurer/src/adventurer_stats.cairo +++ b/contracts/adventurer/src/adventurer_stats.cairo @@ -1,6 +1,6 @@ +use starknet::{StorePacking}; use option::OptionTrait; use traits::{TryInto, Into}; -use pack::{pack::{Packing, rshift_split}, constants::pow}; use survivor::constants::adventurer_constants::MAX_STAT_VALUE; #[derive(Drop, Copy, Serde)] @@ -14,7 +14,7 @@ struct Stats { // 5 bits each wisdom: u8, // 5 bits charisma: u8, // 5 bits // Metaphysical - luck: u8 // dynamically generated (not stored) + luck: u8 // // not stored - dynamically generated } #[generate_trait] @@ -26,64 +26,51 @@ impl StatUtils of IStat { } } -impl StatsPacking of Packing { - fn pack(self: Stats) -> felt252 { - let overflow_protected = self.overflow_pack_protection(); - - (overflow_protected.strength.into() - + overflow_protected.dexterity.into() * pow::TWO_POW_5 - + overflow_protected.vitality.into() * pow::TWO_POW_10 - + overflow_protected.intelligence.into() * pow::TWO_POW_15 - + overflow_protected.wisdom.into() * pow::TWO_POW_20 - + overflow_protected.charisma.into() * pow::TWO_POW_25) +const TWO_POW_5: u256 = 0x20; +const TWO_POW_10: u256 = 0x400; +const TWO_POW_15: u256 = 0x8000; +const TWO_POW_20: u256 = 0x100000; +const TWO_POW_25: u256 = 0x2000000; + +impl StatsPacking of StorePacking { + fn pack(value: Stats) -> felt252 { + (value.strength.into() + + value.dexterity.into() * TWO_POW_5 + + value.vitality.into() * TWO_POW_10 + + value.intelligence.into() * TWO_POW_15 + + value.wisdom.into() * TWO_POW_20 + + value.charisma.into() * TWO_POW_25) .try_into() - .expect('pack Stats') + .unwrap() } - fn unpack(packed: felt252) -> Stats { - let packed = packed.into(); - let (packed, strength) = rshift_split(packed, pow::TWO_POW_5); - let (packed, dexterity) = rshift_split(packed, pow::TWO_POW_5); - let (packed, vitality) = rshift_split(packed, pow::TWO_POW_5); - let (packed, intelligence) = rshift_split(packed, pow::TWO_POW_5); - let (packed, wisdom) = rshift_split(packed, pow::TWO_POW_5); - let (_, charisma) = rshift_split(packed, pow::TWO_POW_5); + fn unpack(value: felt252) -> Stats { + let packed = value.into(); + let (packed, strength) = integer::U256DivRem::div_rem( + packed, TWO_POW_5.try_into().unwrap() + ); + let (packed, dexterity) = integer::U256DivRem::div_rem( + packed, TWO_POW_5.try_into().unwrap() + ); + let (packed, vitality) = integer::U256DivRem::div_rem( + packed, TWO_POW_5.try_into().unwrap() + ); + let (packed, intelligence) = integer::U256DivRem::div_rem( + packed, TWO_POW_5.try_into().unwrap() + ); + let (packed, wisdom) = integer::U256DivRem::div_rem(packed, TWO_POW_5.try_into().unwrap()); + let (_, charisma) = integer::U256DivRem::div_rem(packed, TWO_POW_5.try_into().unwrap()); Stats { - strength: strength.try_into().expect('unpack Stats strength'), - dexterity: dexterity.try_into().expect('unpack Stats dexterity'), - vitality: vitality.try_into().expect('unpack Stats vitality'), - intelligence: intelligence.try_into().expect('unpack Stats intelligence'), - wisdom: wisdom.try_into().expect('unpack Stats wisdom'), - charisma: charisma.try_into().expect('unpack Stats charisma'), + strength: strength.try_into().unwrap(), + dexterity: dexterity.try_into().unwrap(), + vitality: vitality.try_into().unwrap(), + intelligence: intelligence.try_into().unwrap(), + wisdom: wisdom.try_into().unwrap(), + charisma: charisma.try_into().unwrap(), luck: 0 } } - - fn overflow_pack_protection(self: Stats) -> Stats { - let mut overflow_protected_stats = self; - - if self.strength > MAX_STAT_VALUE { - overflow_protected_stats.strength = MAX_STAT_VALUE; - }; - if self.dexterity > MAX_STAT_VALUE { - overflow_protected_stats.dexterity = MAX_STAT_VALUE; - } - if self.vitality > MAX_STAT_VALUE { - overflow_protected_stats.vitality = MAX_STAT_VALUE; - } - if self.intelligence > MAX_STAT_VALUE { - overflow_protected_stats.intelligence = MAX_STAT_VALUE; - } - if self.wisdom > MAX_STAT_VALUE { - overflow_protected_stats.wisdom = MAX_STAT_VALUE; - } - if self.charisma > MAX_STAT_VALUE { - overflow_protected_stats.charisma = MAX_STAT_VALUE; - } - - overflow_protected_stats - } } // --------------------------- @@ -103,7 +90,7 @@ mod tests { strength: 0, dexterity: 0, vitality: 0, intelligence: 0, wisdom: 0, charisma: 0, luck: 0 }; - let packed = stats.pack(); + let packed = StatsPacking::pack(stats); let unpacked = StatsPacking::unpack(packed); assert(stats.strength == unpacked.strength, 'strength zero case'); assert(stats.dexterity == unpacked.dexterity, 'dexterity zero case'); @@ -124,7 +111,7 @@ mod tests { luck: 31 }; - let packed = stats.pack(); + let packed = StatsPacking::pack(stats); let unpacked = StatsPacking::unpack(packed); assert(stats.strength == unpacked.strength, 'strength storage limit'); assert(stats.dexterity == unpacked.dexterity, 'dexterity storage limit'); @@ -133,28 +120,5 @@ mod tests { assert(stats.wisdom == unpacked.wisdom, 'wisdom storage limit'); assert(stats.charisma == unpacked.charisma, 'charisma storage limit'); assert(unpacked.luck == 0, 'luck is zero from storage'); - - // overflow storage limit using max u8 - let stats = Stats { - strength: 255, - dexterity: 255, - vitality: 255, - intelligence: 255, - wisdom: 255, - charisma: 255, - luck: 255 - }; - - let packed = stats.pack(); - let unpacked = StatsPacking::unpack(packed); - - // assert packing function prevented overflow - assert(unpacked.strength == MAX_STAT_VALUE, 'strength pack overflow'); - assert(unpacked.dexterity == MAX_STAT_VALUE, 'dexterity pack overflow'); - assert(unpacked.vitality == MAX_STAT_VALUE, 'vitality pack overflow'); - assert(unpacked.intelligence == MAX_STAT_VALUE, 'intelligence pack overflow'); - assert(unpacked.wisdom == MAX_STAT_VALUE, 'wisdom pack overflow'); - assert(unpacked.charisma == MAX_STAT_VALUE, 'charisma pack overflow'); - assert(unpacked.luck == 0, 'luck is zero from storage'); } } diff --git a/contracts/adventurer/src/adventurer_utils.cairo b/contracts/adventurer/src/adventurer_utils.cairo index 39b8eae47..72745d736 100644 --- a/contracts/adventurer/src/adventurer_utils.cairo +++ b/contracts/adventurer/src/adventurer_utils.cairo @@ -3,7 +3,9 @@ use core::{result::ResultTrait, traits::{TryInto, Into}}; use poseidon::poseidon_hash_span; use option::OptionTrait; use array::ArrayTrait; -use integer::{u8_overflowing_add, u16_overflowing_add, u16_overflowing_sub, U128IntoU256}; +use integer::{ + u8_overflowing_add, u16_overflowing_add, u16_overflowing_sub, U128IntoU256, u256_try_as_non_zero +}; use super::{ constants::{ adventurer_constants::{ @@ -23,10 +25,6 @@ use lootitems::constants::{ } }; use combat::constants::CombatEnums::{Type, Tier, Slot}; -use pack::{ - pack::{rshift_split}, - constants::{MASK_16, pow, MASK_8, MASK_3, MASK_BOOL, mask, U128_MASK_8, u128_pow} -}; #[generate_trait] impl AdventurerUtils of IAdventurerUtils { @@ -94,7 +92,9 @@ impl AdventurerUtils of IAdventurerUtils { hash_span.append(block_number.into()); hash_span.append(block_timestamp.into()); let poseidon: felt252 = poseidon_hash_span(hash_span.span()).into(); - let (d, r) = rshift_split(poseidon.into(), U128_MAX.into()); + let (d, r) = integer::U256DivRem::div_rem( + poseidon.into(), u256_try_as_non_zero(U128_MAX.into()).unwrap() + ); r.try_into().unwrap() } @@ -107,7 +107,9 @@ impl AdventurerUtils of IAdventurerUtils { hash_span.append(entropy.into()); hash_span.append(item_id.into()); let poseidon: felt252 = poseidon_hash_span(hash_span.span()).into(); - let (d, r) = rshift_split(poseidon.into(), U128_MAX.into()); + let (d, r) = integer::U256DivRem::div_rem( + poseidon.into(), u256_try_as_non_zero(U128_MAX.into()).unwrap() + ); (r.try_into().unwrap(), d.try_into().unwrap()) } @@ -219,7 +221,9 @@ impl AdventurerUtils of IAdventurerUtils { // @param felt_to_split: felt to split // @return (u128, u128): tuple of u128s fn split_hash(felt_to_split: felt252) -> (u128, u128) { - let (d, r) = rshift_split(felt_to_split.into(), U128_MAX.into()); + let (d, r) = integer::U256DivRem::div_rem( + felt_to_split.into(), u256_try_as_non_zero(U128_MAX.into()).unwrap() + ); (r.try_into().unwrap(), d.try_into().unwrap()) } @@ -270,25 +274,41 @@ impl AdventurerUtils of IAdventurerUtils { fn u128_to_u8_array(value: u128) -> Array { let mut result = ArrayTrait::::new(); - result.append((value & U128_MASK_8).try_into().unwrap()); - result.append(((value / u128_pow::_8) & U128_MASK_8).try_into().unwrap()); - result.append(((value / u128_pow::_16) & U128_MASK_8).try_into().unwrap()); - result.append(((value / u128_pow::_24) & U128_MASK_8).try_into().unwrap()); - result.append(((value / u128_pow::_32) & U128_MASK_8).try_into().unwrap()); - result.append(((value / u128_pow::_40) & U128_MASK_8).try_into().unwrap()); - result.append(((value / u128_pow::_48) & U128_MASK_8).try_into().unwrap()); - result.append(((value / u128_pow::_56) & U128_MASK_8).try_into().unwrap()); - result.append(((value / u128_pow::_64) & U128_MASK_8).try_into().unwrap()); - result.append(((value / u128_pow::_72) & U128_MASK_8).try_into().unwrap()); - result.append(((value / u128_pow::_80) & U128_MASK_8).try_into().unwrap()); - result.append(((value / u128_pow::_88) & U128_MASK_8).try_into().unwrap()); - result.append(((value / u128_pow::_96) & U128_MASK_8).try_into().unwrap()); - result.append(((value / u128_pow::_104) & U128_MASK_8).try_into().unwrap()); - result.append(((value / u128_pow::_112) & U128_MASK_8).try_into().unwrap()); - result.append(((value / u128_pow::_120) & U128_MASK_8).try_into().unwrap()); + result.append((value & MASK_8).try_into().unwrap()); + result.append(((value / TWO_POW_8) & MASK_8).try_into().unwrap()); + result.append(((value / TWO_POW_16) & MASK_8).try_into().unwrap()); + result.append(((value / TWO_POW_24) & MASK_8).try_into().unwrap()); + result.append(((value / TWO_POW_32) & MASK_8).try_into().unwrap()); + result.append(((value / TWO_POW_40) & MASK_8).try_into().unwrap()); + result.append(((value / TWO_POW_48) & MASK_8).try_into().unwrap()); + result.append(((value / TWO_POW_56) & MASK_8).try_into().unwrap()); + result.append(((value / TWO_POW_64) & MASK_8).try_into().unwrap()); + result.append(((value / TWO_POW_72) & MASK_8).try_into().unwrap()); + result.append(((value / TWO_POW_80) & MASK_8).try_into().unwrap()); + result.append(((value / TWO_POW_88) & MASK_8).try_into().unwrap()); + result.append(((value / TWO_POW_96) & MASK_8).try_into().unwrap()); + result.append(((value / TWO_POW_104) & MASK_8).try_into().unwrap()); + result.append(((value / TWO_POW_112) & MASK_8).try_into().unwrap()); + result.append(((value / TWO_POW_120) & MASK_8).try_into().unwrap()); result } } +const MASK_8: u128 = 0xFF; +const TWO_POW_8: u128 = 0x100; +const TWO_POW_16: u128 = 0x10000; +const TWO_POW_24: u128 = 0x1000000; +const TWO_POW_32: u128 = 0x100000000; +const TWO_POW_40: u128 = 0x10000000000; +const TWO_POW_48: u128 = 0x1000000000000; +const TWO_POW_56: u128 = 0x100000000000000; +const TWO_POW_64: u128 = 0x10000000000000000; +const TWO_POW_72: u128 = 0x1000000000000000000; +const TWO_POW_80: u128 = 0x100000000000000000000; +const TWO_POW_88: u128 = 0x10000000000000000000000; +const TWO_POW_96: u128 = 0x1000000000000000000000000; +const TWO_POW_104: u128 = 0x100000000000000000000000000; +const TWO_POW_112: u128 = 0x10000000000000000000000000000; +const TWO_POW_120: u128 = 0x1000000000000000000000000000000; // --------------------------- // ---------- Tests ---------- diff --git a/contracts/adventurer/src/bag.cairo b/contracts/adventurer/src/bag.cairo index 08c3b5da8..b9623c387 100644 --- a/contracts/adventurer/src/bag.cairo +++ b/contracts/adventurer/src/bag.cairo @@ -1,11 +1,10 @@ -use traits::{TryInto, Into}; -use option::OptionTrait; -use pack::{pack::{Packing, rshift_split}, constants::pow}; +use starknet::{StorePacking}; +use lootitems::constants::ItemId; use super::{ - adventurer::{Adventurer, ImplAdventurer, IAdventurer}, - item_primitive::{ItemPrimitive, ImplItemPrimitive}, item_meta::{ImplItemSpecials, IItemSpecials} + adventurer::{Adventurer, ImplAdventurer}, + item_primitive::{ItemPrimitive, ImplItemPrimitive, ItemPrimitivePacking}, + item_meta::{ImplItemSpecials} }; -use lootitems::constants::ItemId; // Bag is used for storing gear not equipped to the adventurer // TODO: Change this to an Array with id: u8, size: u8, and modified: bool @@ -26,57 +25,65 @@ struct Bag { mutated: bool, } -impl BagPacking of Packing { - fn pack(self: Bag) -> felt252 { - (self.item_1.pack().into() - + self.item_2.pack().into() * pow::TWO_POW_21 - + self.item_3.pack().into() * pow::TWO_POW_42 - + self.item_4.pack().into() * pow::TWO_POW_63 - + self.item_5.pack().into() * pow::TWO_POW_84 - + self.item_6.pack().into() * pow::TWO_POW_105 - + self.item_7.pack().into() * pow::TWO_POW_126 - + self.item_8.pack().into() * pow::TWO_POW_147 - + self.item_9.pack().into() * pow::TWO_POW_168 - + self.item_10.pack().into() * pow::TWO_POW_189 - + self.item_11.pack().into() * pow::TWO_POW_210) +const TWO_POW_21: u256 = 0x200000; +const TWO_POW_42: u256 = 0x40000000000; +const TWO_POW_63: u256 = 0x8000000000000000; +const TWO_POW_84: u256 = 0x1000000000000000000000; +const TWO_POW_105: u256 = 0x200000000000000000000000000; +const TWO_POW_126: u256 = 0x40000000000000000000000000000000; +const TWO_POW_147: u256 = 0x8000000000000000000000000000000000000; +const TWO_POW_168: u256 = 0x1000000000000000000000000000000000000000000; +const TWO_POW_189: u256 = 0x200000000000000000000000000000000000000000000000; +const TWO_POW_210: u256 = 0x40000000000000000000000000000000000000000000000000000; + +impl BagPacking of StorePacking { + fn pack(value: Bag) -> felt252 { + (ItemPrimitivePacking::pack(value.item_1).into() + + ItemPrimitivePacking::pack(value.item_2).into() * TWO_POW_21 + + ItemPrimitivePacking::pack(value.item_3).into() * TWO_POW_42 + + ItemPrimitivePacking::pack(value.item_4).into() * TWO_POW_63 + + ItemPrimitivePacking::pack(value.item_5).into() * TWO_POW_84 + + ItemPrimitivePacking::pack(value.item_6).into() * TWO_POW_105 + + ItemPrimitivePacking::pack(value.item_7).into() * TWO_POW_126 + + ItemPrimitivePacking::pack(value.item_8).into() * TWO_POW_147 + + ItemPrimitivePacking::pack(value.item_9).into() * TWO_POW_168 + + ItemPrimitivePacking::pack(value.item_10).into() * TWO_POW_189 + + ItemPrimitivePacking::pack(value.item_11).into() * TWO_POW_210) .try_into() - .expect('pack Bag') + .unwrap() } - fn unpack(packed: felt252) -> Bag { - let packed = packed.into(); - let (packed, item_1) = rshift_split(packed, pow::TWO_POW_21); - let (packed, item_2) = rshift_split(packed, pow::TWO_POW_21); - let (packed, item_3) = rshift_split(packed, pow::TWO_POW_21); - let (packed, item_4) = rshift_split(packed, pow::TWO_POW_21); - let (packed, item_5) = rshift_split(packed, pow::TWO_POW_21); - let (packed, item_6) = rshift_split(packed, pow::TWO_POW_21); - let (packed, item_7) = rshift_split(packed, pow::TWO_POW_21); - let (packed, item_8) = rshift_split(packed, pow::TWO_POW_21); - let (packed, item_9) = rshift_split(packed, pow::TWO_POW_21); - let (packed, item_10) = rshift_split(packed, pow::TWO_POW_21); - let (_, item_11) = rshift_split(packed, pow::TWO_POW_21); + fn unpack(value: felt252) -> Bag { + let packed = value.into(); + let (packed, item_1) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, item_2) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, item_3) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, item_4) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, item_5) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, item_6) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, item_7) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, item_8) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, item_9) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); + let (packed, item_10) = integer::U256DivRem::div_rem( + packed, TWO_POW_21.try_into().unwrap() + ); + let (_, item_11) = integer::U256DivRem::div_rem(packed, TWO_POW_21.try_into().unwrap()); Bag { - item_1: Packing::unpack(item_1.try_into().expect('unpack Bag item_1')), - item_2: Packing::unpack(item_2.try_into().expect('unpack Bag item_2')), - item_3: Packing::unpack(item_3.try_into().expect('unpack Bag item_3')), - item_4: Packing::unpack(item_4.try_into().expect('unpack Bag item_4')), - item_5: Packing::unpack(item_5.try_into().expect('unpack Bag item_5')), - item_6: Packing::unpack(item_6.try_into().expect('unpack Bag item_6')), - item_7: Packing::unpack(item_7.try_into().expect('unpack Bag item_7')), - item_8: Packing::unpack(item_8.try_into().expect('unpack Bag item_8')), - item_9: Packing::unpack(item_9.try_into().expect('unpack Bag item_9')), - item_10: Packing::unpack(item_10.try_into().expect('unpack Bag item_10')), - item_11: Packing::unpack(item_11.try_into().expect('unpack Bag item_11')), + item_1: ItemPrimitivePacking::unpack(item_1.try_into().unwrap()), + item_2: ItemPrimitivePacking::unpack(item_2.try_into().unwrap()), + item_3: ItemPrimitivePacking::unpack(item_3.try_into().unwrap()), + item_4: ItemPrimitivePacking::unpack(item_4.try_into().unwrap()), + item_5: ItemPrimitivePacking::unpack(item_5.try_into().unwrap()), + item_6: ItemPrimitivePacking::unpack(item_6.try_into().unwrap()), + item_7: ItemPrimitivePacking::unpack(item_7.try_into().unwrap()), + item_8: ItemPrimitivePacking::unpack(item_8.try_into().unwrap()), + item_9: ItemPrimitivePacking::unpack(item_9.try_into().unwrap()), + item_10: ItemPrimitivePacking::unpack(item_10.try_into().unwrap()), + item_11: ItemPrimitivePacking::unpack(item_11.try_into().unwrap()), mutated: false } } - - // Not used for bag - fn overflow_pack_protection(self: Bag) -> Bag { - self - } } #[generate_trait] @@ -374,9 +381,8 @@ impl ImplBag of IBag { // --------------------------- #[cfg(test)] mod tests { - use survivor::{bag::{Bag, ImplBag, IBag}, item_primitive::{ItemPrimitive}}; + use survivor::{bag::{Bag, ImplBag, IBag, BagPacking}, item_primitive::{ItemPrimitive}}; use lootitems::{constants::ItemId}; - use pack::{pack::{Packing}}; #[test] #[available_gas(94030)] @@ -613,7 +619,7 @@ mod tests { mutated: false, }; - let packed_bag: Bag = Packing::unpack(bag.pack()); + let packed_bag: Bag = BagPacking::unpack(BagPacking::pack(bag)); assert(packed_bag.item_1.id == 127, 'Loot 1 ID is not 127'); assert(packed_bag.item_1.xp == 511, 'Loot 1 XP is not 511'); diff --git a/contracts/adventurer/src/item_meta.cairo b/contracts/adventurer/src/item_meta.cairo index 87028a39a..68c6add1e 100644 --- a/contracts/adventurer/src/item_meta.cairo +++ b/contracts/adventurer/src/item_meta.cairo @@ -1,4 +1,4 @@ -use pack::{pack::{Packing, rshift_split}, constants::pow}; +use starknet::{StorePacking}; use lootitems::constants::{ItemId, ItemSuffix}; use super::{ adventurer::{Adventurer, IAdventurer, ImplAdventurer}, item_primitive::ItemPrimitive, @@ -61,7 +61,7 @@ struct ItemSpecialsStorage { mutated: bool, } -// TODO: We can greatly simplify and harden our meta data storage by switching to the below +// TODO: Meta data storage can be simplified and more easily extended by meta data storage by switching to the below // data structure. This data structure will allow us to identify the storage id when // it is being operated on and also to flag the storage as modified when it is altered // so that the top-level contract code knows when it needs to write it to storage. @@ -77,22 +77,39 @@ struct ItemSpecialsStorage { // item_specials: Array, // } -impl ItemSpecialsPacking of Packing { - fn pack(self: ItemSpecials) -> felt252 { - let overflow_protected = self.overflow_pack_protection(); - - (overflow_protected.special2.into() - + overflow_protected.special3.into() * pow::TWO_POW_7 - + overflow_protected.special1.into() * pow::TWO_POW_12) +const TWO_POW_4: u256 = 0x10; +const TWO_POW_5: u256 = 0x20; +const TWO_POW_7: u256 = 0x80; +const TWO_POW_12: u256 = 0x1000; +const TWO_POW_16: u256 = 0x10000; // 2^16 +const TWO_POW_32: u256 = 0x100000000; // 2^32 +const TWO_POW_48: u256 = 0x1000000000000; // 2^48 +const TWO_POW_64: u256 = 0x10000000000000000; // 2^64 +const TWO_POW_80: u256 = 0x100000000000000000000; // 2^80 +const TWO_POW_96: u256 = 0x1000000000000000000000000; // 2^96 +const TWO_POW_112: u256 = 0x10000000000000000000000000000; // 2^112 +const TWO_POW_128: u256 = 0x100000000000000000000000000000000; // 2^128 +const TWO_POW_144: u256 = 0x1000000000000000000000000000000000000; // 2^144 + + +impl ItemSpecialsPacking of StorePacking { + fn pack(value: ItemSpecials) -> felt252 { + (value.special2.into() + + value.special3.into() * TWO_POW_7 + + value.special1.into() * TWO_POW_12) .try_into() - .expect('pack ItemSpecials') + .unwrap() } - fn unpack(packed: felt252) -> ItemSpecials { - let packed = packed.into(); - let (packed, special2) = rshift_split(packed, pow::TWO_POW_7); - let (packed, special3) = rshift_split(packed, pow::TWO_POW_5); - let (_, special1) = rshift_split(packed, pow::TWO_POW_4); + fn unpack(value: felt252) -> ItemSpecials { + let packed = value.into(); + let (packed, special2) = integer::U256DivRem::div_rem( + packed, TWO_POW_7.try_into().unwrap() + ); + let (packed, special3) = integer::U256DivRem::div_rem( + packed, TWO_POW_5.try_into().unwrap() + ); + let (_, special1) = integer::U256DivRem::div_rem(packed, TWO_POW_4.try_into().unwrap()); ItemSpecials { special2: special2.try_into().expect('unpack LISN special2'), @@ -100,93 +117,51 @@ impl ItemSpecialsPacking of Packing { special1: special1.try_into().expect('unpack LISN special1') } } - - // @dev This function applies an overflow protection mechanism to the item's specials. - // - // @notice The function receives an instance of ItemSpecials and checks if any of the specials - // exceed their respective max limit values (MAX_SPECIAL1, MAX_SPECIAL2, and MAX_SPECIAL3). - // If a special exceeds its limit, it is reset to the maximum allowable value. - // This way, the function ensures that none of the specials go beyond the predefined limits. - // The function then returns the updated ItemSpecials object. - // - // @param self An instance of ItemSpecials that is to be checked and potentially adjusted for overflow. - // - // @return An instance of ItemSpecials where all the specials are ensured to be within their respective maximum limits. - fn overflow_pack_protection(self: ItemSpecials) -> ItemSpecials { - // Create a mutable copy of self to apply overflow protection - let mut overflow_protected_specials = self; - - // Check if special1 exceeds its max limit - if self.special1 > MAX_SPECIAL1 { - // If special1 overflows, reset it to its max value - overflow_protected_specials.special1 = MAX_SPECIAL1; - }; - - // Check if special2 exceeds its max limit - if self.special2 > MAX_SPECIAL2 { - // If special2 overflows, reset it to its max value - overflow_protected_specials.special2 = MAX_SPECIAL2; - }; - - // Check if special3 exceeds its max limit - if self.special3 > MAX_SPECIAL3 { - // If special3 overflows, reset it to its max value - overflow_protected_specials.special3 = MAX_SPECIAL3; - }; - - // Return the updated ItemSpecials object with overflow protection - overflow_protected_specials - } } -impl ItemSpecialsStoragePacking of Packing { - fn pack(self: ItemSpecialsStorage) -> felt252 { - (self.item_1.pack().into() - + self.item_2.pack().into() * pow::TWO_POW_16 - + self.item_3.pack().into() * pow::TWO_POW_32 - + self.item_4.pack().into() * pow::TWO_POW_48 - + self.item_5.pack().into() * pow::TWO_POW_64 - + self.item_6.pack().into() * pow::TWO_POW_80 - + self.item_7.pack().into() * pow::TWO_POW_96 - + self.item_8.pack().into() * pow::TWO_POW_112 - + self.item_9.pack().into() * pow::TWO_POW_128 - + self.item_10.pack().into() * pow::TWO_POW_144) +impl ItemSpecialsStoragePacking of StorePacking { + fn pack(value: ItemSpecialsStorage) -> felt252 { + (ItemSpecialsPacking::pack(value.item_1).into() + + ItemSpecialsPacking::pack(value.item_2).into() * TWO_POW_16 + + ItemSpecialsPacking::pack(value.item_3).into() * TWO_POW_32 + + ItemSpecialsPacking::pack(value.item_4).into() * TWO_POW_48 + + ItemSpecialsPacking::pack(value.item_5).into() * TWO_POW_64 + + ItemSpecialsPacking::pack(value.item_6).into() * TWO_POW_80 + + ItemSpecialsPacking::pack(value.item_7).into() * TWO_POW_96 + + ItemSpecialsPacking::pack(value.item_8).into() * TWO_POW_112 + + ItemSpecialsPacking::pack(value.item_9).into() * TWO_POW_128 + + ItemSpecialsPacking::pack(value.item_10).into() * TWO_POW_144) .try_into() - .expect('pack LISNS') + .unwrap() } - fn unpack(packed: felt252) -> ItemSpecialsStorage { - let packed = packed.into(); - let (packed, item_1) = rshift_split(packed, pow::TWO_POW_16); - let (packed, item_2) = rshift_split(packed, pow::TWO_POW_16); - let (packed, item_3) = rshift_split(packed, pow::TWO_POW_16); - let (packed, item_4) = rshift_split(packed, pow::TWO_POW_16); - let (packed, item_5) = rshift_split(packed, pow::TWO_POW_16); - let (packed, item_6) = rshift_split(packed, pow::TWO_POW_16); - let (packed, item_7) = rshift_split(packed, pow::TWO_POW_16); - let (packed, item_8) = rshift_split(packed, pow::TWO_POW_16); - let (packed, item_9) = rshift_split(packed, pow::TWO_POW_16); - let (_, item_10) = rshift_split(packed, pow::TWO_POW_16); + fn unpack(value: felt252) -> ItemSpecialsStorage { + let packed = value.into(); + let (packed, item_1) = integer::U256DivRem::div_rem(packed, TWO_POW_16.try_into().unwrap()); + let (packed, item_2) = integer::U256DivRem::div_rem(packed, TWO_POW_16.try_into().unwrap()); + let (packed, item_3) = integer::U256DivRem::div_rem(packed, TWO_POW_16.try_into().unwrap()); + let (packed, item_4) = integer::U256DivRem::div_rem(packed, TWO_POW_16.try_into().unwrap()); + let (packed, item_5) = integer::U256DivRem::div_rem(packed, TWO_POW_16.try_into().unwrap()); + let (packed, item_6) = integer::U256DivRem::div_rem(packed, TWO_POW_16.try_into().unwrap()); + let (packed, item_7) = integer::U256DivRem::div_rem(packed, TWO_POW_16.try_into().unwrap()); + let (packed, item_8) = integer::U256DivRem::div_rem(packed, TWO_POW_16.try_into().unwrap()); + let (packed, item_9) = integer::U256DivRem::div_rem(packed, TWO_POW_16.try_into().unwrap()); + let (_, item_10) = integer::U256DivRem::div_rem(packed, TWO_POW_16.try_into().unwrap()); ItemSpecialsStorage { - item_1: Packing::unpack(item_1.try_into().expect('unpack LISNS item_1')), - item_2: Packing::unpack(item_2.try_into().expect('unpack LISNS item_2')), - item_3: Packing::unpack(item_3.try_into().expect('unpack LISNS item_3')), - item_4: Packing::unpack(item_4.try_into().expect('unpack LISNS item_4')), - item_5: Packing::unpack(item_5.try_into().expect('unpack LISNS item_5')), - item_6: Packing::unpack(item_6.try_into().expect('unpack LISNS item_6')), - item_7: Packing::unpack(item_7.try_into().expect('unpack LISNS item_7')), - item_8: Packing::unpack(item_8.try_into().expect('unpack LISNS item_8')), - item_9: Packing::unpack(item_9.try_into().expect('unpack LISNS item_9')), - item_10: Packing::unpack(item_10.try_into().expect('unpack LISNS item_10')), + item_1: ItemSpecialsPacking::unpack(item_1.try_into().unwrap()), + item_2: ItemSpecialsPacking::unpack(item_2.try_into().unwrap()), + item_3: ItemSpecialsPacking::unpack(item_3.try_into().unwrap()), + item_4: ItemSpecialsPacking::unpack(item_4.try_into().unwrap()), + item_5: ItemSpecialsPacking::unpack(item_5.try_into().unwrap()), + item_6: ItemSpecialsPacking::unpack(item_6.try_into().unwrap()), + item_7: ItemSpecialsPacking::unpack(item_7.try_into().unwrap()), + item_8: ItemSpecialsPacking::unpack(item_8.try_into().unwrap()), + item_9: ItemSpecialsPacking::unpack(item_9.try_into().unwrap()), + item_10: ItemSpecialsPacking::unpack(item_10.try_into().unwrap()), mutated: false, } } - - // TODO: add overflow pack protection - fn overflow_pack_protection(self: ItemSpecialsStorage) -> ItemSpecialsStorage { - self - } } #[generate_trait] @@ -473,14 +448,13 @@ impl ImplItemSpecials of IItemSpecials { // --------------------------- #[cfg(test)] mod tests { - use pack::pack::{Packing}; use lootitems::constants::{ItemId}; use survivor::{ adventurer::{ImplAdventurer}, item_primitive::ItemPrimitive, adventurer_stats::Stats, bag::{Bag, IBag}, item_meta::{ - ImplItemSpecials, ItemSpecialsStorage, ItemSpecials, MAX_SPECIAL1, MAX_SPECIAL2, - MAX_SPECIAL3, STORAGE + ImplItemSpecials, ItemSpecialsStorage, ItemSpecials, ItemSpecialsStoragePacking, + MAX_SPECIAL1, MAX_SPECIAL2, MAX_SPECIAL3, STORAGE }, }; @@ -498,41 +472,31 @@ mod tests { item_4: ItemSpecials { special1: 15, special2: 127, special3: 31 // max packable values }, - item_5: ItemSpecials { special1: 255, special2: 255, special3: 255 // max u8 values - }, - item_6: ItemSpecials { special1: 5, special2: 5, special3: 5 // dnc - }, - item_7: ItemSpecials { special1: 6, special2: 6, special3: 6 // dnc - }, - item_8: ItemSpecials { special1: 7, special2: 7, special3: 7 // dnc - }, - item_9: ItemSpecials { special1: 8, special2: 8, special3: 8 // dnc - }, - item_10: ItemSpecials { special1: 9, special2: 9, special3: 9 // dnc - }, + item_5: ItemSpecials { special1: 4, special2: 23, special3: 2 }, + item_6: ItemSpecials { special1: 5, special2: 5, special3: 5 }, + item_7: ItemSpecials { special1: 6, special2: 6, special3: 6 }, + item_8: ItemSpecials { special1: 7, special2: 7, special3: 7 }, + item_9: ItemSpecials { special1: 8, special2: 8, special3: 8 }, + item_10: ItemSpecials { special1: 9, special2: 9, special3: 9 }, mutated: false, }; // pack and then unpack the specials - let unpacked: ItemSpecialsStorage = Packing::unpack(storage.pack()); + let unpacked: ItemSpecialsStorage = ItemSpecialsStoragePacking::unpack( + ItemSpecialsStoragePacking::pack(storage) + ); // assert the values were not altered using PartialEq assert(unpacked.item_1 == storage.item_1, 'item 1 packing error'); assert(unpacked.item_2 == storage.item_2, 'item 2 packing error'); assert(unpacked.item_3 == storage.item_3, 'item 3 packing error'); assert(unpacked.item_4 == storage.item_4, 'item 4 packing error'); + assert(unpacked.item_5 == storage.item_5, 'item 5 packing error'); assert(unpacked.item_6 == storage.item_6, 'item 6 packing error'); assert(unpacked.item_7 == storage.item_7, 'item 7 packing error'); assert(unpacked.item_8 == storage.item_8, 'item 8 packing error'); assert(unpacked.item_9 == storage.item_9, 'item 9 packing error'); assert(unpacked.item_10 == storage.item_10, 'item 10 packing error'); - - // item 5 is special in that it attempts to overflow the packing - // assert the packing overflow protection works and instead of - // overflowing, sets these values to max - assert(unpacked.item_5.special1 == MAX_SPECIAL1, 'special1 max u8 check'); - assert(unpacked.item_5.special2 == MAX_SPECIAL2, 'special2 max u8 check'); - assert(unpacked.item_5.special3 == MAX_SPECIAL3, 'special3 max u8 check'); } #[test] diff --git a/contracts/adventurer/src/item_primitive.cairo b/contracts/adventurer/src/item_primitive.cairo index 3770eb351..d36402645 100644 --- a/contracts/adventurer/src/item_primitive.cairo +++ b/contracts/adventurer/src/item_primitive.cairo @@ -1,6 +1,6 @@ +use starknet::{StorePacking}; use option::OptionTrait; use traits::{TryInto, Into}; -use pack::{pack::{Packing, rshift_split}, constants::pow}; use lootitems::loot::{ItemId}; #[derive(Drop, Copy, PartialEq, Serde)] // 21 bits @@ -10,30 +10,29 @@ struct ItemPrimitive { metadata: u8, // 5 bits } -impl ItemPrimitivePacking of Packing { - fn pack(self: ItemPrimitive) -> felt252 { - (self.id.into() + self.xp.into() * pow::TWO_POW_7 + self.metadata.into() * pow::TWO_POW_16) - .try_into() - .expect('pack ItemPrimitive') +const TWO_POW_5: u256 = 0x20; +const TWO_POW_7: u256 = 0x80; +const TWO_POW_9: u256 = 0x200; +const TWO_POW_16: u256 = 0x10000; + +impl ItemPrimitivePacking of StorePacking { + fn pack(value: ItemPrimitive) -> felt252 { + (value.id.into() + value.xp.into() * TWO_POW_7 + value.metadata.into() * TWO_POW_16) + .try_into().unwrap() } - fn unpack(packed: felt252) -> ItemPrimitive { - let packed = packed.into(); - let (packed, id) = rshift_split(packed, pow::TWO_POW_7); - let (packed, xp) = rshift_split(packed, pow::TWO_POW_9); - let (_, metadata) = rshift_split(packed, pow::TWO_POW_5); + fn unpack(value: felt252) -> ItemPrimitive { + let packed = value.into(); + let (packed, id) = integer::U256DivRem::div_rem(packed, TWO_POW_7.try_into().unwrap()); + let (packed, xp) = integer::U256DivRem::div_rem(packed, TWO_POW_9.try_into().unwrap()); + let (_, metadata) = integer::U256DivRem::div_rem(packed, TWO_POW_5.try_into().unwrap()); ItemPrimitive { - id: id.try_into().expect('unpack ItemPrimitive id'), - xp: xp.try_into().expect('unpack ItemPrimitive xp'), - metadata: metadata.try_into().expect('unpack ItemPrimitive metadata') + id: id.try_into().unwrap(), + xp: xp.try_into().unwrap(), + metadata: metadata.try_into().unwrap() } } - - // TODO: add overflow pack protection - fn overflow_pack_protection(self: ItemPrimitive) -> ItemPrimitive { - self - } } #[generate_trait] @@ -138,7 +137,7 @@ mod tests { fn test_item_primitive_packing() { let item = ItemPrimitive { id: 1, xp: 2, metadata: 3 }; - let packed = item.pack(); + let packed = ItemPrimitivePacking::pack(item); let unpacked = ItemPrimitivePacking::unpack(packed); assert(item.id == unpacked.id, 'id should be the same'); @@ -148,7 +147,7 @@ mod tests { // max value case let item = ItemPrimitive { id: 127, xp: 511, metadata: 31 }; - let packed = item.pack(); + let packed = ItemPrimitivePacking::pack(item); let unpacked = ItemPrimitivePacking::unpack(packed); assert(item.id == unpacked.id, 'id should be the same'); assert(item.xp == unpacked.xp, 'xp should be the same'); @@ -156,7 +155,7 @@ mod tests { // overflow case let item = ItemPrimitive { id: 128, xp: 512, metadata: 32 }; - let packed = item.pack(); + let packed = ItemPrimitivePacking::pack(item); let unpacked = ItemPrimitivePacking::unpack(packed); assert(unpacked.id == 0, 'id should overflow to 0'); assert(unpacked.xp == 1, 'xp should overflow to 1'); diff --git a/contracts/game/src/game/game_entropy.cairo b/contracts/game/src/game/game_entropy.cairo index 2404519be..5ff64ec2a 100644 --- a/contracts/game/src/game/game_entropy.cairo +++ b/contracts/game/src/game/game_entropy.cairo @@ -1,4 +1,4 @@ -use pack::{constants::pow, pack::{Packing, rshift_split}}; +use starknet::{StorePacking}; #[derive(Drop, Copy, Serde)] struct GameEntropy { @@ -6,27 +6,23 @@ struct GameEntropy { last_updated: u64, } -impl GameEntropyPacking of Packing { - fn pack(self: GameEntropy) -> felt252 { - (self.entropy.into() - + self.last_updated.into() * pow::TWO_POW_128) - .try_into() - .expect('pack GameEntropy') +const TWO_POW_128: u256 = 0x100000000000000000000000000000000; + +impl GameEntropyPacking of StorePacking { + fn pack(value: GameEntropy) -> felt252 { + (value.entropy.into() + (value.last_updated.into() * TWO_POW_128)).try_into().unwrap() } - fn unpack(packed: felt252) -> GameEntropy { - let packed = packed.into(); - let (packed, entropy) = rshift_split(packed, pow::TWO_POW_128); - let (_, last_updated) = rshift_split(packed, pow::TWO_POW_128); + fn unpack(value: felt252) -> GameEntropy { + let packed = value.into(); + let (packed, entropy) = integer::U256DivRem::div_rem(packed, TWO_POW_128.try_into().unwrap()); + let (_, last_updated) = integer::U256DivRem::div_rem(packed, TWO_POW_128.try_into().unwrap()); GameEntropy { - entropy: entropy.try_into().unwrap(), last_updated: last_updated.try_into().unwrap(), + entropy: entropy.try_into().unwrap(), + last_updated: last_updated.try_into().unwrap(), } } - // Not used for game entropy - fn overflow_pack_protection(self: GameEntropy) -> GameEntropy { - self - } } // --------------------------- @@ -35,19 +31,20 @@ impl GameEntropyPacking of Packing { #[cfg(test)] mod tests { use game::game::game_entropy::{GameEntropy, GameEntropyPacking}; - use pack::{pack::{Packing}}; #[test] #[available_gas(3000000)] fn test_packing_and_unpacking_game_entropy() { + // max value case let game_entropy = GameEntropy { entropy: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, last_updated: 0xFFFFFFFFFFFFFFFF }; - let unpacked: GameEntropy = Packing::unpack(game_entropy.pack()); + let unpacked: GameEntropy = GameEntropyPacking::unpack(GameEntropyPacking::pack(game_entropy)); assert(unpacked.entropy == game_entropy.entropy, 'wrong entropy max value'); assert(unpacked.last_updated == game_entropy.last_updated, 'wrong last_updated max value'); + // zero case let game_entropy = GameEntropy { entropy: 0, last_updated: 0 }; - let unpacked: GameEntropy = Packing::unpack(game_entropy.pack()); + let unpacked: GameEntropy = GameEntropyPacking::unpack(GameEntropyPacking::pack(game_entropy)); assert(unpacked.entropy == game_entropy.entropy, 'wrong entropy zero'); assert(unpacked.last_updated == game_entropy.last_updated, 'wrong last_updated zero'); diff --git a/contracts/game/src/lib.cairo b/contracts/game/src/lib.cairo index bd8e48abf..e0a128951 100644 --- a/contracts/game/src/lib.cairo +++ b/contracts/game/src/lib.cairo @@ -16,16 +16,13 @@ mod Game { const LOOT_NAME_STORAGE_INDEX_1: u256 = 0; const LOOT_NAME_STORAGE_INDEX_2: u256 = 1; - use option::OptionTrait; - use box::BoxTrait; - use core::array::SpanTrait; - use starknet::{ - get_caller_address, ContractAddress, ContractAddressIntoFelt252, contract_address_const + use core::{ + array::{SpanTrait, ArrayTrait}, integer::u256_try_as_non_zero, traits::{TryInto, Into}, + clone::Clone, poseidon::poseidon_hash_span, option::OptionTrait, box::BoxTrait, + starknet::{ + get_caller_address, ContractAddress, ContractAddressIntoFelt252, contract_address_const + }, }; - use core::traits::{TryInto, Into}; - use core::clone::Clone; - use array::ArrayTrait; - use poseidon::poseidon_hash_span; use openzeppelin::token::erc20::interface::{ IERC20Camel, IERC20CamelDispatcher, IERC20CamelDispatcherTrait, IERC20CamelLibraryDispatcher @@ -44,7 +41,6 @@ mod Game { use lootitems::{ loot::{ILoot, Loot, ImplLoot}, constants::{ItemId, NamePrefixLength, NameSuffixLength} }; - use pack::{pack::{Packing, rshift_split}, constants::{MASK_16, pow, MASK_8, MASK_BOOL, mask}}; use survivor::{ adventurer::{Adventurer, ImplAdventurer, IAdventurer}, adventurer_stats::{Stats, StatUtils}, item_primitive::{ImplItemPrimitive, ItemPrimitive}, bag::{Bag, IBag, ImplBag}, @@ -71,13 +67,12 @@ mod Game { #[storage] struct Storage { - _game_entropy: felt252, - _adventurer: LegacyMap::, + _game_entropy: GameEntropy, + _adventurer: LegacyMap::, _owner: LegacyMap::, - _adventurer_meta: LegacyMap::, - _loot: LegacyMap::, - _loot_special_names: LegacyMap::<(u256, u256), felt252>, - _bag: LegacyMap::, + _adventurer_meta: LegacyMap::, + _item_specials: LegacyMap::<(u256, u256), ItemSpecialsStorage>, + _bag: LegacyMap::, _counter: u256, _lords: ContractAddress, _dao: ContractAddress, @@ -805,7 +800,7 @@ mod Game { fn get_special_storage( self: @ContractState, adventurer_id: u256, storage_index: u256 ) -> ItemSpecialsStorage { - Packing::unpack(self._loot_special_names.read((adventurer_id, storage_index))) + self._item_specials.read((adventurer_id, storage_index)) } fn get_beast_type(self: @ContractState, beast_id: u8) -> u8 { ImplCombat::type_to_u8(ImplBeast::get_type(beast_id)) @@ -1987,13 +1982,13 @@ mod Game { // ------------ Helper Functions ------------ // // ------------------------------------------ // fn _unpack_adventurer(self: @ContractState, adventurer_id: u256) -> Adventurer { - Packing::unpack(self._adventurer.read(adventurer_id)) + self._adventurer.read(adventurer_id) } fn _unpack_adventurer_and_bag_with_stat_boosts( self: @ContractState, adventurer_id: u256 ) -> (Adventurer, Stats, Bag) { // unpack adventurer - let mut adventurer: Adventurer = Packing::unpack(self._adventurer.read(adventurer_id)); + let mut adventurer: Adventurer = self._adventurer.read(adventurer_id); // start with no stat boosts let mut stat_boosts = StatUtils::new(); // if adventurer has item specials @@ -2017,7 +2012,7 @@ mod Game { #[inline(always)] fn _pack_adventurer(ref self: ContractState, adventurer_id: u256, adventurer: Adventurer) { - self._adventurer.write(adventurer_id, adventurer.pack()); + self._adventurer.write(adventurer_id, adventurer); } // @dev Packs and saves an adventurer after removing stat boosts. // @param adventurer_id The ID of the adventurer to be modified. @@ -2029,35 +2024,37 @@ mod Game { // remove stat boosts adventurer.remove_stat_boosts(stat_boosts); - // pack and save - self._adventurer.write(adventurer_id, adventurer.pack()); + // save adventurer + self._adventurer.write(adventurer_id, adventurer); } #[inline(always)] fn _unpacked_bag(self: @ContractState, adventurer_id: u256) -> Bag { - Packing::unpack(self._bag.read(adventurer_id)) + self._bag.read(adventurer_id) } #[inline(always)] fn _pack_bag(ref self: ContractState, adventurer_id: u256, bag: Bag) { - self._bag.write(adventurer_id, bag.pack()); + self._bag.write(adventurer_id, bag); } #[inline(always)] fn _unpack_adventurer_meta(self: @ContractState, adventurer_id: u256) -> AdventurerMetadata { - Packing::unpack(self._adventurer_meta.read(adventurer_id)) + self._adventurer_meta.read(adventurer_id) } #[inline(always)] fn _pack_adventurer_meta( ref self: ContractState, adventurer_id: u256, adventurer_meta: AdventurerMetadata ) { - self._adventurer_meta.write(adventurer_id, adventurer_meta.pack()); + self._adventurer_meta.write(adventurer_id, adventurer_meta); } #[inline(always)] fn _unpack_game_entropy(self: @ContractState) -> GameEntropy { - Packing::unpack(self._game_entropy.read()) + //Packing::unpack(self._game_entropy.read()) + self._game_entropy.read() } #[inline(always)] fn _pack_game_entropy(ref self: ContractState, game_entropy: GameEntropy) { - self._game_entropy.write(game_entropy.pack()); + //self._game_entropy.write(game_entropy.pack()); + self._game_entropy.write(game_entropy); } /// @title Internal Rotate Game Entropy Function @@ -2081,7 +2078,9 @@ mod Game { hash_span.append(timestamp.into()); hash_span.append(blocknumber.into()); let poseidon: felt252 = poseidon_hash_span(hash_span.span()).into(); - let (_, entropy) = rshift_split(poseidon.into(), U128_MAX.into()); + let (_, entropy) = integer::U256DivRem::div_rem( + poseidon.into(), u256_try_as_non_zero(U128_MAX.into()).unwrap() + ); // set new game entropy and block number of update let updated_game_entropy = GameEntropy { @@ -2128,9 +2127,7 @@ mod Game { storage_index: u256, loot_special_names_storage: ItemSpecialsStorage, ) { - self - ._loot_special_names - .write((adventurer_id, storage_index), loot_special_names_storage.pack()); + self._item_specials.write((adventurer_id, storage_index), loot_special_names_storage); } #[inline(always)] @@ -2147,7 +2144,7 @@ mod Game { fn _get_specials_storage( self: @ContractState, adventurer_id: u256, storage_index: u256 ) -> ItemSpecialsStorage { - Packing::unpack(self._loot_special_names.read((adventurer_id, storage_index))) + self._item_specials.read((adventurer_id, storage_index)) } #[inline(always)] diff --git a/contracts/loot/Scarb.toml b/contracts/loot/Scarb.toml index a70e19b4b..e09a9f4cc 100644 --- a/contracts/loot/Scarb.toml +++ b/contracts/loot/Scarb.toml @@ -5,5 +5,4 @@ version = "0.1.0" # See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest [dependencies] -pack = { path = "../pack" } combat = { path = "../combat" } diff --git a/contracts/loot/src/loot.cairo b/contracts/loot/src/loot.cairo index ec62d9ba6..ff5ded1d8 100644 --- a/contracts/loot/src/loot.cairo +++ b/contracts/loot/src/loot.cairo @@ -1,9 +1,9 @@ +use starknet::{StorePacking}; use traits::{TryInto, Into}; use option::OptionTrait; use core::{serde::Serde, clone::Clone}; use combat::{combat::ImplCombat, constants::CombatEnums::{Type, Tier, Slot}}; -use pack::{pack::{Packing, rshift_split}, constants::pow}; use super::{ constants::{ NamePrefixLength, ItemNameSuffix, ItemId, ItemNamePrefix, NameSuffixLength, @@ -944,46 +944,41 @@ impl ImplLoot of ILoot { } } } - -impl PackingLoot of Packing { - // pack an item for storage - // @param item The item to pack. - // @return The packed item in a felt252 - fn pack(self: Loot) -> felt252 { - let item_tier = ImplCombat::tier_to_u8(self.tier); - let item_type = ImplCombat::type_to_u8(self.item_type); - let item_slot = ImplCombat::slot_to_u8(self.slot); - - (self.id.into() - + item_tier.into() * pow::TWO_POW_8 - + item_type.into() * pow::TWO_POW_16 - + item_slot.into() * pow::TWO_POW_24) +const TWO_POW_8: u256 = 0x100; +const TWO_POW_16: u256 = 0x10000; +const TWO_POW_24: u256 = 0x1000000; + +impl LootPacking of StorePacking { + fn pack(value: Loot) -> felt252 { + let item_tier = ImplCombat::tier_to_u8(value.tier); + let item_type = ImplCombat::type_to_u8(value.item_type); + let item_slot = ImplCombat::slot_to_u8(value.slot); + + (value.id.into() + + item_tier.into() * TWO_POW_8 + + item_type.into() * TWO_POW_16 + + item_slot.into() * TWO_POW_24) .try_into() - .expect('pack Loot') + .unwrap() } - - // unpack an item from storage - // @param packed The item packed as a felt252 - // @return The unpacked item - fn unpack(packed: felt252) -> Loot { - let packed = packed.into(); - let (packed, item_id) = rshift_split(packed, pow::TWO_POW_8); - let (packed, item_tier) = rshift_split(packed, pow::TWO_POW_8); - let (packed, item_type) = rshift_split(packed, pow::TWO_POW_8); - let (_, item_slot) = rshift_split(packed, pow::TWO_POW_8); + fn unpack(value: felt252) -> Loot { + let packed = value.into(); + let (packed, item_id) = integer::U256DivRem::div_rem(packed, TWO_POW_8.try_into().unwrap()); + let (packed, item_tier) = integer::U256DivRem::div_rem( + packed, TWO_POW_8.try_into().unwrap() + ); + let (packed, item_type) = integer::U256DivRem::div_rem( + packed, TWO_POW_8.try_into().unwrap() + ); + let (_, item_slot) = integer::U256DivRem::div_rem(packed, TWO_POW_8.try_into().unwrap()); Loot { - id: item_id.try_into().expect('unpack Loot id'), - tier: ImplCombat::u8_to_tier(item_tier.try_into().expect('unpack Loot tier')), - item_type: ImplCombat::u8_to_type(item_type.try_into().expect('unpack Loot item type')), - slot: ImplCombat::u8_to_slot(item_slot.try_into().expect('unpack Loot slot')) + id: item_id.try_into().unwrap(), + tier: ImplCombat::u8_to_tier(item_tier.try_into().unwrap()), + item_type: ImplCombat::u8_to_type(item_type.try_into().unwrap()), + slot: ImplCombat::u8_to_slot(item_slot.try_into().unwrap()) } } - - // TODO: add overflow pack protection - fn overflow_pack_protection(self: Loot) -> Loot { - self - } } // --------------------------- @@ -996,9 +991,8 @@ mod tests { use core::{serde::Serde, clone::Clone}; use combat::{combat::ImplCombat, constants::CombatEnums::{Type, Tier, Slot}}; - use pack::{pack::{Packing, rshift_split}, constants::pow}; use lootitems::{ - loot::{ImplLoot, ILoot, PackingLoot, Loot}, + loot::{ImplLoot, ILoot, LootPacking, Loot}, constants::{ NamePrefixLength, ItemNameSuffix, ItemId, ItemNamePrefix, NameSuffixLength, ItemSuffixLength, ItemSuffix, NUM_ITEMS, @@ -1271,7 +1265,7 @@ mod tests { id: 1, tier: Tier::T1(()), item_type: Type::Bludgeon_or_Metal(()), slot: Slot::Waist(()) }; - let unpacked: Loot = Packing::unpack(loot.pack()); + let unpacked: Loot = LootPacking::unpack(LootPacking::pack(loot)); assert(loot.id == unpacked.id, 'id'); assert(loot.tier == unpacked.tier, 'tier'); assert(loot.item_type == unpacked.item_type, 'item_type'); diff --git a/contracts/market/src/market.cairo b/contracts/market/src/market.cairo index b8769fa8c..e668ad535 100644 --- a/contracts/market/src/market.cairo +++ b/contracts/market/src/market.cairo @@ -4,13 +4,12 @@ use array::{ArrayTrait, SpanTrait}; use option::OptionTrait; use core::clone::Clone; use poseidon::poseidon_hash_span; +use integer::u256_try_as_non_zero; use lootitems::{loot::{Loot, ILoot, ImplLoot}, constants::{ItemId, NUM_ITEMS}}; use combat::constants::CombatEnums::{Tier, Slot}; use super::constants::{NUM_LOOT_ITEMS, NUMBER_OF_ITEMS_PER_LEVEL, TIER_PRICE}; -use pack::pack::{rshift_split}; - #[derive(Drop, Serde)] struct LootWithPrice { @@ -147,7 +146,9 @@ impl ImplMarket of IMarket { // @param seed a 256-bit unsigned integer representing a unique identifier for the seed. // @return a u8 representing the item ID. fn get_id(seed: u256) -> u8 { - let (_, item_id) = rshift_split(seed, NUM_ITEMS.into()); + let (_, item_id) = integer::U256DivRem::div_rem( + seed, u256_try_as_non_zero(NUM_ITEMS.into()).unwrap() + ); 1 + item_id.try_into().unwrap() } @@ -220,7 +221,9 @@ impl ImplMarket of IMarket { // market seed and the second element is an 8-bit unsigned integer that represents the market offset. fn split_hash_into_seed_and_offset(poseidon_hash: felt252) -> (u256, u8) { // split hash into two u128s, one for market seed, one for offset - let (market_seed, offset) = rshift_split(poseidon_hash.into(), NUM_ITEMS.into() - 1); + let (market_seed, offset) = integer::U256DivRem::div_rem( + poseidon_hash.into(), u256_try_as_non_zero(NUM_ITEMS.into() - 1).unwrap() + ); // return market seed and market offset (market_seed, 1 + offset.try_into().unwrap()) @@ -241,8 +244,6 @@ mod tests { use market::{ market::ImplMarket, constants::{NUM_LOOT_ITEMS, NUMBER_OF_ITEMS_PER_LEVEL, TIER_PRICE} }; - use pack::pack::{rshift_split}; - const TEST_MARKET_SEED: u256 = 515; const TEST_OFFSET: u8 = 3; diff --git a/contracts/pack/.gitignore b/contracts/pack/.gitignore deleted file mode 100644 index eb5a316cb..000000000 --- a/contracts/pack/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target diff --git a/contracts/pack/Scarb.toml b/contracts/pack/Scarb.toml deleted file mode 100644 index 1f6afa068..000000000 --- a/contracts/pack/Scarb.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "pack" -version = "0.1.0" - -# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest - -[dependencies] -# foo = { path = "vendor/foo" } diff --git a/contracts/pack/src/constants.cairo b/contracts/pack/src/constants.cairo deleted file mode 100644 index 5e09a4aa7..000000000 --- a/contracts/pack/src/constants.cairo +++ /dev/null @@ -1,435 +0,0 @@ -mod mask { - const MASK_1: u256 = 0x1; - const MASK_2: u256 = 0x3; - const MASK_3: u256 = 0x7; - const MASK_4: u256 = 0xF; - const MASK_5: u256 = 0x1F; - const MASK_6: u256 = 0x3F; - const MASK_7: u256 = 0x7F; - const MASK_8: u256 = 0xFF; - const MASK_9: u256 = 0x1FF; - const MASK_10: u256 = 0x3FF; - const MASK_11: u256 = 0x7FF; - const MASK_12: u256 = 0xFFF; - const MASK_13: u256 = 0x1FFF; - const MASK_14: u256 = 0x3FFF; - const MASK_15: u256 = 0x7FFF; - const MASK_16: u256 = 0xFFFF; - const MASK_17: u256 = 0x1FFFF; - const MASK_18: u256 = 0x3FFFF; - const MASK_19: u256 = 0x7FFFF; - const MASK_20: u256 = 0xFFFFF; - const MASK_21: u256 = 0x1FFFFF; - const MASK_22: u256 = 0x3FFFFF; - const MASK_23: u256 = 0x7FFFFF; - const MASK_24: u256 = 0xFFFFFF; - const MASK_25: u256 = 0x1FFFFFF; - const MASK_26: u256 = 0x3FFFFFF; - const MASK_27: u256 = 0x7FFFFFF; - const MASK_28: u256 = 0xFFFFFFF; - const MASK_29: u256 = 0x1FFFFFFF; - const MASK_30: u256 = 0x3FFFFFFF; - const MASK_31: u256 = 0x7FFFFFFF; - const MASK_32: u256 = 0xFFFFFFFF; - const MASK_33: u256 = 0x1FFFFFFFF; - const MASK_34: u256 = 0x3FFFFFFFF; - const MASK_35: u256 = 0x7FFFFFFFF; - const MASK_36: u256 = 0xFFFFFFFFF; - const MASK_37: u256 = 0x1FFFFFFFFF; - const MASK_38: u256 = 0x3FFFFFFFFF; - const MASK_39: u256 = 0x7FFFFFFFFF; - const MASK_40: u256 = 0xFFFFFFFFFF; - const MASK_41: u256 = 0x1FFFFFFFFFF; - const MASK_42: u256 = 0x3FFFFFFFFFF; - const MASK_43: u256 = 0x7FFFFFFFFFF; - const MASK_44: u256 = 0xFFFFFFFFFFF; - const MASK_45: u256 = 0x1FFFFFFFFFFF; - const MASK_46: u256 = 0x3FFFFFFFFFFF; - const MASK_47: u256 = 0x7FFFFFFFFFFF; - const MASK_48: u256 = 0xFFFFFFFFFFFF; - const MASK_49: u256 = 0x1FFFFFFFFFFFF; - const MASK_50: u256 = 0x3FFFFFFFFFFFF; - const MASK_51: u256 = 0x7FFFFFFFFFFFF; - const MASK_52: u256 = 0xFFFFFFFFFFFFF; - const MASK_53: u256 = 0x1FFFFFFFFFFFFF; - const MASK_54: u256 = 0x3FFFFFFFFFFFFF; - const MASK_55: u256 = 0x7FFFFFFFFFFFFF; - const MASK_56: u256 = 0xFFFFFFFFFFFFFF; - const MASK_57: u256 = 0x1FFFFFFFFFFFFFF; - const MASK_58: u256 = 0x3FFFFFFFFFFFFFF; - const MASK_59: u256 = 0x7FFFFFFFFFFFFFF; - const MASK_60: u256 = 0xFFFFFFFFFFFFFFF; - const MASK_61: u256 = 0x1FFFFFFFFFFFFFFF; - const MASK_62: u256 = 0x3FFFFFFFFFFFFFFF; - const MASK_63: u256 = 0x7FFFFFFFFFFFFFFF; - const MASK_64: u256 = 0xFFFFFFFFFFFFFFFF; - const MASK_65: u256 = 0x1FFFFFFFFFFFFFFFF; - const MASK_66: u256 = 0x3FFFFFFFFFFFFFFFF; - const MASK_67: u256 = 0x7FFFFFFFFFFFFFFFF; - const MASK_68: u256 = 0xFFFFFFFFFFFFFFFFF; - const MASK_69: u256 = 0x1FFFFFFFFFFFFFFFFF; - const MASK_70: u256 = 0x3FFFFFFFFFFFFFFFFF; - const MASK_71: u256 = 0x7FFFFFFFFFFFFFFFFF; - const MASK_72: u256 = 0xFFFFFFFFFFFFFFFFFF; - const MASK_73: u256 = 0x1FFFFFFFFFFFFFFFFFF; - const MASK_74: u256 = 0x3FFFFFFFFFFFFFFFFFF; - const MASK_75: u256 = 0x7FFFFFFFFFFFFFFFFFF; - const MASK_76: u256 = 0xFFFFFFFFFFFFFFFFFFFF; - const MASK_77: u256 = 0x1FFFFFFFFFFFFFFFFFFFF; - const MASK_78: u256 = 0x3FFFFFFFFFFFFFFFFFFFF; - const MASK_79: u256 = 0x7FFFFFFFFFFFFFFFFFFFF; - const MASK_80: u256 = 0xFFFFFFFFFFFFFFFFFFFFFF; - const MASK_81: u256 = 0x1FFFFFFFFFFFFFFFFFFFFFF; - const MASK_82: u256 = 0x3FFFFFFFFFFFFFFFFFFFFFF; - const MASK_83: u256 = 0x7FFFFFFFFFFFFFFFFFFFFFF; - const MASK_84: u256 = 0xFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_85: u256 = 0x1FFFFFFFFFFFFFFFFFFFFFFF; - const MASK_86: u256 = 0x3FFFFFFFFFFFFFFFFFFFFFFF; - const MASK_87: u256 = 0x7FFFFFFFFFFFFFFFFFFFFFFF; - const MASK_88: u256 = 0xFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_89: u256 = 0x1FFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_90: u256 = 0x3FFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_91: u256 = 0x7FFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_92: u256 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_93: u256 = 0x1FFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_94: u256 = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_95: u256 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_96: u256 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_97: u256 = 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_98: u256 = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_99: u256 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_100: u256 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_101: u256 = 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_102: u256 = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_103: u256 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_104: u256 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_105: u256 = 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_106: u256 = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_107: u256 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_108: u256 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_109: u256 = 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_110: u256 = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_111: u256 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_112: u256 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_113: u256 = 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_114: u256 = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_115: u256 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_116: u256 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_117: u256 = 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_118: u256 = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_119: u256 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_120: u256 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_121: u256 = 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_122: u256 = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_123: u256 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_124: u256 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_125: u256 = 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_126: u256 = 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_127: u256 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; - const MASK_128: u256 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; -} - -const MASK_63: u256 = 0x7FFFFFFFFFFFFFFF; -const MASK_3: u256 = 0b111; -const MASK_6: u256 = 0x3F; -const MASK_8: u256 = 0xFF; // Mask for 8-bit values: id, prefix1, prefix2, suffix -const U128_MASK_8: u128 = 0xFF; - -const MASK_16: u256 = 0xFFFF; // Mask for 16-bit values: xp -const MASK_BOOL: u256 = 0x1; // Mask for boolean values: isEquipped - -mod u128_pow { - const _8: u128 = 0x100; - const _16: u128 = 0x10000; - const _24: u128 = 0x1000000; - const _32: u128 = 0x100000000; - const _40: u128 = 0x10000000000; - const _48: u128 = 0x1000000000000; - const _56: u128 = 0x100000000000000; - const _64: u128 = 0x10000000000000000; - const _72: u128 = 0x1000000000000000000; - const _80: u128 = 0x100000000000000000000; - const _88: u128 = 0x10000000000000000000000; - const _96: u128 = 0x1000000000000000000000000; - const _104: u128 = 0x100000000000000000000000000; - const _112: u128 = 0x10000000000000000000000000000; - const _120: u128 = 0x1000000000000000000000000000000; -} - -mod pow { - const TWO_POW_1: u256 = 0x2; // 2^1 - const TWO_POW_2: u256 = 0x4; // 2^2 - const TWO_POW_3: u256 = 0x8; // 2^3 - const TWO_POW_4: u256 = 0x10; // 2^4 - const TWO_POW_5: u256 = 0x20; // 2^5 - const TWO_POW_6: u256 = 0x40; // 2^6 - const TWO_POW_7: u256 = 0x80; // 2^7 - const TWO_POW_8: u256 = 0x100; // 2^8 - const TWO_POW_9: u256 = 0x200; // 2^9 - const TWO_POW_10: u256 = 0x400; // 2^10 - const TWO_POW_11: u256 = 0x800; // 2^11 - const TWO_POW_12: u256 = 0x1000; // 2^12 - const TWO_POW_13: u256 = 0x2000; // 2^13 - const TWO_POW_14: u256 = 0x4000; // 2^14 - const TWO_POW_15: u256 = 0x8000; // 2^15 - const TWO_POW_16: u256 = 0x10000; // 2^16 - const TWO_POW_17: u256 = 0x20000; // 2^17 - const TWO_POW_18: u256 = 0x40000; // 2^18 - const TWO_POW_19: u256 = 0x80000; // 2^19 - const TWO_POW_20: u256 = 0x100000; // 2^20 - const TWO_POW_21: u256 = 0x200000; // 2^21 - const TWO_POW_22: u256 = 0x400000; // 2^22 - const TWO_POW_23: u256 = 0x800000; // 2^23 - const TWO_POW_24: u256 = 0x1000000; // 2^24 - const TWO_POW_25: u256 = 0x2000000; // 2^25 - const TWO_POW_26: u256 = 0x4000000; // 2^26 - const TWO_POW_27: u256 = 0x8000000; // 2^27 - const TWO_POW_28: u256 = 0x10000000; // 2^28 - const TWO_POW_29: u256 = 0x20000000; // 2^29 - const TWO_POW_30: u256 = 0x40000000; // 2^30 - const TWO_POW_31: u256 = 0x80000000; // 2^31 - const TWO_POW_32: u256 = 0x100000000; // 2^32 - const TWO_POW_33: u256 = 0x200000000; // 2^33 - const TWO_POW_34: u256 = 0x400000000; // 2^34 - const TWO_POW_35: u256 = 0x800000000; // 2^35 - const TWO_POW_36: u256 = 0x1000000000; // 2^36 - const TWO_POW_37: u256 = 0x2000000000; // 2^37 - const TWO_POW_38: u256 = 0x4000000000; // 2^38 - const TWO_POW_39: u256 = 0x8000000000; // 2^39 - const TWO_POW_40: u256 = 0x10000000000; // 2^40 - const TWO_POW_41: u256 = 0x20000000000; // 2^41 - const TWO_POW_42: u256 = 0x40000000000; // 2^42 - const TWO_POW_43: u256 = 0x80000000000; // 2^43 - const TWO_POW_44: u256 = 0x100000000000; // 2^44 - const TWO_POW_45: u256 = 0x200000000000; // 2^45 - const TWO_POW_46: u256 = 0x400000000000; // 2^46 - const TWO_POW_47: u256 = 0x800000000000; // 2^47 - const TWO_POW_48: u256 = 0x1000000000000; // 2^48 - const TWO_POW_49: u256 = 0x2000000000000; // 2^49 - const TWO_POW_50: u256 = 0x4000000000000; // 2^50 - const TWO_POW_51: u256 = 0x8000000000000; // 2^51 - const TWO_POW_52: u256 = 0x10000000000000; // 2^52 - const TWO_POW_53: u256 = 0x20000000000000; // 2^53 - const TWO_POW_54: u256 = 0x40000000000000; // 2^54 - const TWO_POW_55: u256 = 0x80000000000000; // 2^55 - const TWO_POW_56: u256 = 0x100000000000000; // 2^56 - const TWO_POW_57: u256 = 0x200000000000000; // 2^57 - const TWO_POW_58: u256 = 0x400000000000000; // 2^58 - const TWO_POW_59: u256 = 0x800000000000000; // 2^59 - const TWO_POW_60: u256 = 0x1000000000000000; // 2^60 - const TWO_POW_61: u256 = 0x2000000000000000; // 2^61 - const TWO_POW_62: u256 = 0x4000000000000000; // 2^62 - const TWO_POW_63: u256 = 0x8000000000000000; // 2^63 - const TWO_POW_64: u256 = 0x10000000000000000; // 2^64 - const TWO_POW_65: u256 = 0x20000000000000000; // 2^65 - const TWO_POW_66: u256 = 0x40000000000000000; // 2^66 - const TWO_POW_67: u256 = 0x80000000000000000; // 2^67 - const TWO_POW_68: u256 = 0x100000000000000000; // 2^68 - const TWO_POW_69: u256 = 0x200000000000000000; // 2^69 - const TWO_POW_70: u256 = 0x400000000000000000; // 2^70 - const TWO_POW_71: u256 = 0x800000000000000000; // 2^71 - const TWO_POW_72: u256 = 0x1000000000000000000; // 2^72 - const TWO_POW_73: u256 = 0x2000000000000000000; // 2^73 - const TWO_POW_74: u256 = 0x4000000000000000000; // 2^74 - const TWO_POW_75: u256 = 0x8000000000000000000; // 2^75 - const TWO_POW_76: u256 = 0x10000000000000000000; // 2^76 - const TWO_POW_77: u256 = 0x20000000000000000000; // 2^77 - const TWO_POW_78: u256 = 0x40000000000000000000; // 2^78 - const TWO_POW_79: u256 = 0x80000000000000000000; // 2^79 - const TWO_POW_80: u256 = 0x100000000000000000000; // 2^80 - const TWO_POW_81: u256 = 0x200000000000000000000; // 2^81 - const TWO_POW_82: u256 = 0x400000000000000000000; // 2^82 - const TWO_POW_83: u256 = 0x800000000000000000000; // 2^83 - const TWO_POW_84: u256 = 0x1000000000000000000000; // 2^84 - const TWO_POW_85: u256 = 0x2000000000000000000000; // 2^85 - const TWO_POW_86: u256 = 0x4000000000000000000000; // 2^86 - const TWO_POW_87: u256 = 0x8000000000000000000000; // 2^87 - const TWO_POW_88: u256 = 0x10000000000000000000000; // 2^88 - const TWO_POW_89: u256 = 0x20000000000000000000000; // 2^89 - const TWO_POW_90: u256 = 0x40000000000000000000000; // 2^90 - const TWO_POW_91: u256 = 0x80000000000000000000000; // 2^91 - const TWO_POW_92: u256 = 0x100000000000000000000000; // 2^92 - const TWO_POW_93: u256 = 0x200000000000000000000000; // 2^93 - const TWO_POW_94: u256 = 0x400000000000000000000000; // 2^94 - const TWO_POW_95: u256 = 0x800000000000000000000000; // 2^95 - const TWO_POW_96: u256 = 0x1000000000000000000000000; // 2^96 - const TWO_POW_97: u256 = 0x2000000000000000000000000; // 2^97 - const TWO_POW_98: u256 = 0x4000000000000000000000000; // 2^98 - const TWO_POW_99: u256 = 0x8000000000000000000000000; // 2^99 - const TWO_POW_100: u256 = 0x10000000000000000000000000; // 2^100 - const TWO_POW_101: u256 = 0x20000000000000000000000000; // 2^101 - const TWO_POW_102: u256 = 0x40000000000000000000000000; // 2^102 - const TWO_POW_103: u256 = 0x80000000000000000000000000; // 2^103 - const TWO_POW_104: u256 = 0x100000000000000000000000000; // 2^104 - const TWO_POW_105: u256 = 0x200000000000000000000000000; // 2^105 - const TWO_POW_106: u256 = 0x400000000000000000000000000; // 2^106 - const TWO_POW_107: u256 = 0x800000000000000000000000000; // 2^107 - const TWO_POW_108: u256 = 0x1000000000000000000000000000; // 2^108 - const TWO_POW_109: u256 = 0x2000000000000000000000000000; // 2^109 - const TWO_POW_110: u256 = 0x4000000000000000000000000000; // 2^110 - const TWO_POW_111: u256 = 0x8000000000000000000000000000; // 2^111 - const TWO_POW_112: u256 = 0x10000000000000000000000000000; // 2^112 - const TWO_POW_113: u256 = 0x20000000000000000000000000000; // 2^113 - const TWO_POW_114: u256 = 0x40000000000000000000000000000; // 2^114 - const TWO_POW_115: u256 = 0x80000000000000000000000000000; // 2^115 - const TWO_POW_116: u256 = 0x100000000000000000000000000000; // 2^116 - const TWO_POW_117: u256 = 0x200000000000000000000000000000; // 2^117 - const TWO_POW_118: u256 = 0x400000000000000000000000000000; // 2^118 - const TWO_POW_119: u256 = 0x800000000000000000000000000000; // 2^119 - const TWO_POW_120: u256 = 0x1000000000000000000000000000000; // 2^120 - const TWO_POW_121: u256 = 0x2000000000000000000000000000000; // 2^121 - const TWO_POW_122: u256 = 0x4000000000000000000000000000000; // 2^122 - const TWO_POW_123: u256 = 0x8000000000000000000000000000000; // 2^123 - const TWO_POW_124: u256 = 0x10000000000000000000000000000000; // 2^124 - const TWO_POW_125: u256 = 0x20000000000000000000000000000000; // 2^125 - const TWO_POW_126: u256 = 0x40000000000000000000000000000000; // 2^126 - const TWO_POW_127: u256 = 0x80000000000000000000000000000000; // 2^127 - const TWO_POW_128: u256 = 0x100000000000000000000000000000000; // 2^128 - const TWO_POW_129: u256 = 0x200000000000000000000000000000000; // 2^129 - const TWO_POW_130: u256 = 0x400000000000000000000000000000000; // 2^130 - const TWO_POW_131: u256 = 0x800000000000000000000000000000000; // 2^131 - const TWO_POW_132: u256 = 0x1000000000000000000000000000000000; // 2^132 - const TWO_POW_133: u256 = 0x2000000000000000000000000000000000; // 2^133 - const TWO_POW_134: u256 = 0x4000000000000000000000000000000000; // 2^134 - const TWO_POW_135: u256 = 0x8000000000000000000000000000000000; // 2^135 - const TWO_POW_136: u256 = 0x10000000000000000000000000000000000; // 2^136 - const TWO_POW_137: u256 = 0x20000000000000000000000000000000000; // 2^137 - const TWO_POW_138: u256 = 0x40000000000000000000000000000000000; // 2^138 - const TWO_POW_139: u256 = 0x80000000000000000000000000000000000; // 2^139 - const TWO_POW_140: u256 = 0x100000000000000000000000000000000000; // 2^140 - const TWO_POW_141: u256 = 0x200000000000000000000000000000000000; // 2^141 - const TWO_POW_142: u256 = 0x400000000000000000000000000000000000; // 2^142 - const TWO_POW_143: u256 = 0x800000000000000000000000000000000000; // 2^143 - const TWO_POW_144: u256 = 0x1000000000000000000000000000000000000; // 2^144 - const TWO_POW_145: u256 = 0x2000000000000000000000000000000000000; // 2^145 - const TWO_POW_146: u256 = 0x4000000000000000000000000000000000000; // 2^146 - const TWO_POW_147: u256 = 0x8000000000000000000000000000000000000; // 2^147 - const TWO_POW_148: u256 = 0x10000000000000000000000000000000000000; // 2^148 - const TWO_POW_149: u256 = 0x20000000000000000000000000000000000000; // 2^149 - const TWO_POW_150: u256 = 0x40000000000000000000000000000000000000; // 2^150 - const TWO_POW_151: u256 = 0x80000000000000000000000000000000000000; // 2^151 - const TWO_POW_152: u256 = 0x100000000000000000000000000000000000000; // 2^152 - const TWO_POW_153: u256 = 0x200000000000000000000000000000000000000; // 2^153 - const TWO_POW_154: u256 = 0x400000000000000000000000000000000000000; // 2^154 - const TWO_POW_155: u256 = 0x800000000000000000000000000000000000000; // 2^155 - const TWO_POW_156: u256 = 0x1000000000000000000000000000000000000000; // 2^156 - const TWO_POW_157: u256 = 0x2000000000000000000000000000000000000000; // 2^157 - const TWO_POW_158: u256 = 0x4000000000000000000000000000000000000000; // 2^158 - const TWO_POW_159: u256 = 0x8000000000000000000000000000000000000000; // 2^159 - const TWO_POW_160: u256 = 0x10000000000000000000000000000000000000000; // 2^160 - const TWO_POW_161: u256 = 0x20000000000000000000000000000000000000000; // 2^161 - const TWO_POW_162: u256 = 0x40000000000000000000000000000000000000000; // 2^162 - const TWO_POW_163: u256 = 0x80000000000000000000000000000000000000000; // 2^163 - const TWO_POW_164: u256 = 0x100000000000000000000000000000000000000000; // 2^164 - const TWO_POW_165: u256 = 0x200000000000000000000000000000000000000000; // 2^165 - const TWO_POW_166: u256 = 0x400000000000000000000000000000000000000000; // 2^166 - const TWO_POW_167: u256 = 0x800000000000000000000000000000000000000000; // 2^167 - const TWO_POW_168: u256 = 0x1000000000000000000000000000000000000000000; // 2^168 - const TWO_POW_169: u256 = 0x2000000000000000000000000000000000000000000; // 2^169 - const TWO_POW_170: u256 = 0x4000000000000000000000000000000000000000000; // 2^170 - const TWO_POW_171: u256 = 0x8000000000000000000000000000000000000000000; // 2^171 - const TWO_POW_172: u256 = 0x10000000000000000000000000000000000000000000; // 2^172 - const TWO_POW_173: u256 = 0x20000000000000000000000000000000000000000000; // 2^173 - const TWO_POW_174: u256 = 0x40000000000000000000000000000000000000000000; // 2^174 - const TWO_POW_175: u256 = 0x80000000000000000000000000000000000000000000; // 2^175 - const TWO_POW_176: u256 = 0x100000000000000000000000000000000000000000000; // 2^176 - const TWO_POW_177: u256 = 0x200000000000000000000000000000000000000000000; // 2^177 - const TWO_POW_178: u256 = 0x400000000000000000000000000000000000000000000; // 2^178 - const TWO_POW_179: u256 = 0x800000000000000000000000000000000000000000000; // 2^179 - const TWO_POW_180: u256 = 0x1000000000000000000000000000000000000000000000; // 2^180 - const TWO_POW_181: u256 = 0x2000000000000000000000000000000000000000000000; // 2^181 - const TWO_POW_182: u256 = 0x4000000000000000000000000000000000000000000000; // 2^182 - const TWO_POW_183: u256 = 0x8000000000000000000000000000000000000000000000; // 2^183 - const TWO_POW_184: u256 = 0x10000000000000000000000000000000000000000000000; // 2^184 - const TWO_POW_185: u256 = 0x20000000000000000000000000000000000000000000000; // 2^185 - const TWO_POW_186: u256 = 0x40000000000000000000000000000000000000000000000; // 2^186 - const TWO_POW_187: u256 = 0x80000000000000000000000000000000000000000000000; // 2^187 - const TWO_POW_188: u256 = 0x100000000000000000000000000000000000000000000000; // 2^188 - const TWO_POW_189: u256 = 0x200000000000000000000000000000000000000000000000; // 2^189 - const TWO_POW_190: u256 = 0x400000000000000000000000000000000000000000000000; // 2^190 - const TWO_POW_191: u256 = 0x800000000000000000000000000000000000000000000000; // 2^191 - const TWO_POW_192: u256 = 0x1000000000000000000000000000000000000000000000000; // 2^192 - const TWO_POW_193: u256 = 0x2000000000000000000000000000000000000000000000000; // 2^193 - const TWO_POW_194: u256 = 0x4000000000000000000000000000000000000000000000000; // 2^194 - const TWO_POW_195: u256 = 0x8000000000000000000000000000000000000000000000000; // 2^195 - const TWO_POW_196: u256 = 0x10000000000000000000000000000000000000000000000000; // 2^196 - const TWO_POW_197: u256 = 0x20000000000000000000000000000000000000000000000000; // 2^197 - const TWO_POW_198: u256 = 0x40000000000000000000000000000000000000000000000000; // 2^198 - const TWO_POW_199: u256 = 0x80000000000000000000000000000000000000000000000000; // 2^199 - const TWO_POW_200: u256 = 0x100000000000000000000000000000000000000000000000000; // 2^200 - const TWO_POW_201: u256 = 0x200000000000000000000000000000000000000000000000000; // 2^201 - const TWO_POW_202: u256 = 0x400000000000000000000000000000000000000000000000000; // 2^202 - const TWO_POW_203: u256 = 0x800000000000000000000000000000000000000000000000000; // 2^203 - const TWO_POW_204: u256 = 0x1000000000000000000000000000000000000000000000000000; // 2^204 - const TWO_POW_205: u256 = 0x2000000000000000000000000000000000000000000000000000; // 2^205 - const TWO_POW_206: u256 = 0x4000000000000000000000000000000000000000000000000000; // 2^206 - const TWO_POW_207: u256 = 0x8000000000000000000000000000000000000000000000000000; // 2^207 - const TWO_POW_208: u256 = 0x10000000000000000000000000000000000000000000000000000; // 2^208 - const TWO_POW_209: u256 = 0x20000000000000000000000000000000000000000000000000000; // 2^209 - const TWO_POW_210: u256 = 0x40000000000000000000000000000000000000000000000000000; // 2^210 - const TWO_POW_211: u256 = 0x80000000000000000000000000000000000000000000000000000; // 2^211 - const TWO_POW_212: u256 = 0x100000000000000000000000000000000000000000000000000000; // 2^212 - const TWO_POW_213: u256 = 0x200000000000000000000000000000000000000000000000000000; // 2^213 - const TWO_POW_214: u256 = 0x400000000000000000000000000000000000000000000000000000; // 2^214 - const TWO_POW_215: u256 = 0x800000000000000000000000000000000000000000000000000000; // 2^215 - const TWO_POW_216: u256 = 0x1000000000000000000000000000000000000000000000000000000; // 2^216 - const TWO_POW_217: u256 = 0x2000000000000000000000000000000000000000000000000000000; // 2^217 - const TWO_POW_218: u256 = 0x4000000000000000000000000000000000000000000000000000000; // 2^218 - const TWO_POW_219: u256 = 0x8000000000000000000000000000000000000000000000000000000; // 2^219 - const TWO_POW_220: u256 = 0x10000000000000000000000000000000000000000000000000000000; // 2^220 - const TWO_POW_221: u256 = 0x20000000000000000000000000000000000000000000000000000000; // 2^221 - const TWO_POW_222: u256 = 0x40000000000000000000000000000000000000000000000000000000; // 2^222 - const TWO_POW_223: u256 = 0x80000000000000000000000000000000000000000000000000000000; // 2^223 - const TWO_POW_224: u256 = 0x100000000000000000000000000000000000000000000000000000000; // 2^224 - const TWO_POW_225: u256 = 0x200000000000000000000000000000000000000000000000000000000; // 2^225 - const TWO_POW_226: u256 = 0x400000000000000000000000000000000000000000000000000000000; // 2^226 - const TWO_POW_227: u256 = 0x800000000000000000000000000000000000000000000000000000000; // 2^227 - const TWO_POW_228: u256 = 0x1000000000000000000000000000000000000000000000000000000000; // 2^228 - const TWO_POW_229: u256 = 0x2000000000000000000000000000000000000000000000000000000000; // 2^229 - const TWO_POW_230: u256 = 0x4000000000000000000000000000000000000000000000000000000000; // 2^230 - const TWO_POW_231: u256 = 0x8000000000000000000000000000000000000000000000000000000000; // 2^231 - const TWO_POW_232: u256 = - 0x10000000000000000000000000000000000000000000000000000000000; // 2^232 - const TWO_POW_233: u256 = - 0x20000000000000000000000000000000000000000000000000000000000; // 2^233 - const TWO_POW_234: u256 = - 0x40000000000000000000000000000000000000000000000000000000000; // 2^234 - const TWO_POW_235: u256 = - 0x80000000000000000000000000000000000000000000000000000000000; // 2^235 - const TWO_POW_236: u256 = - 0x100000000000000000000000000000000000000000000000000000000000; // 2^236 - const TWO_POW_237: u256 = - 0x200000000000000000000000000000000000000000000000000000000000; // 2^237 - const TWO_POW_238: u256 = - 0x400000000000000000000000000000000000000000000000000000000000; // 2^238 - const TWO_POW_239: u256 = - 0x800000000000000000000000000000000000000000000000000000000000; // 2^239 - const TWO_POW_240: u256 = - 0x1000000000000000000000000000000000000000000000000000000000000; // 2^240 - const TWO_POW_241: u256 = - 0x2000000000000000000000000000000000000000000000000000000000000; // 2^241 - const TWO_POW_242: u256 = - 0x4000000000000000000000000000000000000000000000000000000000000; // 2^242 - const TWO_POW_243: u256 = - 0x8000000000000000000000000000000000000000000000000000000000000; // 2^243 - const TWO_POW_244: u256 = - 0x10000000000000000000000000000000000000000000000000000000000000; // 2^244 - const TWO_POW_245: u256 = - 0x20000000000000000000000000000000000000000000000000000000000000; // 2^245 - const TWO_POW_246: u256 = - 0x40000000000000000000000000000000000000000000000000000000000000; // 2^246 - const TWO_POW_247: u256 = - 0x80000000000000000000000000000000000000000000000000000000000000; // 2^247 - const TWO_POW_248: u256 = - 0x100000000000000000000000000000000000000000000000000000000000000; // 2^248 - const TWO_POW_249: u256 = - 0x200000000000000000000000000000000000000000000000000000000000000; // 2^249 - const TWO_POW_250: u256 = - 0x400000000000000000000000000000000000000000000000000000000000000; // 2^250 - const TWO_POW_251: u256 = - 0x800000000000000000000000000000000000000000000000000000000000000; // 2^251 - const TWO_POW_252: u256 = - 0x1000000000000000000000000000000000000000000000000000000000000000; // 2^252 - const TWO_POW_256: u256 = - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // 2^256 -} diff --git a/contracts/pack/src/lib.cairo b/contracts/pack/src/lib.cairo deleted file mode 100644 index 5c25f5326..000000000 --- a/contracts/pack/src/lib.cairo +++ /dev/null @@ -1,2 +0,0 @@ -mod pack; -mod constants; diff --git a/contracts/pack/src/pack.cairo b/contracts/pack/src/pack.cairo deleted file mode 100644 index 48fc92002..000000000 --- a/contracts/pack/src/pack.cairo +++ /dev/null @@ -1,52 +0,0 @@ -use option::OptionTrait; -use traits::{Into, TryInto}; - -trait Packing { - fn pack(self: T) -> felt252; - fn overflow_pack_protection(self: T) -> T; - fn unpack(packed: felt252) -> T; -} - -#[inline(always)] -fn rshift_split(value: u256, bits: u256) -> (u256, u256) { - integer::U256DivRem::div_rem(value, bits.try_into().expect('0 bits')) -} - -#[cfg(test)] -mod tests { - use super::rshift_split; - use pack::constants::pow; - - #[test] - #[available_gas(81450)] - fn test_rshift_split_pass() { - let v = 0b11010101; - - let (q, r) = rshift_split(v, pow::TWO_POW_1); - assert(q == 0b1101010, 'q 1 bit'); - assert(r == 0b1, 'r 1 bit'); - - let (q, r) = rshift_split(v, pow::TWO_POW_2); - assert(q == 0b110101, 'q 2 bits'); - assert(r == 0b01, 'r 2 bits'); - - let (q, r) = rshift_split(v, pow::TWO_POW_3); - assert(q == 0b11010, 'q 3 bits'); - assert(r == 0b101, 'r 3 bits'); - - let (q, r) = rshift_split(v, pow::TWO_POW_4); - assert(q == 0b1101, 'q 4 bits'); - assert(r == 0b0101, 'r 4 bits'); - - let (q, r) = rshift_split(v, pow::TWO_POW_8); - assert(q == 0, 'q 8 bits'); - assert(r == v, 'r 8 bits'); - } - - #[test] - #[available_gas(11750)] - #[should_panic] - fn test_rshift_split_0() { - rshift_split(0b1101, 0); - } -}