Skip to content

Commit

Permalink
refactor: rename startIndex to startByteIndex
Browse files Browse the repository at this point in the history
  • Loading branch information
dk1a committed Mar 28, 2023
1 parent de86274 commit 00a4151
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 26 deletions.
2 changes: 1 addition & 1 deletion packages/store/src/IStore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ interface IStore {
uint256 table,
bytes32[] calldata key,
uint8 schemaIndex,
uint256 startIndex,
uint256 startByteIndex,
bytes calldata dataToSet
) external;

Expand Down
22 changes: 11 additions & 11 deletions packages/store/src/StoreCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ library StoreCore {
uint256 tableId,
bytes32[] memory key,
uint8 schemaIndex,
uint256 startIndex,
uint256 startByteIndex,
bytes memory dataToSet
) internal {
Schema schema = getSchema(tableId);
Expand All @@ -309,18 +309,18 @@ library StoreCore {
}
// index must be checked because it could be arbitrarily large
// (but dataToSet.length can be unchecked - it won't overflow into another slot due to gas costs and hashed slots)
if (startIndex > type(uint16).max) {
revert StoreCore_DataIndexOverflow(type(uint16).max, startIndex);
if (startByteIndex > type(uint16).max) {
revert StoreCore_DataIndexOverflow(type(uint16).max, startByteIndex);
}

// TODO add setItem-specific event and hook to avoid the storage read? (https://github.com/latticexyz/mud/issues/444)
bytes memory fullData;
{
bytes memory oldData = StoreCoreInternal._getDynamicField(tableId, key, schemaIndex, schema);
fullData = abi.encodePacked(
SliceLib.getSubslice(oldData, 0, startIndex).toBytes(),
SliceLib.getSubslice(oldData, 0, startByteIndex).toBytes(),
dataToSet,
SliceLib.getSubslice(oldData, startIndex + dataToSet.length, oldData.length).toBytes()
SliceLib.getSubslice(oldData, startByteIndex + dataToSet.length, oldData.length).toBytes()
);
}

Expand All @@ -334,7 +334,7 @@ library StoreCore {
hook.onBeforeSetField(tableId, key, schemaIndex, fullData);
}

StoreCoreInternal._setDynamicFieldItem(tableId, key, schema, schemaIndex, startIndex, dataToSet);
StoreCoreInternal._setDynamicFieldItem(tableId, key, schema, schemaIndex, startByteIndex, dataToSet);

// Call onAfterSetField hooks (after modifying the state)
for (uint256 i; i < hooks.length; i++) {
Expand Down Expand Up @@ -541,13 +541,13 @@ library StoreCoreInternal {
bytes32[] memory key,
Schema schema,
uint8 schemaIndex,
uint256 startIndex,
uint256 startByteIndex,
bytes memory dataToSet
) internal {
uint8 dynamicSchemaIndex = schemaIndex - schema.numStaticFields();

// Set `dataToSet` at the given index
_setPartialDynamicData(tableId, key, dynamicSchemaIndex, startIndex, dataToSet);
_setPartialDynamicData(tableId, key, dynamicSchemaIndex, startByteIndex, dataToSet);
}

/************************************************************************
Expand Down Expand Up @@ -698,14 +698,14 @@ library StoreCoreInternal {
uint256 tableId,
bytes32[] memory key,
uint8 dynamicSchemaIndex,
uint256 startIndex,
uint256 startByteIndex,
bytes memory partialData
) internal {
uint256 dynamicDataLocation = _getDynamicDataLocation(tableId, key, dynamicSchemaIndex);
// start index is in bytes, whereas storage slots are in 32-byte words
dynamicDataLocation += startIndex / 32;
dynamicDataLocation += startByteIndex / 32;
// partial storage slot offset (there is no inherent offset, as each dynamic field starts at its own storage slot)
uint256 offset = startIndex % 32;
uint256 offset = startByteIndex % 32;
Storage.store({ storagePointer: dynamicDataLocation, offset: offset, data: partialData });
}
}
Expand Down
6 changes: 3 additions & 3 deletions packages/store/src/StoreSwitch.sol
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,13 @@ library StoreSwitch {
uint256 table,
bytes32[] memory key,
uint8 fieldIndex,
uint256 startIndex,
uint256 startByteIndex,
bytes memory dataToSet
) internal {
if (isDelegateCall()) {
StoreCore.updateInField(table, key, fieldIndex, startIndex, dataToSet);
StoreCore.updateInField(table, key, fieldIndex, startByteIndex, dataToSet);
} else {
IStore(msg.sender).updateInField(table, key, fieldIndex, startIndex, dataToSet);
IStore(msg.sender).updateInField(table, key, fieldIndex, startByteIndex, dataToSet);
}
}

Expand Down
6 changes: 3 additions & 3 deletions packages/store/test/StoreCore.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ contract StoreCoreTest is Test, StoreView {
uint256 table,
bytes32[] calldata key,
uint8 schemaIndex,
uint256 startIndex,
uint256 startByteIndex,
bytes calldata dataToSet
) public override {
StoreCore.updateInField(table, key, schemaIndex, startIndex, dataToSet);
StoreCore.updateInField(table, key, schemaIndex, startByteIndex, dataToSet);
}

// Expose an external deleteRecord function for testing purposes of indexers (see testHooks)
Expand Down Expand Up @@ -774,7 +774,7 @@ contract StoreCoreTest is Test, StoreView {
assertEq(bytes32(StoreCore.getField(table, key, 0)), firstDataBytes);
assertEq(StoreCore.getField(table, key, 1), newSecondDataBytes);

// startIndex must not overflow
// startByteIndex must not overflow
vm.expectRevert(
abi.encodeWithSelector(StoreCore.StoreCore_DataIndexOverflow.selector, type(uint16).max, type(uint32).max)
);
Expand Down
19 changes: 13 additions & 6 deletions packages/world/src/World.sol
Original file line number Diff line number Diff line change
Expand Up @@ -164,22 +164,22 @@ contract World is Store, IWorldCore, IErrors {
}

/**
* Update data at `startIndex` of a field in the table at the given namespace and file.
* Update data at `startByteIndex` of a field in the table at the given namespace and file.
* Requires the caller to have access to the namespace or file.
*/
function updateInField(
bytes16 namespace,
bytes16 file,
bytes32[] calldata key,
uint8 schemaIndex,
uint256 startIndex,
uint256 startByteIndex,
bytes calldata dataToSet
) public virtual {
// Require access to namespace or file
bytes32 resourceSelector = AccessControl.requireAccess(namespace, file, msg.sender);

// Update data in the field
StoreCore.updateInField(resourceSelector.toTableId(), key, schemaIndex, startIndex, dataToSet);
StoreCore.updateInField(resourceSelector.toTableId(), key, schemaIndex, startByteIndex, dataToSet);
}

/**
Expand Down Expand Up @@ -314,19 +314,26 @@ contract World is Store, IWorldCore, IErrors {
}

/**
* Update data at `startIndex` of a field in the table at the given tableId.
* Update data at `startByteIndex` of a field in the table at the given tableId.
* This overload exists to conform with the `IStore` interface.
* The tableId is converted to a resourceSelector, and access is checked based on the namespace or file.
*/
function updateInField(
uint256 tableId,
bytes32[] calldata key,
uint8 schemaIndex,
uint256 startIndex,
uint256 startByteIndex,
bytes calldata dataToSet
) public virtual {
bytes32 resourceSelector = ResourceSelector.from(tableId);
updateInField(resourceSelector.getNamespace(), resourceSelector.getFile(), key, schemaIndex, startIndex, dataToSet);
updateInField(
resourceSelector.getNamespace(),
resourceSelector.getFile(),
key,
schemaIndex,
startByteIndex,
dataToSet
);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/world/src/interfaces/IWorldCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,15 @@ interface IWorldCore {
) external;

/**
* Update data at `startIndex` of a field in the table at the given namespace and file.
* Update data at `startByteIndex` of a field in the table at the given namespace and file.
* Requires the caller to have access to the namespace or file.
*/
function updateInField(
bytes16 namespace,
bytes16 file,
bytes32[] calldata key,
uint8 schemaIndex,
uint256 startIndex,
uint256 startByteIndex,
bytes calldata dataToSet
) external;

Expand Down

0 comments on commit 00a4151

Please sign in to comment.