diff --git a/packages/cli/contracts/src/tables/Dynamics.sol b/packages/cli/contracts/src/tables/Dynamics.sol new file mode 100644 index 0000000000..1241dc712b --- /dev/null +++ b/packages/cli/contracts/src/tables/Dynamics.sol @@ -0,0 +1,500 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +/* Autogenerated file. Do not edit manually. */ + +// Import schema type +import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol"; + +// Import store internals +import { IStore } from "@latticexyz/store/src/IStore.sol"; +import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; +import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; +import { Bytes } from "@latticexyz/store/src/Bytes.sol"; +import { Memory } from "@latticexyz/store/src/Memory.sol"; +import { SliceLib } from "@latticexyz/store/src/Slice.sol"; +import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; +import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; +import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; + +uint256 constant _tableId = uint256(bytes32(abi.encodePacked(bytes16(""), bytes16("Dynamics")))); +uint256 constant DynamicsTableId = _tableId; + +struct DynamicsData { + bytes32[1] staticB32; + int32[2] staticI32; + uint128[3] staticU128; + address[4] staticAddrs; + bool[5] staticBools; + uint64[] u64; + string str; + bytes b; +} + +library Dynamics { + /** Get the table's schema */ + function getSchema() internal pure returns (Schema) { + SchemaType[] memory _schema = new SchemaType[](8); + _schema[0] = SchemaType.BYTES32_ARRAY; + _schema[1] = SchemaType.INT32_ARRAY; + _schema[2] = SchemaType.UINT128_ARRAY; + _schema[3] = SchemaType.ADDRESS_ARRAY; + _schema[4] = SchemaType.BOOL_ARRAY; + _schema[5] = SchemaType.UINT64_ARRAY; + _schema[6] = SchemaType.STRING; + _schema[7] = SchemaType.BYTES; + + return SchemaLib.encode(_schema); + } + + function getKeySchema() internal pure returns (Schema) { + SchemaType[] memory _schema = new SchemaType[](1); + _schema[0] = SchemaType.BYTES32; + + return SchemaLib.encode(_schema); + } + + /** Get the table's metadata */ + function getMetadata() internal pure returns (string memory, string[] memory) { + string[] memory _fieldNames = new string[](8); + _fieldNames[0] = "staticB32"; + _fieldNames[1] = "staticI32"; + _fieldNames[2] = "staticU128"; + _fieldNames[3] = "staticAddrs"; + _fieldNames[4] = "staticBools"; + _fieldNames[5] = "u64"; + _fieldNames[6] = "str"; + _fieldNames[7] = "b"; + return ("Dynamics", _fieldNames); + } + + /** Register the table's schema */ + function registerSchema() internal { + StoreSwitch.registerSchema(_tableId, getSchema(), getKeySchema()); + } + + /** Set the table's metadata */ + function setMetadata() internal { + (string memory _tableName, string[] memory _fieldNames) = getMetadata(); + StoreSwitch.setMetadata(_tableId, _tableName, _fieldNames); + } + + /** Get staticB32 */ + function getStaticB32(bytes32 key) internal view returns (bytes32[1] memory staticB32) { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 0); + return toStaticArray_bytes32_1(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bytes32()); + } + + /** Set staticB32 */ + function setStaticB32(bytes32 key, bytes32[1] memory staticB32) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.setField(_tableId, _primaryKeys, 0, EncodeArray.encode(fromStaticArray_bytes32_1(staticB32))); + } + + /** Push an element to staticB32 */ + function pushStaticB32(bytes32 key, bytes32 _element) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.pushToField(_tableId, _primaryKeys, 0, abi.encodePacked((_element))); + } + + /** Get staticI32 */ + function getStaticI32(bytes32 key) internal view returns (int32[2] memory staticI32) { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 1); + return toStaticArray_int32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_int32()); + } + + /** Set staticI32 */ + function setStaticI32(bytes32 key, int32[2] memory staticI32) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.setField(_tableId, _primaryKeys, 1, EncodeArray.encode(fromStaticArray_int32_2(staticI32))); + } + + /** Push an element to staticI32 */ + function pushStaticI32(bytes32 key, int32 _element) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.pushToField(_tableId, _primaryKeys, 1, abi.encodePacked((_element))); + } + + /** Get staticU128 */ + function getStaticU128(bytes32 key) internal view returns (uint128[3] memory staticU128) { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 2); + return toStaticArray_uint128_3(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint128()); + } + + /** Set staticU128 */ + function setStaticU128(bytes32 key, uint128[3] memory staticU128) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.setField(_tableId, _primaryKeys, 2, EncodeArray.encode(fromStaticArray_uint128_3(staticU128))); + } + + /** Push an element to staticU128 */ + function pushStaticU128(bytes32 key, uint128 _element) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.pushToField(_tableId, _primaryKeys, 2, abi.encodePacked((_element))); + } + + /** Get staticAddrs */ + function getStaticAddrs(bytes32 key) internal view returns (address[4] memory staticAddrs) { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 3); + return toStaticArray_address_4(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_address()); + } + + /** Set staticAddrs */ + function setStaticAddrs(bytes32 key, address[4] memory staticAddrs) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.setField(_tableId, _primaryKeys, 3, EncodeArray.encode(fromStaticArray_address_4(staticAddrs))); + } + + /** Push an element to staticAddrs */ + function pushStaticAddrs(bytes32 key, address _element) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.pushToField(_tableId, _primaryKeys, 3, abi.encodePacked((_element))); + } + + /** Get staticBools */ + function getStaticBools(bytes32 key) internal view returns (bool[5] memory staticBools) { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 4); + return toStaticArray_bool_5(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_bool()); + } + + /** Set staticBools */ + function setStaticBools(bytes32 key, bool[5] memory staticBools) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.setField(_tableId, _primaryKeys, 4, EncodeArray.encode(fromStaticArray_bool_5(staticBools))); + } + + /** Push an element to staticBools */ + function pushStaticBools(bytes32 key, bool _element) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.pushToField(_tableId, _primaryKeys, 4, abi.encodePacked((_element))); + } + + /** Get u64 */ + function getU64(bytes32 key) internal view returns (uint64[] memory u64) { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 5); + return (SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint64()); + } + + /** Set u64 */ + function setU64(bytes32 key, uint64[] memory u64) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.setField(_tableId, _primaryKeys, 5, EncodeArray.encode((u64))); + } + + /** Push an element to u64 */ + function pushU64(bytes32 key, uint64 _element) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.pushToField(_tableId, _primaryKeys, 5, abi.encodePacked((_element))); + } + + /** Get str */ + function getStr(bytes32 key) internal view returns (string memory str) { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 6); + return (string(_blob)); + } + + /** Set str */ + function setStr(bytes32 key, string memory str) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.setField(_tableId, _primaryKeys, 6, bytes((str))); + } + + /** Push a slice to str */ + function pushStr(bytes32 key, string memory _slice) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.pushToField(_tableId, _primaryKeys, 6, bytes((_slice))); + } + + /** Get b */ + function getB(bytes32 key) internal view returns (bytes memory b) { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 7); + return (bytes(_blob)); + } + + /** Set b */ + function setB(bytes32 key, bytes memory b) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.setField(_tableId, _primaryKeys, 7, bytes((b))); + } + + /** Push a slice to b */ + function pushB(bytes32 key, bytes memory _slice) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.pushToField(_tableId, _primaryKeys, 7, bytes((_slice))); + } + + /** Get the full data */ + function get(bytes32 key) internal view returns (DynamicsData memory _table) { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + bytes memory _blob = StoreSwitch.getRecord(_tableId, _primaryKeys, getSchema()); + return decode(_blob); + } + + /** Set the full data using individual values */ + function set( + bytes32 key, + bytes32[1] memory staticB32, + int32[2] memory staticI32, + uint128[3] memory staticU128, + address[4] memory staticAddrs, + bool[5] memory staticBools, + uint64[] memory u64, + string memory str, + bytes memory b + ) internal { + bytes memory _data = encode(staticB32, staticI32, staticU128, staticAddrs, staticBools, u64, str, b); + + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.setRecord(_tableId, _primaryKeys, _data); + } + + /** Set the full data using the data struct */ + function set(bytes32 key, DynamicsData memory _table) internal { + set( + key, + _table.staticB32, + _table.staticI32, + _table.staticU128, + _table.staticAddrs, + _table.staticBools, + _table.u64, + _table.str, + _table.b + ); + } + + /** Decode the tightly packed blob using this table's schema */ + function decode(bytes memory _blob) internal view returns (DynamicsData memory _table) { + // 0 is the total byte length of static data + PackedCounter _encodedLengths = PackedCounter.wrap(Bytes.slice32(_blob, 0)); + + uint256 _start; + uint256 _end = 32; + + _start = _end; + _end += _encodedLengths.atIndex(0); + _table.staticB32 = toStaticArray_bytes32_1(SliceLib.getSubslice(_blob, _start, _end).decodeArray_bytes32()); + + _start = _end; + _end += _encodedLengths.atIndex(1); + _table.staticI32 = toStaticArray_int32_2(SliceLib.getSubslice(_blob, _start, _end).decodeArray_int32()); + + _start = _end; + _end += _encodedLengths.atIndex(2); + _table.staticU128 = toStaticArray_uint128_3(SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint128()); + + _start = _end; + _end += _encodedLengths.atIndex(3); + _table.staticAddrs = toStaticArray_address_4(SliceLib.getSubslice(_blob, _start, _end).decodeArray_address()); + + _start = _end; + _end += _encodedLengths.atIndex(4); + _table.staticBools = toStaticArray_bool_5(SliceLib.getSubslice(_blob, _start, _end).decodeArray_bool()); + + _start = _end; + _end += _encodedLengths.atIndex(5); + _table.u64 = (SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint64()); + + _start = _end; + _end += _encodedLengths.atIndex(6); + _table.str = (string(SliceLib.getSubslice(_blob, _start, _end).toBytes())); + + _start = _end; + _end += _encodedLengths.atIndex(7); + _table.b = (bytes(SliceLib.getSubslice(_blob, _start, _end).toBytes())); + } + + /** Tightly pack full data using this table's schema */ + function encode( + bytes32[1] memory staticB32, + int32[2] memory staticI32, + uint128[3] memory staticU128, + address[4] memory staticAddrs, + bool[5] memory staticBools, + uint64[] memory u64, + string memory str, + bytes memory b + ) internal view returns (bytes memory) { + uint16[] memory _counters = new uint16[](8); + _counters[0] = uint16(staticB32.length * 32); + _counters[1] = uint16(staticI32.length * 4); + _counters[2] = uint16(staticU128.length * 16); + _counters[3] = uint16(staticAddrs.length * 20); + _counters[4] = uint16(staticBools.length * 1); + _counters[5] = uint16(u64.length * 8); + _counters[6] = uint16(bytes(str).length); + _counters[7] = uint16(bytes(b).length); + PackedCounter _encodedLengths = PackedCounterLib.pack(_counters); + + return + abi.encodePacked( + _encodedLengths.unwrap(), + EncodeArray.encode(fromStaticArray_bytes32_1(staticB32)), + EncodeArray.encode(fromStaticArray_int32_2(staticI32)), + EncodeArray.encode(fromStaticArray_uint128_3(staticU128)), + EncodeArray.encode(fromStaticArray_address_4(staticAddrs)), + EncodeArray.encode(fromStaticArray_bool_5(staticBools)), + EncodeArray.encode((u64)), + bytes((str)), + bytes((b)) + ); + } + + /* Delete all data for given keys */ + function deleteRecord(bytes32 key) internal { + bytes32[] memory _primaryKeys = new bytes32[](1); + _primaryKeys[0] = bytes32((key)); + + StoreSwitch.deleteRecord(_tableId, _primaryKeys); + } +} + +function toStaticArray_bytes32_1(bytes32[] memory _value) pure returns (bytes32[1] memory _result) { + // in memory static arrays are just dynamic arrays without the length byte + assembly { + _result := add(_value, 0x20) + } +} + +function toStaticArray_int32_2(int32[] memory _value) pure returns (int32[2] memory _result) { + // in memory static arrays are just dynamic arrays without the length byte + assembly { + _result := add(_value, 0x20) + } +} + +function toStaticArray_uint128_3(uint128[] memory _value) pure returns (uint128[3] memory _result) { + // in memory static arrays are just dynamic arrays without the length byte + assembly { + _result := add(_value, 0x20) + } +} + +function toStaticArray_address_4(address[] memory _value) pure returns (address[4] memory _result) { + // in memory static arrays are just dynamic arrays without the length byte + assembly { + _result := add(_value, 0x20) + } +} + +function toStaticArray_bool_5(bool[] memory _value) pure returns (bool[5] memory _result) { + // in memory static arrays are just dynamic arrays without the length byte + assembly { + _result := add(_value, 0x20) + } +} + +function fromStaticArray_bytes32_1(bytes32[1] memory _value) view returns (bytes32[] memory _result) { + _result = new bytes32[](1); + uint256 fromPointer; + uint256 toPointer; + assembly { + fromPointer := _value + toPointer := add(_result, 0x20) + } + Memory.copy(fromPointer, toPointer, 32); +} + +function fromStaticArray_int32_2(int32[2] memory _value) view returns (int32[] memory _result) { + _result = new int32[](2); + uint256 fromPointer; + uint256 toPointer; + assembly { + fromPointer := _value + toPointer := add(_result, 0x20) + } + Memory.copy(fromPointer, toPointer, 64); +} + +function fromStaticArray_uint128_3(uint128[3] memory _value) view returns (uint128[] memory _result) { + _result = new uint128[](3); + uint256 fromPointer; + uint256 toPointer; + assembly { + fromPointer := _value + toPointer := add(_result, 0x20) + } + Memory.copy(fromPointer, toPointer, 96); +} + +function fromStaticArray_address_4(address[4] memory _value) view returns (address[] memory _result) { + _result = new address[](4); + uint256 fromPointer; + uint256 toPointer; + assembly { + fromPointer := _value + toPointer := add(_result, 0x20) + } + Memory.copy(fromPointer, toPointer, 128); +} + +function fromStaticArray_bool_5(bool[5] memory _value) view returns (bool[] memory _result) { + _result = new bool[](5); + uint256 fromPointer; + uint256 toPointer; + assembly { + fromPointer := _value + toPointer := add(_result, 0x20) + } + Memory.copy(fromPointer, toPointer, 160); +} diff --git a/packages/cli/contracts/src/tables/Singleton.sol b/packages/cli/contracts/src/tables/Singleton.sol new file mode 100644 index 0000000000..90c29c60aa --- /dev/null +++ b/packages/cli/contracts/src/tables/Singleton.sol @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +/* Autogenerated file. Do not edit manually. */ + +// Import schema type +import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol"; + +// Import store internals +import { IStore } from "@latticexyz/store/src/IStore.sol"; +import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; +import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; +import { Bytes } from "@latticexyz/store/src/Bytes.sol"; +import { Memory } from "@latticexyz/store/src/Memory.sol"; +import { SliceLib } from "@latticexyz/store/src/Slice.sol"; +import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; +import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; +import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCounter.sol"; + +uint256 constant _tableId = uint256(bytes32(abi.encodePacked(bytes16(""), bytes16("Singleton")))); +uint256 constant SingletonTableId = _tableId; + +library Singleton { + /** Get the table's schema */ + function getSchema() internal pure returns (Schema) { + SchemaType[] memory _schema = new SchemaType[](4); + _schema[0] = SchemaType.INT256; + _schema[1] = SchemaType.UINT32_ARRAY; + _schema[2] = SchemaType.UINT32_ARRAY; + _schema[3] = SchemaType.UINT32_ARRAY; + + return SchemaLib.encode(_schema); + } + + function getKeySchema() internal pure returns (Schema) { + SchemaType[] memory _schema = new SchemaType[](0); + + return SchemaLib.encode(_schema); + } + + /** Get the table's metadata */ + function getMetadata() internal pure returns (string memory, string[] memory) { + string[] memory _fieldNames = new string[](4); + _fieldNames[0] = "v1"; + _fieldNames[1] = "v2"; + _fieldNames[2] = "v3"; + _fieldNames[3] = "v4"; + return ("Singleton", _fieldNames); + } + + /** Register the table's schema */ + function registerSchema() internal { + StoreSwitch.registerSchema(_tableId, getSchema(), getKeySchema()); + } + + /** Set the table's metadata */ + function setMetadata() internal { + (string memory _tableName, string[] memory _fieldNames) = getMetadata(); + StoreSwitch.setMetadata(_tableId, _tableName, _fieldNames); + } + + /** Get v1 */ + function getV1() internal view returns (int256 v1) { + bytes32[] memory _primaryKeys = new bytes32[](0); + + bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 0); + return (int256(uint256(Bytes.slice32(_blob, 0)))); + } + + /** Set v1 */ + function setV1(int256 v1) internal { + bytes32[] memory _primaryKeys = new bytes32[](0); + + StoreSwitch.setField(_tableId, _primaryKeys, 0, abi.encodePacked((v1))); + } + + /** Get v2 */ + function getV2() internal view returns (uint32[2] memory v2) { + bytes32[] memory _primaryKeys = new bytes32[](0); + + bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 1); + return toStaticArray_uint32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); + } + + /** Set v2 */ + function setV2(uint32[2] memory v2) internal { + bytes32[] memory _primaryKeys = new bytes32[](0); + + StoreSwitch.setField(_tableId, _primaryKeys, 1, EncodeArray.encode(fromStaticArray_uint32_2(v2))); + } + + /** Push an element to v2 */ + function pushV2(uint32 _element) internal { + bytes32[] memory _primaryKeys = new bytes32[](0); + + StoreSwitch.pushToField(_tableId, _primaryKeys, 1, abi.encodePacked((_element))); + } + + /** Get v3 */ + function getV3() internal view returns (uint32[2] memory v3) { + bytes32[] memory _primaryKeys = new bytes32[](0); + + bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 2); + return toStaticArray_uint32_2(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); + } + + /** Set v3 */ + function setV3(uint32[2] memory v3) internal { + bytes32[] memory _primaryKeys = new bytes32[](0); + + StoreSwitch.setField(_tableId, _primaryKeys, 2, EncodeArray.encode(fromStaticArray_uint32_2(v3))); + } + + /** Push an element to v3 */ + function pushV3(uint32 _element) internal { + bytes32[] memory _primaryKeys = new bytes32[](0); + + StoreSwitch.pushToField(_tableId, _primaryKeys, 2, abi.encodePacked((_element))); + } + + /** Get v4 */ + function getV4() internal view returns (uint32[1] memory v4) { + bytes32[] memory _primaryKeys = new bytes32[](0); + + bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 3); + return toStaticArray_uint32_1(SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_uint32()); + } + + /** Set v4 */ + function setV4(uint32[1] memory v4) internal { + bytes32[] memory _primaryKeys = new bytes32[](0); + + StoreSwitch.setField(_tableId, _primaryKeys, 3, EncodeArray.encode(fromStaticArray_uint32_1(v4))); + } + + /** Push an element to v4 */ + function pushV4(uint32 _element) internal { + bytes32[] memory _primaryKeys = new bytes32[](0); + + StoreSwitch.pushToField(_tableId, _primaryKeys, 3, abi.encodePacked((_element))); + } + + /** Get the full data */ + function get() internal view returns (int256 v1, uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4) { + bytes32[] memory _primaryKeys = new bytes32[](0); + + bytes memory _blob = StoreSwitch.getRecord(_tableId, _primaryKeys, getSchema()); + return decode(_blob); + } + + /** Set the full data using individual values */ + function set(int256 v1, uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4) internal { + bytes memory _data = encode(v1, v2, v3, v4); + + bytes32[] memory _primaryKeys = new bytes32[](0); + + StoreSwitch.setRecord(_tableId, _primaryKeys, _data); + } + + /** Decode the tightly packed blob using this table's schema */ + function decode( + bytes memory _blob + ) internal view returns (int256 v1, uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4) { + // 32 is the total byte length of static data + PackedCounter _encodedLengths = PackedCounter.wrap(Bytes.slice32(_blob, 32)); + + v1 = (int256(uint256(Bytes.slice32(_blob, 0)))); + + uint256 _start; + uint256 _end = 64; + + _start = _end; + _end += _encodedLengths.atIndex(0); + v2 = toStaticArray_uint32_2(SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint32()); + + _start = _end; + _end += _encodedLengths.atIndex(1); + v3 = toStaticArray_uint32_2(SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint32()); + + _start = _end; + _end += _encodedLengths.atIndex(2); + v4 = toStaticArray_uint32_1(SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint32()); + } + + /** Tightly pack full data using this table's schema */ + function encode( + int256 v1, + uint32[2] memory v2, + uint32[2] memory v3, + uint32[1] memory v4 + ) internal view returns (bytes memory) { + uint16[] memory _counters = new uint16[](3); + _counters[0] = uint16(v2.length * 4); + _counters[1] = uint16(v3.length * 4); + _counters[2] = uint16(v4.length * 4); + PackedCounter _encodedLengths = PackedCounterLib.pack(_counters); + + return + abi.encodePacked( + v1, + _encodedLengths.unwrap(), + EncodeArray.encode(fromStaticArray_uint32_2(v2)), + EncodeArray.encode(fromStaticArray_uint32_2(v3)), + EncodeArray.encode(fromStaticArray_uint32_1(v4)) + ); + } + + /* Delete all data for given keys */ + function deleteRecord() internal { + bytes32[] memory _primaryKeys = new bytes32[](0); + + StoreSwitch.deleteRecord(_tableId, _primaryKeys); + } +} + +function toStaticArray_uint32_2(uint32[] memory _value) pure returns (uint32[2] memory _result) { + // in memory static arrays are just dynamic arrays without the length byte + assembly { + _result := add(_value, 0x20) + } +} + +function toStaticArray_uint32_1(uint32[] memory _value) pure returns (uint32[1] memory _result) { + // in memory static arrays are just dynamic arrays without the length byte + assembly { + _result := add(_value, 0x20) + } +} + +function fromStaticArray_uint32_2(uint32[2] memory _value) view returns (uint32[] memory _result) { + _result = new uint32[](2); + uint256 fromPointer; + uint256 toPointer; + assembly { + fromPointer := _value + toPointer := add(_result, 0x20) + } + Memory.copy(fromPointer, toPointer, 64); +} + +function fromStaticArray_uint32_1(uint32[1] memory _value) view returns (uint32[] memory _result) { + _result = new uint32[](1); + uint256 fromPointer; + uint256 toPointer; + assembly { + fromPointer := _value + toPointer := add(_result, 0x20) + } + Memory.copy(fromPointer, toPointer, 32); +} diff --git a/packages/cli/contracts/src/tables/Table1.sol b/packages/cli/contracts/src/tables/Statics.sol similarity index 85% rename from packages/cli/contracts/src/tables/Table1.sol rename to packages/cli/contracts/src/tables/Statics.sol index b83e2586f4..41200b231c 100644 --- a/packages/cli/contracts/src/tables/Table1.sol +++ b/packages/cli/contracts/src/tables/Statics.sol @@ -11,6 +11,7 @@ import { IStore } from "@latticexyz/store/src/IStore.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; import { Bytes } from "@latticexyz/store/src/Bytes.sol"; +import { Memory } from "@latticexyz/store/src/Memory.sol"; import { SliceLib } from "@latticexyz/store/src/Slice.sol"; import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; @@ -19,10 +20,10 @@ import { PackedCounter, PackedCounterLib } from "@latticexyz/store/src/PackedCou // Import user types import { Enum1, Enum2 } from "./../Types.sol"; -uint256 constant _tableId = uint256(bytes32(abi.encodePacked(bytes16(""), bytes16("Table1")))); -uint256 constant Table1TableId = _tableId; +uint256 constant _tableId = uint256(bytes32(abi.encodePacked(bytes16(""), bytes16("Statics")))); +uint256 constant StaticsTableId = _tableId; -struct Table1Data { +struct StaticsData { uint256 v1; int32 v2; bytes16 v3; @@ -32,7 +33,7 @@ struct Table1Data { Enum2 v7; } -library Table1 { +library Statics { /** Get the table's schema */ function getSchema() internal pure returns (Schema) { SchemaType[] memory _schema = new SchemaType[](7); @@ -70,7 +71,7 @@ library Table1 { _fieldNames[4] = "v5"; _fieldNames[5] = "v6"; _fieldNames[6] = "v7"; - return ("Table1", _fieldNames); + return ("Statics", _fieldNames); } /** Register the table's schema */ @@ -100,8 +101,8 @@ library Table1 { _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 0); return (uint256(Bytes.slice32(_blob, 0))); @@ -115,8 +116,8 @@ library Table1 { _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); StoreSwitch.setField(_tableId, _primaryKeys, 0, abi.encodePacked((v1))); } @@ -137,8 +138,8 @@ library Table1 { _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 1); return (int32(uint32(Bytes.slice4(_blob, 0)))); @@ -152,8 +153,8 @@ library Table1 { _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); StoreSwitch.setField(_tableId, _primaryKeys, 1, abi.encodePacked((v2))); } @@ -174,8 +175,8 @@ library Table1 { _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 2); return (Bytes.slice16(_blob, 0)); @@ -189,8 +190,8 @@ library Table1 { _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); StoreSwitch.setField(_tableId, _primaryKeys, 2, abi.encodePacked((v3))); } @@ -211,8 +212,8 @@ library Table1 { _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 3); return (address(Bytes.slice20(_blob, 0))); @@ -226,8 +227,8 @@ library Table1 { _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); StoreSwitch.setField(_tableId, _primaryKeys, 3, abi.encodePacked((v4))); } @@ -248,8 +249,8 @@ library Table1 { _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 4); return (_toBool(uint8(Bytes.slice1(_blob, 0)))); @@ -263,8 +264,8 @@ library Table1 { _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); StoreSwitch.setField(_tableId, _primaryKeys, 4, abi.encodePacked((v5))); } @@ -285,8 +286,8 @@ library Table1 { _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 5); return Enum1(uint8(Bytes.slice1(_blob, 0))); @@ -300,10 +301,10 @@ library Table1 { _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); - StoreSwitch.setField(_tableId, _primaryKeys, 5, abi.encodePacked(Enum1(v6))); + StoreSwitch.setField(_tableId, _primaryKeys, 5, abi.encodePacked(uint8(v6))); } /** Get v7 */ @@ -322,8 +323,8 @@ library Table1 { _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, 6); return Enum2(uint8(Bytes.slice1(_blob, 0))); @@ -337,10 +338,10 @@ library Table1 { _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); - StoreSwitch.setField(_tableId, _primaryKeys, 6, abi.encodePacked(Enum2(v7))); + StoreSwitch.setField(_tableId, _primaryKeys, 6, abi.encodePacked(uint8(v7))); } /** Get the full data */ @@ -352,15 +353,15 @@ library Table1 { bool k5, Enum1 k6, Enum2 k7 - ) internal view returns (Table1Data memory _table) { + ) internal view returns (StaticsData memory _table) { bytes32[] memory _primaryKeys = new bytes32[](7); _primaryKeys[0] = bytes32(uint256((k1))); _primaryKeys[1] = bytes32(uint256(uint32((k2)))); _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); bytes memory _blob = StoreSwitch.getRecord(_tableId, _primaryKeys, getSchema()); return decode(_blob); @@ -391,8 +392,8 @@ library Table1 { _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); StoreSwitch.setRecord(_tableId, _primaryKeys, _data); } @@ -406,13 +407,13 @@ library Table1 { bool k5, Enum1 k6, Enum2 k7, - Table1Data memory _table + StaticsData memory _table ) internal { set(k1, k2, k3, k4, k5, k6, k7, _table.v1, _table.v2, _table.v3, _table.v4, _table.v5, _table.v6, _table.v7); } /** Decode the tightly packed blob using this table's schema */ - function decode(bytes memory _blob) internal pure returns (Table1Data memory _table) { + function decode(bytes memory _blob) internal pure returns (StaticsData memory _table) { _table.v1 = (uint256(Bytes.slice32(_blob, 0))); _table.v2 = (int32(uint32(Bytes.slice4(_blob, 32)))); @@ -437,7 +438,7 @@ library Table1 { bool v5, Enum1 v6, Enum2 v7 - ) internal pure returns (bytes memory) { + ) internal view returns (bytes memory) { return abi.encodePacked(v1, v2, v3, v4, v5, v6, v7); } @@ -449,8 +450,8 @@ library Table1 { _primaryKeys[2] = bytes32((k3)); _primaryKeys[3] = bytes32(bytes20((k4))); _primaryKeys[4] = _boolToBytes32((k5)); - _primaryKeys[5] = bytes32(uint256(Enum1(k6))); - _primaryKeys[6] = bytes32(uint256(Enum2(k7))); + _primaryKeys[5] = bytes32(uint256(uint8(k6))); + _primaryKeys[6] = bytes32(uint256(uint8(k7))); StoreSwitch.deleteRecord(_tableId, _primaryKeys); } diff --git a/packages/cli/contracts/test/Tablegen.t.sol b/packages/cli/contracts/test/Tablegen.t.sol index 0f5f047f6c..96d679d965 100644 --- a/packages/cli/contracts/test/Tablegen.t.sol +++ b/packages/cli/contracts/test/Tablegen.t.sol @@ -3,12 +3,14 @@ pragma solidity >=0.8.0; import "forge-std/Test.sol"; import { StoreView } from "@latticexyz/store/src/StoreView.sol"; -import { Table1, Table1Data } from "../src/tables/Table1.sol"; +import { Statics, StaticsData } from "../src/tables/Statics.sol"; +import { Dynamics, DynamicsData } from "../src/tables/Dynamics.sol"; +import { Singleton } from "../src/tables/Singleton.sol"; import { Enum1, Enum2 } from "../src/Types.sol"; contract TablegenTest is Test, StoreView { - function testTable1SetAndGet() public { - Table1.registerSchema(); + function testStaticsSetAndGet() public { + Statics.registerSchema(); uint256 k1 = 1; int32 k2 = -1; @@ -18,11 +20,57 @@ contract TablegenTest is Test, StoreView { Enum1 k6 = Enum1.E3; Enum2 k7 = Enum2.E1; - Table1.setV1(k1, k2, k3, k4, k5, k6, k7, 4); - assertEq(Table1.getV1(k1, k2, k3, k4, k5, k6, k7), 4); + Statics.setV1(k1, k2, k3, k4, k5, k6, k7, 4); + assertEq(Statics.getV1(k1, k2, k3, k4, k5, k6, k7), 4); - Table1Data memory data = Table1Data(4, -5, hex"06", address(456), false, Enum1.E2, Enum2.E1); - Table1.set(k1, k2, k3, k4, k5, k6, k7, data); - assertEq(abi.encode(Table1.get(k1, k2, k3, k4, k5, k6, k7)), abi.encode(data)); + StaticsData memory data = StaticsData(4, -5, hex"06", address(456), false, Enum1.E2, Enum2.E1); + Statics.set(k1, k2, k3, k4, k5, k6, k7, data); + assertEq(abi.encode(Statics.get(k1, k2, k3, k4, k5, k6, k7)), abi.encode(data)); + } + + function testDynamicsSetAndGet() public { + Dynamics.registerSchema(); + + bytes32 key = keccak256("key"); + + bool[5] memory staticBools = [true, false, true, true, false]; + uint64[] memory u64 = new uint64[](5); + u64[0] = 0; + u64[1] = 1; + u64[2] = type(uint64).max / 2; + u64[3] = type(uint64).max - 1; + u64[4] = type(uint64).max; + string memory str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit,"; + bytes memory b = hex"ff"; + + DynamicsData memory data = DynamicsData( + [keccak256("value")], + [int32(-123), 123], + [type(uint128).max, 123, 456], + [address(this), address(0x0), address(0x1), address(0x2)], + staticBools, + u64, + str, + b + ); + + Dynamics.set(key, data); + assertEq(abi.encode(Dynamics.get(key)), abi.encode(data)); + + Dynamics.setStaticBools(key, staticBools); + assertEq(abi.encode(Dynamics.getStaticBools(key)), abi.encode(staticBools)); + + Dynamics.setU64(key, u64); + assertEq(abi.encode(Dynamics.getU64(key)), abi.encode(u64)); + } + + function testSingletonSetAndGet() public { + Singleton.registerSchema(); + + Singleton.set(-10, [uint32(1), 2], [uint32(3), 4], [uint32(5)]); + assertEq(Singleton.getV1(), -10); + assertEq(abi.encode(Singleton.getV2()), abi.encode([uint32(1), 2])); + assertEq(abi.encode(Singleton.getV3()), abi.encode([uint32(3), 4])); + assertEq(abi.encode(Singleton.getV4()), abi.encode([uint32(5)])); } } diff --git a/packages/cli/foundry.toml b/packages/cli/foundry.toml index 051e95dc8a..7341f796c7 100644 --- a/packages/cli/foundry.toml +++ b/packages/cli/foundry.toml @@ -1,4 +1,5 @@ [profile.default] +# check all "WARNING:" comments before changing major solidity versions solc_version = "0.8.13" ffi = false fuzz_runs = 256 diff --git a/packages/cli/scripts/codegen.ts b/packages/cli/scripts/codegen.ts index ae3b92d2fe..1f4afde689 100644 --- a/packages/cli/scripts/codegen.ts +++ b/packages/cli/scripts/codegen.ts @@ -6,7 +6,7 @@ import { getSrcDirectory } from "../src/utils/foundry.js"; // This config is used only for tests const config = storeConfig({ tables: { - Table1: { + Statics: { primaryKeys: { k1: "uint256", k2: "int32", @@ -26,6 +26,28 @@ const config = storeConfig({ v7: "Enum2", }, }, + Dynamics: { + schema: { + staticB32: "bytes32[1]", + staticI32: "int32[2]", + staticU128: "uint128[3]", + staticAddrs: "address[4]", + staticBools: "bool[5]", + u64: "uint64[]", + str: "string", + b: "bytes", + }, + }, + Singleton: { + primaryKeys: {}, + schema: { + v1: "int256", + v2: "uint32[2]", + v3: "uint32[2]", + v4: "uint32[1]", + }, + dataStruct: false, + }, }, enums: { diff --git a/packages/cli/src/config/parseStoreConfig.test-d.ts b/packages/cli/src/config/parseStoreConfig.test-d.ts index 3abb3772de..83886dd50f 100644 --- a/packages/cli/src/config/parseStoreConfig.test-d.ts +++ b/packages/cli/src/config/parseStoreConfig.test-d.ts @@ -1,6 +1,6 @@ import { describe, expectTypeOf } from "vitest"; import { z } from "zod"; -import { StoreConfig, StoreUserConfig } from "./parseStoreConfig.js"; +import { storeConfig, StoreConfig, StoreUserConfig } from "./parseStoreConfig.js"; describe("StoreUserConfig", () => { // Typecheck manual interfaces against zod @@ -11,4 +11,30 @@ describe("StoreUserConfig", () => { NonNullable>["enums"]>[string] >(); // TODO If more nested schemas are added, provide separate tests for them + + // Test possible inference confusion. + // This would fail if you remove `AsDependent` from `StoreUserConfig` + expectTypeOf( + storeConfig({ + tables: { + Table1: { + primaryKeys: { + a: "Enum1", + }, + schema: { + b: "Enum2", + }, + }, + Table2: { + schema: { + a: "uint32", + }, + }, + }, + enums: { + Enum1: ["E1"], + Enum2: ["E1"], + }, + }) + ).toEqualTypeOf>(); }); diff --git a/packages/cli/src/config/parseStoreConfig.ts b/packages/cli/src/config/parseStoreConfig.ts index d7d46ad969..d2a46dd16d 100644 --- a/packages/cli/src/config/parseStoreConfig.ts +++ b/packages/cli/src/config/parseStoreConfig.ts @@ -1,6 +1,6 @@ import { AbiType, AbiTypes, StaticAbiType, StaticAbiTypes } from "@latticexyz/schema-type"; import { RefinementCtx, z, ZodIssueCode } from "zod"; -import { ExtractUserTypes, RequireKeys, StringForUnion } from "../utils/typeUtils.js"; +import { AsDependent, ExtractUserTypes, RequireKeys, StaticArray, StringForUnion } from "../utils/typeUtils.js"; import { ObjectName, Selector, UserEnum, ValueName } from "./commonSchemas.js"; import { getDuplicates, parseStaticArray } from "./validation.js"; @@ -13,7 +13,7 @@ const UserEnumName = ObjectName; // (user types are refined later, based on the appropriate config options) const zFieldData = z.string(); -type FieldData = AbiType | UserTypes; +type FieldData = AbiType | StaticArray | UserTypes; // Primary keys allow only static types // (user types are refined later, based on the appropriate config options) @@ -189,7 +189,7 @@ export type StoreUserConfig< * - abi or user type for a single-value table (aka ECS component). * - FullTableConfig object for multi-value tables (or for customizable options). */ - tables: TablesConfig; + tables: TablesConfig, AsDependent>; /** Path to the file where common user types will be generated and imported from. Default is "Types" */ userTypesPath?: string; }; @@ -310,11 +310,5 @@ function validateStaticArray( code: ZodIssueCode.custom, message: `Static array length must be less than 2**16`, }); - } else { - // TODO add static array support to tablegen - ctx.addIssue({ - code: ZodIssueCode.custom, - message: `Static arrays are not yet supported`, - }); } } diff --git a/packages/cli/src/render-solidity/record.ts b/packages/cli/src/render-solidity/record.ts index 1007c92bb6..7d394a63de 100644 --- a/packages/cli/src/render-solidity/record.ts +++ b/packages/cli/src/render-solidity/record.ts @@ -137,12 +137,18 @@ function renderDecodedRecord({ structName, fields }: RenderTableOptions) { } function renderDecodeDynamicFieldPartial(field: RenderTableDynamicField) { - const { typeId, arrayElement } = field; + const { typeId, arrayElement, typeWrap } = field; if (arrayElement) { // arrays - return `SliceLib.getSubslice(_blob, _start, _end).decodeArray_${arrayElement.typeId}()`; + return `${typeWrap}( + SliceLib.getSubslice(_blob, _start, _end).decodeArray_${arrayElement.typeId}() + )`; } else { // bytes/string - return `${typeId}(SliceLib.getSubslice(_blob, _start, _end).toBytes())`; + return `${typeWrap}( + ${typeId}( + SliceLib.getSubslice(_blob, _start, _end).toBytes() + ) + )`; } } diff --git a/packages/cli/src/render-solidity/renderTable.ts b/packages/cli/src/render-solidity/renderTable.ts index a71cd569a1..e304093a3d 100644 --- a/packages/cli/src/render-solidity/renderTable.ts +++ b/packages/cli/src/render-solidity/renderTable.ts @@ -9,6 +9,7 @@ import { } from "./common.js"; import { renderEncodeField, renderFieldMethods } from "./field.js"; import { renderRecordMethods } from "./record.js"; +import { renderTypeHelpers } from "./renderTypeHelpers.js"; import { RenderTableDynamicField, RenderTableOptions } from "./types.js"; export function renderTable(options: RenderTableOptions) { @@ -38,6 +39,7 @@ import { IStore } from "${storeImportPath}IStore.sol"; import { StoreSwitch } from "${storeImportPath}StoreSwitch.sol"; import { StoreCore } from "${storeImportPath}StoreCore.sol"; import { Bytes } from "${storeImportPath}Bytes.sol"; +import { Memory } from "${storeImportPath}Memory.sol"; import { SliceLib } from "${storeImportPath}Slice.sol"; import { EncodeArray } from "${storeImportPath}tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "${storeImportPath}Schema.sol"; @@ -114,7 +116,7 @@ library ${libraryName} { /** Tightly pack full data using this table's schema */ function encode(${renderArguments( options.fields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`) - )}) internal pure returns (bytes memory) { + )}) internal view returns (bytes memory) { ${renderEncodedLengths(dynamicFields)} return abi.encodePacked(${renderArguments([ renderArguments(staticFields.map(({ name }) => name)), @@ -138,31 +140,7 @@ library ${libraryName} { )} } -${ - // nothing can be cast to bool, so an assembly helper is required - !fields.some(({ typeId }) => typeId === "bool") - ? "" - : ` - function _toBool(uint8 value) pure returns (bool result) { - assembly { - result := value - } - } -` -} - -${ - // nothing can be cast from bool, so an assembly helper is required - !options.primaryKeys.some(({ typeId }) => typeId === "bool") - ? "" - : ` - function _boolToBytes32(bool value) pure returns (bytes32 result) { - assembly { - result := value - } - } -` -} +${renderTypeHelpers(options)} `; } diff --git a/packages/cli/src/render-solidity/renderTypeHelpers.ts b/packages/cli/src/render-solidity/renderTypeHelpers.ts new file mode 100644 index 0000000000..58f6223a5b --- /dev/null +++ b/packages/cli/src/render-solidity/renderTypeHelpers.ts @@ -0,0 +1,99 @@ +import { RenderTableOptions, RenderTableType } from "./types.js"; + +export function renderTypeHelpers(options: RenderTableOptions) { + const { fields, primaryKeys } = options; + + let result = ""; + + for (const wrappingHelper of getWrappingHelpers([...fields, ...primaryKeys])) { + result += wrappingHelper; + } + + // bool is special - it's the only primitive value type that can't be typecasted to/from + if (fields.some(({ typeId }) => typeId === "bool")) { + result += ` + function _toBool(uint8 value) pure returns (bool result) { + assembly { + result := value + } + } + `; + } + if (primaryKeys.some(({ typeId }) => typeId === "bool")) { + result += ` + function _boolToBytes32(bool value) pure returns (bytes32 result) { + assembly { + result := value + } + } + `; + } + + return result; +} + +function getWrappingHelpers(array: RenderTableType[]) { + const wrappers = new Map(); + const unwrappers = new Map(); + for (const { typeWrappingData, typeWrap, typeUnwrap, internalTypeId } of array) { + if (!typeWrappingData) continue; + const { kind } = typeWrappingData; + + if (kind === "staticArray") { + const { elementType, staticLength } = typeWrappingData; + wrappers.set(typeWrap, renderWrapperStaticArray(typeWrap, elementType, staticLength, internalTypeId)); + unwrappers.set(typeUnwrap, renderUnwrapperStaticArray(typeUnwrap, elementType, staticLength, internalTypeId)); + } + } + + return [...wrappers.values(), ...unwrappers.values()]; +} + +function renderWrapperStaticArray( + functionName: string, + elementType: string, + staticLength: number, + internalTypeId: string +) { + // WARNING: ensure this still works if changing major solidity versions! + // (the memory layout for static arrays may change) + return ` + function ${functionName}( + ${internalTypeId} memory _value + ) pure returns ( + ${elementType}[${staticLength}] memory _result + ) { + // in memory static arrays are just dynamic arrays without the length byte + assembly { + _result := add(_value, 0x20) + } + } + `; +} + +function renderUnwrapperStaticArray( + functionName: string, + elementType: string, + staticLength: number, + internalTypeId: string +) { + // byte length for memory copying (more efficient than a loop) + const byteLength = staticLength * 32; + // TODO to optimize memory usage consider generalizing TightEncoder to a render-time utility + return ` + function ${functionName}( + ${elementType}[${staticLength}] memory _value + ) view returns ( + ${internalTypeId} memory _result + ) { + _result = new ${internalTypeId}(${staticLength}); + uint256 fromPointer; + uint256 toPointer; + assembly { + fromPointer := _value + toPointer := add(_result, 0x20) + } + Memory.copy(fromPointer, toPointer, ${byteLength}); + } + `; +} diff --git a/packages/cli/src/render-solidity/types.ts b/packages/cli/src/render-solidity/types.ts index 058931ef7e..007028600f 100644 --- a/packages/cli/src/render-solidity/types.ts +++ b/packages/cli/src/render-solidity/types.ts @@ -43,10 +43,18 @@ export interface RenderTableType { typeWrap: string; /** Empty for internal types. Custom `unwrap` method for user defined types. */ typeUnwrap: string; + /** Data to generate the custom wrapper and unwrapper if necessary. */ + typeWrappingData?: RenderTableTypeWrappingData; /** Same as typeId for internal types. The underlying `typeId` for user defined types. */ internalTypeId: string; } +export type RenderTableTypeWrappingData = { + kind: "staticArray"; + elementType: string; + staticLength: number; +}; + export interface RenderTablePrimaryKey extends RenderTableType { name: string; isDynamic: false; diff --git a/packages/cli/src/render-solidity/userType.ts b/packages/cli/src/render-solidity/userType.ts index feae7d3b31..d44d6f936e 100644 --- a/packages/cli/src/render-solidity/userType.ts +++ b/packages/cli/src/render-solidity/userType.ts @@ -1,23 +1,39 @@ import { AbiTypeToSchemaType, getStaticByteLength, SchemaType, SchemaTypeToAbiType } from "@latticexyz/schema-type"; import { StoreConfig } from "../index.js"; import { ImportDatum, RenderTableType } from "./types.js"; +import { parseStaticArray } from "../config/validation.js"; export type UserTypeInfo = ReturnType; /** * Resolve an abi or user type into a SchemaType */ -export function resolveAbiOrUserType(abiOrUserType: string, config: StoreConfig) { +export function resolveAbiOrUserType( + abiOrUserType: string, + config: StoreConfig +): { + schemaType: SchemaType; + renderTableType: RenderTableType; +} { + // abi types which directly mirror a SchemaType if (abiOrUserType in AbiTypeToSchemaType) { const schemaType = AbiTypeToSchemaType[abiOrUserType]; return { schemaType, renderTableType: getSchemaTypeInfo(schemaType), }; - } else { - const { schemaType, renderTableType } = getUserTypeInfo(abiOrUserType, config); - return { schemaType, renderTableType }; } + // static arrays + const staticArray = parseStaticArray(abiOrUserType); + if (staticArray) { + if (staticArray.elementType in AbiTypeToSchemaType) { + return getStaticArrayTypeInfo(abiOrUserType, staticArray.elementType, staticArray.staticLength); + } else { + throw new Error("Static arrays of user types are not supported"); + } + } + // user types + return getUserTypeInfo(abiOrUserType, config); } /** @@ -28,15 +44,21 @@ export function importForAbiOrUserType( usedInDirectory: string, config: StoreConfig ): ImportDatum | undefined { + // abi types which directly mirror a SchemaType if (abiOrUserType in AbiTypeToSchemaType) { return undefined; - } else { - return { - symbol: abiOrUserType, - fromPath: config.userTypesPath + ".sol", - usedInPath: usedInDirectory, - }; } + // static arrays + const staticArray = parseStaticArray(abiOrUserType); + if (staticArray) { + return undefined; + } + // user types + return { + symbol: abiOrUserType, + fromPath: config.userTypesPath + ".sol", + usedInPath: usedInDirectory, + }; } export function getSchemaTypeInfo(schemaType: SchemaType): RenderTableType { @@ -62,6 +84,7 @@ export function getUserTypeInfo( schemaType: SchemaType; renderTableType: RenderTableType; } { + // enums if (userType in config.enums) { const schemaType = SchemaType.UINT8; const staticByteLength = getStaticByteLength(schemaType); @@ -76,11 +99,34 @@ export function getUserTypeInfo( staticByteLength, isDynamic, typeWrap: `${userType}`, - typeUnwrap: `${userType}`, + typeUnwrap: `uint8`, internalTypeId: `${SchemaTypeToAbiType[schemaType]}`, }, }; - } else { - throw new Error(`User type "${userType}" does not exist`); } + // invalid + throw new Error(`User type "${userType}" does not exist`); +} + +function getStaticArrayTypeInfo(abiType: string, elementType: string, staticLength: number) { + const internalTypeId = elementType + "[]"; + const schemaType = AbiTypeToSchemaType[internalTypeId]; + return { + schemaType, + renderTableType: { + typeId: abiType, + typeWithLocation: `${abiType} memory`, + enumName: SchemaType[schemaType], + staticByteLength: 0, + isDynamic: true, + typeWrap: `toStaticArray_${elementType}_${staticLength}`, + typeUnwrap: `fromStaticArray_${elementType}_${staticLength}`, + typeWrappingData: { + kind: "staticArray", + elementType, + staticLength, + }, + internalTypeId, + }, + } as const; } diff --git a/packages/cli/src/utils/typeUtils.ts b/packages/cli/src/utils/typeUtils.ts index 48212b9c38..9ab04275a9 100644 --- a/packages/cli/src/utils/typeUtils.ts +++ b/packages/cli/src/utils/typeUtils.ts @@ -9,3 +9,9 @@ export type StringForUnion = string & Record; export type StaticArray = `${StaticAbiType}[${number}]`; // static arrays and inferred enum names get mixed together - this helper separates them export type ExtractUserTypes = Exclude; + +// When type inference sees multiple uses of 1 generic, it can only guess +// which of those are supposed to define the generic (and it will be wrong in complex situations). +// This helper explicitly makes a type that's dependent on some generic, +// and will not be inferred as the generic's definition. +export type AsDependent = T extends infer P ? P : never; diff --git a/packages/store/src/tables/Callbacks.sol b/packages/store/src/tables/Callbacks.sol index 72bd552eee..085f5961e3 100644 --- a/packages/store/src/tables/Callbacks.sol +++ b/packages/store/src/tables/Callbacks.sol @@ -11,6 +11,7 @@ import { IStore } from "../IStore.sol"; import { StoreSwitch } from "../StoreSwitch.sol"; import { StoreCore } from "../StoreCore.sol"; import { Bytes } from "../Bytes.sol"; +import { Memory } from "../Memory.sol"; import { SliceLib } from "../Slice.sol"; import { EncodeArray } from "../tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "../Schema.sol"; @@ -79,7 +80,7 @@ library Callbacks { } /** Tightly pack full data using this table's schema */ - function encode(bytes24[] memory value) internal pure returns (bytes memory) { + function encode(bytes24[] memory value) internal view returns (bytes memory) { uint16[] memory _counters = new uint16[](1); _counters[0] = uint16(value.length * 24); PackedCounter _encodedLengths = PackedCounterLib.pack(_counters); diff --git a/packages/store/src/tables/Hooks.sol b/packages/store/src/tables/Hooks.sol index 0e8d8c28fe..052cfd28b5 100644 --- a/packages/store/src/tables/Hooks.sol +++ b/packages/store/src/tables/Hooks.sol @@ -11,6 +11,7 @@ import { IStore } from "../IStore.sol"; import { StoreSwitch } from "../StoreSwitch.sol"; import { StoreCore } from "../StoreCore.sol"; import { Bytes } from "../Bytes.sol"; +import { Memory } from "../Memory.sol"; import { SliceLib } from "../Slice.sol"; import { EncodeArray } from "../tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "../Schema.sol"; @@ -79,7 +80,7 @@ library Hooks { } /** Tightly pack full data using this table's schema */ - function encode(address[] memory value) internal pure returns (bytes memory) { + function encode(address[] memory value) internal view returns (bytes memory) { uint16[] memory _counters = new uint16[](1); _counters[0] = uint16(value.length * 20); PackedCounter _encodedLengths = PackedCounterLib.pack(_counters); diff --git a/packages/store/src/tables/Mixed.sol b/packages/store/src/tables/Mixed.sol index 8128b8e802..6570e65d6b 100644 --- a/packages/store/src/tables/Mixed.sol +++ b/packages/store/src/tables/Mixed.sol @@ -11,6 +11,7 @@ import { IStore } from "../IStore.sol"; import { StoreSwitch } from "../StoreSwitch.sol"; import { StoreCore } from "../StoreCore.sol"; import { Bytes } from "../Bytes.sol"; +import { Memory } from "../Memory.sol"; import { SliceLib } from "../Slice.sol"; import { EncodeArray } from "../tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "../Schema.sol"; @@ -188,15 +189,15 @@ library Mixed { _start = _end; _end += _encodedLengths.atIndex(0); - _table.a32 = SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint32(); + _table.a32 = (SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint32()); _start = _end; _end += _encodedLengths.atIndex(1); - _table.s = string(SliceLib.getSubslice(_blob, _start, _end).toBytes()); + _table.s = (string(SliceLib.getSubslice(_blob, _start, _end).toBytes())); } /** Tightly pack full data using this table's schema */ - function encode(uint32 u32, uint128 u128, uint32[] memory a32, string memory s) internal pure returns (bytes memory) { + function encode(uint32 u32, uint128 u128, uint32[] memory a32, string memory s) internal view returns (bytes memory) { uint16[] memory _counters = new uint16[](2); _counters[0] = uint16(a32.length * 4); _counters[1] = uint16(bytes(s).length); diff --git a/packages/store/src/tables/StoreMetadata.sol b/packages/store/src/tables/StoreMetadata.sol index 967e67c3d6..8b141af6dd 100644 --- a/packages/store/src/tables/StoreMetadata.sol +++ b/packages/store/src/tables/StoreMetadata.sol @@ -11,6 +11,7 @@ import { IStore } from "../IStore.sol"; import { StoreSwitch } from "../StoreSwitch.sol"; import { StoreCore } from "../StoreCore.sol"; import { Bytes } from "../Bytes.sol"; +import { Memory } from "../Memory.sol"; import { SliceLib } from "../Slice.sol"; import { EncodeArray } from "../tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "../Schema.sol"; @@ -232,15 +233,15 @@ library StoreMetadata { _start = _end; _end += _encodedLengths.atIndex(0); - _table.tableName = string(SliceLib.getSubslice(_blob, _start, _end).toBytes()); + _table.tableName = (string(SliceLib.getSubslice(_blob, _start, _end).toBytes())); _start = _end; _end += _encodedLengths.atIndex(1); - _table.abiEncodedFieldNames = bytes(SliceLib.getSubslice(_blob, _start, _end).toBytes()); + _table.abiEncodedFieldNames = (bytes(SliceLib.getSubslice(_blob, _start, _end).toBytes())); } /** Tightly pack full data using this table's schema */ - function encode(string memory tableName, bytes memory abiEncodedFieldNames) internal pure returns (bytes memory) { + function encode(string memory tableName, bytes memory abiEncodedFieldNames) internal view returns (bytes memory) { uint16[] memory _counters = new uint16[](2); _counters[0] = uint16(bytes(tableName).length); _counters[1] = uint16(bytes(abiEncodedFieldNames).length); diff --git a/packages/store/src/tables/Vector2.sol b/packages/store/src/tables/Vector2.sol index 7c860aba5d..8334a7c301 100644 --- a/packages/store/src/tables/Vector2.sol +++ b/packages/store/src/tables/Vector2.sol @@ -11,6 +11,7 @@ import { IStore } from "../IStore.sol"; import { StoreSwitch } from "../StoreSwitch.sol"; import { StoreCore } from "../StoreCore.sol"; import { Bytes } from "../Bytes.sol"; +import { Memory } from "../Memory.sol"; import { SliceLib } from "../Slice.sol"; import { EncodeArray } from "../tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "../Schema.sol"; @@ -126,7 +127,7 @@ library Vector2 { } /** Tightly pack full data using this table's schema */ - function encode(uint32 x, uint32 y) internal pure returns (bytes memory) { + function encode(uint32 x, uint32 y) internal view returns (bytes memory) { return abi.encodePacked(x, y); } diff --git a/packages/world/gas-report.txt b/packages/world/gas-report.txt index 9e146f5f22..3fcdee3f15 100644 --- a/packages/world/gas-report.txt +++ b/packages/world/gas-report.txt @@ -1,12 +1,12 @@ -(test/KeysWithValueModule.t.sol) | install keys with value module [world.installRootModule(keysWithValueModule, abi.encode(sourceTableId))]: 391485 +(test/KeysWithValueModule.t.sol) | install keys with value module [world.installRootModule(keysWithValueModule, abi.encode(sourceTableId))]: 391457 (test/KeysWithValueModule.t.sol) | Get list of keys with a given value [bytes32[] memory keysWithValue = getKeysWithValue(world, sourceTableId, abi.encode(value1))]: 7672 (test/KeysWithValueModule.t.sol) | compute the target table selector [bytes32 targetTableSelector = getTargetTableSelector(sourceTableId)]: 2245 -(test/KeysWithValueModule.t.sol) | install keys with value module [world.installRootModule(keysWithValueModule, abi.encode(sourceTableId))]: 391485 +(test/KeysWithValueModule.t.sol) | install keys with value module [world.installRootModule(keysWithValueModule, abi.encode(sourceTableId))]: 391457 (test/KeysWithValueModule.t.sol) | set a record on a table with KeysWithValueModule installed [world.setRecord(namespace, sourceFile, keyTuple1, abi.encodePacked(value))]: 169477 -(test/KeysWithValueModule.t.sol) | install keys with value module [world.installRootModule(keysWithValueModule, abi.encode(sourceTableId))]: 391485 +(test/KeysWithValueModule.t.sol) | install keys with value module [world.installRootModule(keysWithValueModule, abi.encode(sourceTableId))]: 391457 (test/KeysWithValueModule.t.sol) | change a record on a table with KeysWithValueModule installed [world.setRecord(namespace, sourceFile, keyTuple1, abi.encodePacked(value2))]: 135475 (test/KeysWithValueModule.t.sol) | delete a record on a table with KeysWithValueModule installed [world.deleteRecord(namespace, sourceFile, keyTuple1)]: 57998 -(test/KeysWithValueModule.t.sol) | install keys with value module [world.installRootModule(keysWithValueModule, abi.encode(sourceTableId))]: 391485 +(test/KeysWithValueModule.t.sol) | install keys with value module [world.installRootModule(keysWithValueModule, abi.encode(sourceTableId))]: 391457 (test/KeysWithValueModule.t.sol) | set a field on a table with KeysWithValueModule installed [world.setField(namespace, sourceFile, keyTuple1, 0, abi.encodePacked(value1))]: 177731 (test/KeysWithValueModule.t.sol) | change a field on a table with KeysWithValueModule installed [world.setField(namespace, sourceFile, keyTuple1, 0, abi.encodePacked(value2))]: 142076 (test/World.t.sol) | Delete record [world.deleteRecord(namespace, file, singletonKey)]: 16115 @@ -14,9 +14,9 @@ (test/World.t.sol) | Register a fallback system [bytes4 funcSelector1 = world.registerFunctionSelector(namespace, file, "", "")]: 81251 (test/World.t.sol) | Register a root fallback system [bytes4 funcSelector2 = world.registerRootFunctionSelector(namespace, file, worldFunc, 0)]: 72478 (test/World.t.sol) | Register a function selector [bytes4 functionSelector = world.registerFunctionSelector(namespace, file, "msgSender", "()")]: 101848 -(test/World.t.sol) | Register a new namespace [world.registerNamespace("test")]: 152132 +(test/World.t.sol) | Register a new namespace [world.registerNamespace("test")]: 152118 (test/World.t.sol) | Register a root function selector [bytes4 functionSelector = world.registerRootFunctionSelector(namespace, file, worldFunc, sysFunc)]: 96384 -(test/World.t.sol) | Register a new table in the namespace [bytes32 tableSelector = world.registerTable(namespace, table, schema, defaultKeySchema)]: 252940 +(test/World.t.sol) | Register a new table in the namespace [bytes32 tableSelector = world.registerTable(namespace, table, schema, defaultKeySchema)]: 252912 (test/World.t.sol) | Write data to a table field [world.setField(namespace, file, singletonKey, 0, abi.encodePacked(true))]: 44816 (test/World.t.sol) | Set metadata [world.setMetadata(namespace, file, tableName, fieldNames)]: 277464 (test/World.t.sol) | Write data to the table [Bool.set(world, tableId, true)]: 42697 \ No newline at end of file diff --git a/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol b/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol index 694d5af068..5919891179 100644 --- a/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol +++ b/packages/world/src/modules/keyswithvalue/tables/KeysWithValue.sol @@ -11,6 +11,7 @@ import { IStore } from "@latticexyz/store/src/IStore.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; import { Bytes } from "@latticexyz/store/src/Bytes.sol"; +import { Memory } from "@latticexyz/store/src/Memory.sol"; import { SliceLib } from "@latticexyz/store/src/Slice.sol"; import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; @@ -116,7 +117,7 @@ library KeysWithValue { } /** Tightly pack full data using this table's schema */ - function encode(bytes32[] memory keysWithValue) internal pure returns (bytes memory) { + function encode(bytes32[] memory keysWithValue) internal view returns (bytes memory) { uint16[] memory _counters = new uint16[](1); _counters[0] = uint16(keysWithValue.length * 32); PackedCounter _encodedLengths = PackedCounterLib.pack(_counters); diff --git a/packages/world/src/modules/registration/tables/ResourceType.sol b/packages/world/src/modules/registration/tables/ResourceType.sol index 9b3e5c8929..69020c1b1e 100644 --- a/packages/world/src/modules/registration/tables/ResourceType.sol +++ b/packages/world/src/modules/registration/tables/ResourceType.sol @@ -11,6 +11,7 @@ import { IStore } from "@latticexyz/store/src/IStore.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; import { Bytes } from "@latticexyz/store/src/Bytes.sol"; +import { Memory } from "@latticexyz/store/src/Memory.sol"; import { SliceLib } from "@latticexyz/store/src/Slice.sol"; import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; @@ -70,11 +71,11 @@ library ResourceType { bytes32[] memory _primaryKeys = new bytes32[](1); _primaryKeys[0] = bytes32((resourceSelector)); - StoreSwitch.setField(_tableId, _primaryKeys, 0, abi.encodePacked(Resource(resourceType))); + StoreSwitch.setField(_tableId, _primaryKeys, 0, abi.encodePacked(uint8(resourceType))); } /** Tightly pack full data using this table's schema */ - function encode(Resource resourceType) internal pure returns (bytes memory) { + function encode(Resource resourceType) internal view returns (bytes memory) { return abi.encodePacked(resourceType); } diff --git a/packages/world/src/modules/registration/tables/SystemRegistry.sol b/packages/world/src/modules/registration/tables/SystemRegistry.sol index 272a772e4c..32112dcf14 100644 --- a/packages/world/src/modules/registration/tables/SystemRegistry.sol +++ b/packages/world/src/modules/registration/tables/SystemRegistry.sol @@ -11,6 +11,7 @@ import { IStore } from "@latticexyz/store/src/IStore.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; import { Bytes } from "@latticexyz/store/src/Bytes.sol"; +import { Memory } from "@latticexyz/store/src/Memory.sol"; import { SliceLib } from "@latticexyz/store/src/Slice.sol"; import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; @@ -71,7 +72,7 @@ library SystemRegistry { } /** Tightly pack full data using this table's schema */ - function encode(bytes32 resourceSelector) internal pure returns (bytes memory) { + function encode(bytes32 resourceSelector) internal view returns (bytes memory) { return abi.encodePacked(resourceSelector); } diff --git a/packages/world/src/tables/AddressArray.sol b/packages/world/src/tables/AddressArray.sol index 8c0b295ec9..514d299f4f 100644 --- a/packages/world/src/tables/AddressArray.sol +++ b/packages/world/src/tables/AddressArray.sol @@ -11,6 +11,7 @@ import { IStore } from "@latticexyz/store/src/IStore.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; import { Bytes } from "@latticexyz/store/src/Bytes.sol"; +import { Memory } from "@latticexyz/store/src/Memory.sol"; import { SliceLib } from "@latticexyz/store/src/Slice.sol"; import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; @@ -112,7 +113,7 @@ library AddressArray { } /** Tightly pack full data using this table's schema */ - function encode(address[] memory value) internal pure returns (bytes memory) { + function encode(address[] memory value) internal view returns (bytes memory) { uint16[] memory _counters = new uint16[](1); _counters[0] = uint16(value.length * 20); PackedCounter _encodedLengths = PackedCounterLib.pack(_counters); diff --git a/packages/world/src/tables/Bool.sol b/packages/world/src/tables/Bool.sol index ff0ea2afb3..88d497179d 100644 --- a/packages/world/src/tables/Bool.sol +++ b/packages/world/src/tables/Bool.sol @@ -11,6 +11,7 @@ import { IStore } from "@latticexyz/store/src/IStore.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; import { Bytes } from "@latticexyz/store/src/Bytes.sol"; +import { Memory } from "@latticexyz/store/src/Memory.sol"; import { SliceLib } from "@latticexyz/store/src/Slice.sol"; import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; @@ -91,7 +92,7 @@ library Bool { } /** Tightly pack full data using this table's schema */ - function encode(bool value) internal pure returns (bytes memory) { + function encode(bool value) internal view returns (bytes memory) { return abi.encodePacked(value); } diff --git a/packages/world/src/tables/FunctionSelectors.sol b/packages/world/src/tables/FunctionSelectors.sol index 423d96ae85..ba9163e07c 100644 --- a/packages/world/src/tables/FunctionSelectors.sol +++ b/packages/world/src/tables/FunctionSelectors.sol @@ -11,6 +11,7 @@ import { IStore } from "@latticexyz/store/src/IStore.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; import { Bytes } from "@latticexyz/store/src/Bytes.sol"; +import { Memory } from "@latticexyz/store/src/Memory.sol"; import { SliceLib } from "@latticexyz/store/src/Slice.sol"; import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; @@ -141,7 +142,7 @@ library FunctionSelectors { } /** Tightly pack full data using this table's schema */ - function encode(bytes16 namespace, bytes16 file, bytes4 systemFunctionSelector) internal pure returns (bytes memory) { + function encode(bytes16 namespace, bytes16 file, bytes4 systemFunctionSelector) internal view returns (bytes memory) { return abi.encodePacked(namespace, file, systemFunctionSelector); } diff --git a/packages/world/src/tables/InstalledModules.sol b/packages/world/src/tables/InstalledModules.sol index dc983143dd..73fbbe15e0 100644 --- a/packages/world/src/tables/InstalledModules.sol +++ b/packages/world/src/tables/InstalledModules.sol @@ -11,6 +11,7 @@ import { IStore } from "@latticexyz/store/src/IStore.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; import { Bytes } from "@latticexyz/store/src/Bytes.sol"; +import { Memory } from "@latticexyz/store/src/Memory.sol"; import { SliceLib } from "@latticexyz/store/src/Slice.sol"; import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; @@ -109,7 +110,7 @@ library InstalledModules { } /** Tightly pack full data using this table's schema */ - function encode(address moduleAddress) internal pure returns (bytes memory) { + function encode(address moduleAddress) internal view returns (bytes memory) { return abi.encodePacked(moduleAddress); } diff --git a/packages/world/src/tables/NamespaceOwner.sol b/packages/world/src/tables/NamespaceOwner.sol index 8367b210f1..e30489aedc 100644 --- a/packages/world/src/tables/NamespaceOwner.sol +++ b/packages/world/src/tables/NamespaceOwner.sol @@ -11,6 +11,7 @@ import { IStore } from "@latticexyz/store/src/IStore.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; import { Bytes } from "@latticexyz/store/src/Bytes.sol"; +import { Memory } from "@latticexyz/store/src/Memory.sol"; import { SliceLib } from "@latticexyz/store/src/Slice.sol"; import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; @@ -99,7 +100,7 @@ library NamespaceOwner { } /** Tightly pack full data using this table's schema */ - function encode(address owner) internal pure returns (bytes memory) { + function encode(address owner) internal view returns (bytes memory) { return abi.encodePacked(owner); } diff --git a/packages/world/src/tables/ResourceAccess.sol b/packages/world/src/tables/ResourceAccess.sol index fb9b348c6f..33c82c911d 100644 --- a/packages/world/src/tables/ResourceAccess.sol +++ b/packages/world/src/tables/ResourceAccess.sol @@ -11,6 +11,7 @@ import { IStore } from "@latticexyz/store/src/IStore.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; import { Bytes } from "@latticexyz/store/src/Bytes.sol"; +import { Memory } from "@latticexyz/store/src/Memory.sol"; import { SliceLib } from "@latticexyz/store/src/Slice.sol"; import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; @@ -104,7 +105,7 @@ library ResourceAccess { } /** Tightly pack full data using this table's schema */ - function encode(bool access) internal pure returns (bytes memory) { + function encode(bool access) internal view returns (bytes memory) { return abi.encodePacked(access); } diff --git a/packages/world/src/tables/Systems.sol b/packages/world/src/tables/Systems.sol index 7e767b7145..142cfef148 100644 --- a/packages/world/src/tables/Systems.sol +++ b/packages/world/src/tables/Systems.sol @@ -11,6 +11,7 @@ import { IStore } from "@latticexyz/store/src/IStore.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; import { StoreCore } from "@latticexyz/store/src/StoreCore.sol"; import { Bytes } from "@latticexyz/store/src/Bytes.sol"; +import { Memory } from "@latticexyz/store/src/Memory.sol"; import { SliceLib } from "@latticexyz/store/src/Slice.sol"; import { EncodeArray } from "@latticexyz/store/src/tightcoder/EncodeArray.sol"; import { Schema, SchemaLib } from "@latticexyz/store/src/Schema.sol"; @@ -180,7 +181,7 @@ library Systems { } /** Tightly pack full data using this table's schema */ - function encode(address system, bool publicAccess) internal pure returns (bytes memory) { + function encode(address system, bool publicAccess) internal view returns (bytes memory) { return abi.encodePacked(system, publicAccess); }