Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions snapshots/BetterCPUInlineGasTest.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"Flag0_P0ForcedSwitch": "22701",
"Turn0_Lead": "104410",
"Turn1_BothAttack": "262381",
"Turn2_BothAttack": "236457",
"Turn3_BothAttack": "232481",
"Turn4_BothAttack": "232485"
"Flag0_P0ForcedSwitch": "22763",
"Turn0_Lead": "104184",
"Turn1_BothAttack": "264088",
"Turn2_BothAttack": "238164",
"Turn3_BothAttack": "234188",
"Turn4_BothAttack": "234192"
}
36 changes: 18 additions & 18 deletions snapshots/EngineGasTest.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
{
"B1_Execute": "889458",
"B1_Setup": "816408",
"B2_Execute": "645719",
"B2_Setup": "282218",
"Battle1_Execute": "449877",
"Battle1_Setup": "791633",
"Battle2_Execute": "367369",
"Battle2_Setup": "233097",
"External_Execute": "456527",
"External_Setup": "782348",
"FirstBattle": "2906000",
"Inline_Execute": "318805",
"Inline_Setup": "225023",
"B1_Execute": "889886",
"B1_Setup": "816459",
"B2_Execute": "648291",
"B2_Setup": "282290",
"Battle1_Execute": "449213",
"Battle1_Setup": "791685",
"Battle2_Execute": "368905",
"Battle2_Setup": "233149",
"External_Execute": "456719",
"External_Setup": "782400",
"FirstBattle": "2911711",
"Inline_Execute": "320015",
"Inline_Setup": "225083",
"Intermediary stuff": "44458",
"SecondBattle": "2927592",
"Setup 1": "1670484",
"Setup 2": "292493",
"Setup 3": "332770",
"ThirdBattle": "2274723"
"SecondBattle": "2936650",
"Setup 1": "1670530",
"Setup 2": "292539",
"Setup 3": "332805",
"ThirdBattle": "2282494"
}
4 changes: 2 additions & 2 deletions snapshots/EngineOptimizationTest.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"ExternalStaminaRegen": "390772",
"InlineStaminaRegen": "999942"
"ExternalStaminaRegen": "392424",
"InlineStaminaRegen": "999051"
}
12 changes: 6 additions & 6 deletions snapshots/FullyOptimizedInlineGasTest.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"Fast_Battle1": "1802444",
"Fast_Battle2": "1704099",
"Fast_Battle3": "1221705",
"Fast_Setup_1": "1321867",
"Fast_Setup_2": "216314",
"Fast_Setup_3": "212698"
"Fast_Battle1": "1867564",
"Fast_Battle2": "1777864",
"Fast_Battle3": "1288656",
"Fast_Setup_1": "1322088",
"Fast_Setup_2": "216706",
"Fast_Setup_3": "212909"
}
28 changes: 14 additions & 14 deletions snapshots/InlineEngineGasTest.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{
"B1_Execute": "870357",
"B1_Setup": "758497",
"B2_Execute": "604941",
"B2_Setup": "271670",
"Battle1_Execute": "402355",
"Battle1_Setup": "733715",
"Battle2_Execute": "318757",
"Battle2_Setup": "224451",
"FirstBattle": "2595237",
"SecondBattle": "2580140",
"Setup 1": "1612152",
"Setup 2": "318169",
"Setup 3": "314901",
"ThirdBattle": "1964987"
"B1_Execute": "870101",
"B1_Setup": "758557",
"B2_Execute": "606857",
"B2_Setup": "271758",
"Battle1_Execute": "401230",
"Battle1_Setup": "733775",
"Battle2_Execute": "319832",
"Battle2_Setup": "224511",
"FirstBattle": "2595770",
"SecondBattle": "2583418",
"Setup 1": "1612191",
"Setup 2": "318239",
"Setup 3": "314704",
"ThirdBattle": "1967495"
}
6 changes: 3 additions & 3 deletions snapshots/MatchmakerTest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"Accept1": "307765",
"Accept2": "34130",
"Propose1": "197286"
"Accept1": "307809",
"Accept2": "34162",
"Propose1": "197318"
}
6 changes: 3 additions & 3 deletions src/DefaultValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ contract DefaultValidator is IValidator {
bytes32 battleKey,
uint256 moveIndex,
uint256 playerIndex,
uint240 extraData
uint16 extraData
) public view returns (bool) {
BattleContext memory ctx = ENGINE.getBattleContext(battleKey);
uint256 activeMonIndex = (playerIndex == 0) ? ctx.p0ActiveMonIndex : ctx.p1ActiveMonIndex;
Expand All @@ -127,7 +127,7 @@ contract DefaultValidator is IValidator {
}

// Validates that you can't switch to the same mon, you have enough stamina, the move isn't disabled, etc.
function validatePlayerMove(bytes32 battleKey, uint256 moveIndex, uint256 playerIndex, uint240 extraData)
function validatePlayerMove(bytes32 battleKey, uint256 moveIndex, uint256 playerIndex, uint16 extraData)
external
view
returns (bool)
Expand Down Expand Up @@ -191,7 +191,7 @@ contract DefaultValidator is IValidator {
bytes32 battleKey,
uint256 moveIndex,
uint256 playerIndex,
uint240 extraData,
uint16 extraData,
uint256 activeMonIndex,
ValidationContext memory vctx
) internal view returns (bool) {
Expand Down
42 changes: 21 additions & 21 deletions src/Engine.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ contract Engine is IEngine, MappingAllocator {
// A non-zero encoded move is the "transient is populated for this call" signal.
uint256 private transient _turnP0MoveEncoded;
uint256 private transient _turnP1MoveEncoded;
bytes32 private transient _turnP0Salt;
bytes32 private transient _turnP1Salt;
uint104 private transient _turnP0Salt;
uint104 private transient _turnP1Salt;

// Errors
error NoWriteAllowed();
Expand All @@ -65,7 +65,7 @@ contract Engine is IEngine, MappingAllocator {
// Events
event BattleStart(bytes32 indexed battleKey, address p0, address p1);
event MonMove(
bytes32 indexed battleKey, uint256 packedPlayerIndexMonIndex, uint256 packedMoveIndexExtraData, bytes32 salt
bytes32 indexed battleKey, uint256 packedPlayerIndexMonIndex, uint256 packedMoveIndexExtraData, uint104 salt
);
event EngineExecute(bytes32 indexed battleKey);
event BattleComplete(bytes32 indexed battleKey, address winner);
Expand Down Expand Up @@ -300,11 +300,11 @@ contract Engine is IEngine, MappingAllocator {
function executeWithMoves(
bytes32 battleKey,
uint8 p0MoveIndex,
bytes32 p0Salt,
uint240 p0ExtraData,
uint104 p0Salt,
uint16 p0ExtraData,
uint8 p1MoveIndex,
bytes32 p1Salt,
uint240 p1ExtraData
uint104 p1Salt,
uint16 p1ExtraData
) external {
bytes32 storageKey = _getStorageKey(battleKey);
storageKeyForWrite = storageKey;
Expand All @@ -329,7 +329,7 @@ contract Engine is IEngine, MappingAllocator {

/// @notice Combined single-player setMove + execute for forced switch turns
/// @dev Only callable by moveManager. The acting player is inferred from battle.playerSwitchForTurnFlag.
function executeWithSingleMove(bytes32 battleKey, uint8 moveIndex, bytes32 salt, uint240 extraData) external {
function executeWithSingleMove(bytes32 battleKey, uint8 moveIndex, uint104 salt, uint16 extraData) external {
bytes32 storageKey = _getStorageKey(battleKey);
storageKeyForWrite = storageKey;

Expand Down Expand Up @@ -358,12 +358,12 @@ contract Engine is IEngine, MappingAllocator {
_executeInternal(battleKey, storageKey);
}

/// @dev Decodes a transient-encoded move (layout: [extraData:240 | packedMoveIndex:8]) into a
/// @dev Decodes a transient-encoded move (layout: [extraData:16 | packedMoveIndex:8]) into a
/// MoveDecision. Encoded == 0 means "no current turn move" since packedMoveIndex always has
/// IS_REAL_TURN_BIT set for a real move.
function _decodeMove(uint256 encoded) private pure returns (MoveDecision memory m) {
m.packedMoveIndex = uint8(encoded & 0xFF);
m.extraData = uint240(encoded >> 8);
m.extraData = uint16(encoded >> 8);
}

/// @dev Returns the current turn's MoveDecision for `playerIndex`. During an active
Expand All @@ -381,7 +381,7 @@ contract Engine is IEngine, MappingAllocator {
}

/// @dev Salt companion to `_getCurrentTurnMove`.
function _getCurrentTurnSalt(BattleConfig storage config, uint256 playerIndex) internal view returns (bytes32) {
function _getCurrentTurnSalt(BattleConfig storage config, uint256 playerIndex) internal view returns (uint104) {
uint256 encoded = playerIndex == 0 ? _turnP0MoveEncoded : _turnP1MoveEncoded;
if (encoded != 0) {
return playerIndex == 0 ? _turnP0Salt : _turnP1Salt;
Expand Down Expand Up @@ -481,12 +481,12 @@ contract Engine is IEngine, MappingAllocator {
// Update the temporary RNG to the newest value
// Inline RNG computation when oracle is address(0) to avoid external call
uint256 rng;
bytes32 p0TurnSalt = _getCurrentTurnSalt(config, 0);
bytes32 p1TurnSalt = _getCurrentTurnSalt(config, 1);
uint104 p0TurnSalt = _getCurrentTurnSalt(config, 0);
uint104 p1TurnSalt = _getCurrentTurnSalt(config, 1);
if (address(config.rngOracle) == address(0)) {
rng = uint256(keccak256(abi.encode(p0TurnSalt, p1TurnSalt)));
} else {
rng = config.rngOracle.getRNG(p0TurnSalt, p1TurnSalt);
rng = config.rngOracle.getRNG(bytes32(uint256(p0TurnSalt)), bytes32(uint256(p1TurnSalt)));
}
tempRNG = rng;

Expand Down Expand Up @@ -730,8 +730,8 @@ contract Engine is IEngine, MappingAllocator {
function resetCallContext() external {
_turnP0MoveEncoded = 0;
_turnP1MoveEncoded = 0;
_turnP0Salt = bytes32(0);
_turnP1Salt = bytes32(0);
_turnP0Salt = 0;
_turnP1Salt = 0;
}

function end(bytes32 battleKey) external {
Expand Down Expand Up @@ -1377,8 +1377,8 @@ contract Engine is IEngine, MappingAllocator {
BattleConfig storage config,
uint256 playerIndex,
uint8 moveIndex,
bytes32 salt,
uint240 extraData
uint104 salt,
uint16 extraData
) internal {
// Pack moveIndex with isRealTurn bit and apply +1 offset for regular moves
// Regular moves (< SWITCH_MOVE_INDEX) are stored as moveIndex + 1 to avoid zero ambiguity
Expand All @@ -1395,7 +1395,7 @@ contract Engine is IEngine, MappingAllocator {
}
}

function setMove(bytes32 battleKey, uint256 playerIndex, uint8 moveIndex, bytes32 salt, uint240 extraData)
function setMove(bytes32 battleKey, uint256 playerIndex, uint8 moveIndex, uint104 salt, uint16 extraData)
external
{
bool isInsideExecute = _turnP0MoveEncoded != 0 || _turnP1MoveEncoded != 0;
Expand Down Expand Up @@ -1565,7 +1565,7 @@ contract Engine is IEngine, MappingAllocator {
// check below silently no-ops and timeout handles the stuck player.
if ((battle.turnId == 0 || currentMonState.isKnockedOut) && moveIndex != SWITCH_MOVE_INDEX) {
moveIndex = SWITCH_MOVE_INDEX;
move.extraData = uint240(0);
move.extraData = uint16(0);
}

// Handle a switch, no-op, or regular move.
Expand Down Expand Up @@ -2391,7 +2391,7 @@ contract Engine is IEngine, MappingAllocator {

/// @notice Validates a player move, handling both inline validation (when validator is address(0)) and external validators
/// @dev This allows callers like CPU to validate moves without needing to handle the address(0) case themselves
function validatePlayerMoveForBattle(bytes32 battleKey, uint256 moveIndex, uint256 playerIndex, uint240 extraData)
function validatePlayerMoveForBattle(bytes32 battleKey, uint256 moveIndex, uint256 playerIndex, uint16 extraData)
external
returns (bool)
{
Expand Down
14 changes: 7 additions & 7 deletions src/IEngine.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,18 @@ interface IEngine {
uint256 rng
) external returns (int32 damage, bytes32 eventType);
function switchActiveMon(uint256 playerIndex, uint256 monToSwitchIndex) external;
function setMove(bytes32 battleKey, uint256 playerIndex, uint8 moveIndex, bytes32 salt, uint240 extraData) external;
function setMove(bytes32 battleKey, uint256 playerIndex, uint8 moveIndex, uint104 salt, uint16 extraData) external;
function execute(bytes32 battleKey) external;
function executeWithMoves(
bytes32 battleKey,
uint8 p0MoveIndex,
bytes32 p0Salt,
uint240 p0ExtraData,
uint104 p0Salt,
uint16 p0ExtraData,
uint8 p1MoveIndex,
bytes32 p1Salt,
uint240 p1ExtraData
uint104 p1Salt,
uint16 p1ExtraData
) external;
function executeWithSingleMove(bytes32 battleKey, uint8 moveIndex, bytes32 salt, uint240 extraData) external;
function executeWithSingleMove(bytes32 battleKey, uint8 moveIndex, uint104 salt, uint16 extraData) external;
function resetCallContext() external;

// Getters
Expand Down Expand Up @@ -94,7 +94,7 @@ interface IEngine {
function getPlayerSwitchForTurnFlagForBattleState(bytes32 battleKey) external view returns (uint256);
function getGlobalKV(bytes32 battleKey, uint64 key) external view returns (uint192);
function getBattleValidator(bytes32 battleKey) external view returns (IValidator);
function validatePlayerMoveForBattle(bytes32 battleKey, uint256 moveIndex, uint256 playerIndex, uint240 extraData)
function validatePlayerMoveForBattle(bytes32 battleKey, uint256 moveIndex, uint256 playerIndex, uint16 extraData)
external
returns (bool);
function getEffects(bytes32 battleKey, uint256 targetIndex, uint256 monIndex)
Expand Down
4 changes: 2 additions & 2 deletions src/IValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface IValidator {
) external returns (bool);

// Validates that you can't switch to the same mon, you have enough stamina, the move isn't disabled, etc.
function validatePlayerMove(bytes32 battleKey, uint256 moveIndex, uint256 playerIndex, uint240 extraData)
function validatePlayerMove(bytes32 battleKey, uint256 moveIndex, uint256 playerIndex, uint16 extraData)
external
returns (bool);

Expand All @@ -20,7 +20,7 @@ interface IValidator {
bytes32 battleKey,
uint256 moveIndex,
uint256 playerIndex,
uint240 extraData
uint16 extraData
) external returns (bool);

// Validates that a switch is valid
Expand Down
16 changes: 8 additions & 8 deletions src/Structs.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ struct Battle {
IEngineHook[] engineHooks;
}

// Packed into 1 storage slot (8 + 240 = 248 bits)
// Packed into 1 storage slot (8 + 16 = 24 bits)
// packedMoveIndex: lower 7 bits = moveIndex (0-127), bit 7 = isRealTurn (1 = real, 0 = not set)
struct MoveDecision {
uint8 packedMoveIndex;
uint240 extraData;
uint16 extraData;
}

// Stored by the Engine, tracks immutable battle data and battle state
Expand Down Expand Up @@ -81,8 +81,8 @@ struct BattleConfig {
uint40 startTimestamp; // 40 — battle start time; overflows in year ~36825 (shrunk from uint48 for slot-2 packing)
bool hasInlineStaminaRegen; // 8
uint8 globalKVCount; // 8 — live entry count in the current battle's globalKV key buffer
bytes32 p0Salt;
bytes32 p1Salt;
uint104 p0Salt;
uint104 p1Salt;
MoveDecision p0Move;
MoveDecision p1Move;
mapping(uint256 index => Mon) p0Team;
Expand Down Expand Up @@ -118,8 +118,8 @@ struct BattleConfigView {
uint96 packedP1EffectsCount;
uint8 teamSizes;
uint40 startTimestamp; // Needed client-side for the getGlobalKV freshness gate
bytes32 p0Salt;
bytes32 p1Salt;
uint104 p0Salt;
uint104 p1Salt;
MoveDecision p0Move;
MoveDecision p1Move;
EffectInstance[] globalEffects;
Expand Down Expand Up @@ -185,8 +185,8 @@ struct PlayerDecisionData {

struct RevealedMove {
uint8 moveIndex;
uint240 extraData;
bytes32 salt;
uint16 extraData;
uint104 salt;
}

// Used for StatBoosts
Expand Down
2 changes: 1 addition & 1 deletion src/commit-manager/DefaultCommitManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ contract DefaultCommitManager is ICommitManager {
emit MoveCommit(battleKey, caller);
}

function revealMove(bytes32 battleKey, uint8 moveIndex, bytes32 salt, uint240 extraData, bool autoExecute)
function revealMove(bytes32 battleKey, uint8 moveIndex, uint104 salt, uint16 extraData, bool autoExecute)
external
{
// Get all battle context in one call
Expand Down
Loading
Loading