diff --git a/packages/world/ts/node/render-solidity/renderSystemLibrary.ts b/packages/world/ts/node/render-solidity/renderSystemLibrary.ts index 85f4925a86..a7e1c8fd0b 100644 --- a/packages/world/ts/node/render-solidity/renderSystemLibrary.ts +++ b/packages/world/ts/node/render-solidity/renderSystemLibrary.ts @@ -87,9 +87,9 @@ export function renderSystemLibrary(options: RenderSystemLibraryOptions) { ${renderList(functions, (contractFunction) => renderUserTypeFunction(contractFunction, userTypeName))} - ${renderList(functions, (contractFunction) => renderCallWrapperFunction(contractFunction, systemLabel, callingFromRootSystemErrorName))} + ${renderList(functions, (contractFunction) => renderCallWrapperFunction(contractFunction, callingFromRootSystemErrorName))} - ${renderList(functions, (contractFunction) => renderRootCallWrapperFunction(contractFunction, systemLabel, namespace))} + ${renderList(functions, (contractFunction) => renderRootCallWrapperFunction(contractFunction, namespace))} function callFrom(${userTypeName} self, address from) internal pure returns (CallWrapper memory) { return CallWrapper(self.toResourceId(), from); @@ -120,6 +120,12 @@ export function renderSystemLibrary(options: RenderSystemLibraryOptions) { } } + /** + * These interfaces are used to support overloaded functions + */ + ${renderList(functions, (contractFunction) => renderFunctionInterface(contractFunction))} + + using ${libraryName} for ${userTypeName} global; using ${libraryName} for CallWrapper global; using ${libraryName} for RootCallWrapper global; @@ -154,7 +160,6 @@ function renderUserTypeFunction(contractFunction: ContractInterfaceFunction, use function renderCallWrapperFunction( contractFunction: ContractInterfaceFunction, - systemLabel: string, callingFromRootSystemErrorName: string, ) { const { name, parameters, stateMutability, returnParameters } = contractFunction; @@ -174,7 +179,7 @@ function renderCallWrapperFunction( if (address(_world()) == address(this)) revert ${callingFromRootSystemErrorName}(); `; - const encodedSystemCall = renderEncodeSystemCall(systemLabel, name, parameters); + const encodedSystemCall = renderEncodeSystemCall(contractFunction); if (stateMutability === "") { return ` @@ -203,11 +208,7 @@ function renderCallWrapperFunction( } } -function renderRootCallWrapperFunction( - contractFunction: ContractInterfaceFunction, - systemLabel: string, - namespace: string, -) { +function renderRootCallWrapperFunction(contractFunction: ContractInterfaceFunction, namespace: string) { const { name, parameters, stateMutability, returnParameters } = contractFunction; // Staticcalls are not supported between root systems yet, due to the additional @@ -226,7 +227,7 @@ function renderRootCallWrapperFunction( ${renderReturnParameters(returnParameters)} `; - const encodedSystemCall = renderEncodeSystemCall(systemLabel, name, parameters); + const encodedSystemCall = renderEncodeSystemCall(contractFunction); if (stateMutability === "") { return ` @@ -248,9 +249,28 @@ function renderRootCallWrapperFunction( } } -function renderEncodeSystemCall(interfaceName: string, functionName: string, parameters: string[]) { +function renderFunctionInterface(contractFunction: ContractInterfaceFunction) { + const { name, parameters } = contractFunction; + + return ` + interface ${functionInterfaceName(contractFunction)} { + function ${name}( + ${renderArguments(parameters)} + ) external; + } + `; +} + +function functionInterfaceName(contractFunction: ContractInterfaceFunction) { + const { name, parameters } = contractFunction; + const paramTypes = parameters.map((param) => param.split(" ")[0]).join("_"); + return `_I${name}${paramTypes.length === 0 ? "" : `_${paramTypes}`}`; +} + +function renderEncodeSystemCall(contractFunction: ContractInterfaceFunction) { + const { name, parameters } = contractFunction; const paramNames = parameters.map((param) => param.split(" ").slice(-1)[0]).join(", "); - return `abi.encodeCall(${interfaceName}.${functionName}, (${paramNames}))`; + return `abi.encodeCall(${functionInterfaceName(contractFunction)}.${name}, (${paramNames}))`; } function renderAbiDecode(expression: string, returnParameters: string[]) { diff --git a/test/system-libraries/src/codegen/world/IASystem.sol b/test/system-libraries/src/codegen/world/IASystem.sol index e99392b810..aca4932c4d 100644 --- a/test/system-libraries/src/codegen/world/IASystem.sol +++ b/test/system-libraries/src/codegen/world/IASystem.sol @@ -13,6 +13,8 @@ import { ASystemThing } from "../../namespaces/a/ASystemTypes.sol"; interface IASystem { function a__setValue(ASystemThing memory value) external; + function a__setValue(uint256 value) external; + function a__getValue() external view returns (uint256); function a__getTwoValues() external view returns (uint256, uint256); diff --git a/test/system-libraries/src/namespaces/a/ASystem.sol b/test/system-libraries/src/namespaces/a/ASystem.sol index f67d064bdd..1a8d92f2de 100644 --- a/test/system-libraries/src/namespaces/a/ASystem.sol +++ b/test/system-libraries/src/namespaces/a/ASystem.sol @@ -11,6 +11,10 @@ contract ASystem is System { Value.set(value.a); } + function setValue(uint256 value) external { + Value.set(value); + } + function getValue() external view returns (uint256) { return Value.get(); } diff --git a/test/system-libraries/src/namespaces/a/codegen/systems/ASystemLib.sol b/test/system-libraries/src/namespaces/a/codegen/systems/ASystemLib.sol index 47f00a29d0..fda1c37f8d 100644 --- a/test/system-libraries/src/namespaces/a/codegen/systems/ASystemLib.sol +++ b/test/system-libraries/src/namespaces/a/codegen/systems/ASystemLib.sol @@ -39,6 +39,10 @@ library ASystemLib { return CallWrapper(self.toResourceId(), address(0)).setValue(value); } + function setValue(ASystemType self, uint256 value) internal { + return CallWrapper(self.toResourceId(), address(0)).setValue(value); + } + function getValue(ASystemType self) internal view returns (uint256) { return CallWrapper(self.toResourceId(), address(0)).getValue(); } @@ -55,7 +59,17 @@ library ASystemLib { // if the contract calling this function is a root system, it should use `callAsRoot` if (address(_world()) == address(this)) revert ASystemLib_CallingFromRootSystem(); - bytes memory systemCall = abi.encodeCall(ASystem.setValue, (value)); + bytes memory systemCall = abi.encodeCall(_IsetValue_ASystemThing.setValue, (value)); + self.from == address(0) + ? _world().call(self.systemId, systemCall) + : _world().callFrom(self.from, self.systemId, systemCall); + } + + function setValue(CallWrapper memory self, uint256 value) internal { + // if the contract calling this function is a root system, it should use `callAsRoot` + if (address(_world()) == address(this)) revert ASystemLib_CallingFromRootSystem(); + + bytes memory systemCall = abi.encodeCall(_IsetValue_uint256.setValue, (value)); self.from == address(0) ? _world().call(self.systemId, systemCall) : _world().callFrom(self.from, self.systemId, systemCall); @@ -65,7 +79,7 @@ library ASystemLib { // if the contract calling this function is a root system, it should use `callAsRoot` if (address(_world()) == address(this)) revert ASystemLib_CallingFromRootSystem(); - bytes memory systemCall = abi.encodeCall(ASystem.getValue, ()); + bytes memory systemCall = abi.encodeCall(_IgetValue.getValue, ()); bytes memory worldCall = self.from == address(0) ? abi.encodeCall(IWorldCall.call, (self.systemId, systemCall)) : abi.encodeCall(IWorldCall.callFrom, (self.from, self.systemId, systemCall)); @@ -80,7 +94,7 @@ library ASystemLib { // if the contract calling this function is a root system, it should use `callAsRoot` if (address(_world()) == address(this)) revert ASystemLib_CallingFromRootSystem(); - bytes memory systemCall = abi.encodeCall(ASystem.getTwoValues, ()); + bytes memory systemCall = abi.encodeCall(_IgetTwoValues.getTwoValues, ()); bytes memory worldCall = self.from == address(0) ? abi.encodeCall(IWorldCall.call, (self.systemId, systemCall)) : abi.encodeCall(IWorldCall.callFrom, (self.from, self.systemId, systemCall)); @@ -95,7 +109,7 @@ library ASystemLib { // if the contract calling this function is a root system, it should use `callAsRoot` if (address(_world()) == address(this)) revert ASystemLib_CallingFromRootSystem(); - bytes memory systemCall = abi.encodeCall(ASystem.setAddress, ()); + bytes memory systemCall = abi.encodeCall(_IsetAddress.setAddress, ()); bytes memory result = self.from == address(0) ? _world().call(self.systemId, systemCall) @@ -104,26 +118,31 @@ library ASystemLib { } function setValue(RootCallWrapper memory self, ASystemThing memory value) internal { - bytes memory systemCall = abi.encodeCall(ASystem.setValue, (value)); + bytes memory systemCall = abi.encodeCall(_IsetValue_ASystemThing.setValue, (value)); + SystemCall.callWithHooksOrRevert(self.from, self.systemId, systemCall, msg.value); + } + + function setValue(RootCallWrapper memory self, uint256 value) internal { + bytes memory systemCall = abi.encodeCall(_IsetValue_uint256.setValue, (value)); SystemCall.callWithHooksOrRevert(self.from, self.systemId, systemCall, msg.value); } function getValue(RootCallWrapper memory self) internal view returns (uint256) { - bytes memory systemCall = abi.encodeCall(ASystem.getValue, ()); + bytes memory systemCall = abi.encodeCall(_IgetValue.getValue, ()); bytes memory result = SystemCall.staticcallOrRevert(self.from, self.systemId, systemCall); return abi.decode(result, (uint256)); } function getTwoValues(RootCallWrapper memory self) internal view returns (uint256, uint256) { - bytes memory systemCall = abi.encodeCall(ASystem.getTwoValues, ()); + bytes memory systemCall = abi.encodeCall(_IgetTwoValues.getTwoValues, ()); bytes memory result = SystemCall.staticcallOrRevert(self.from, self.systemId, systemCall); return abi.decode(result, (uint256, uint256)); } function setAddress(RootCallWrapper memory self) internal returns (address) { - bytes memory systemCall = abi.encodeCall(ASystem.setAddress, ()); + bytes memory systemCall = abi.encodeCall(_IsetAddress.setAddress, ()); bytes memory result = SystemCall.callWithHooksOrRevert(self.from, self.systemId, systemCall, msg.value); return abi.decode(result, (address)); @@ -158,6 +177,30 @@ library ASystemLib { } } +/** + * These interfaces are used to support overloaded functions + */ + +interface _IsetValue_ASystemThing { + function setValue(ASystemThing memory value) external; +} + +interface _IsetValue_uint256 { + function setValue(uint256 value) external; +} + +interface _IgetValue { + function getValue() external; +} + +interface _IgetTwoValues { + function getTwoValues() external; +} + +interface _IsetAddress { + function setAddress() external; +} + using ASystemLib for ASystemType global; using ASystemLib for CallWrapper global; using ASystemLib for RootCallWrapper global; diff --git a/test/system-libraries/src/namespaces/b/codegen/systems/BSystemLib.sol b/test/system-libraries/src/namespaces/b/codegen/systems/BSystemLib.sol index bc12e8a41a..d3983fffe1 100644 --- a/test/system-libraries/src/namespaces/b/codegen/systems/BSystemLib.sol +++ b/test/system-libraries/src/namespaces/b/codegen/systems/BSystemLib.sol @@ -47,7 +47,7 @@ library BSystemLib { // if the contract calling this function is a root system, it should use `callAsRoot` if (address(_world()) == address(this)) revert BSystemLib_CallingFromRootSystem(); - bytes memory systemCall = abi.encodeCall(BSystem.setValueInA, (thing)); + bytes memory systemCall = abi.encodeCall(_IsetValueInA_ASystemThing.setValueInA, (thing)); self.from == address(0) ? _world().call(self.systemId, systemCall) : _world().callFrom(self.from, self.systemId, systemCall); @@ -57,7 +57,7 @@ library BSystemLib { // if the contract calling this function is a root system, it should use `callAsRoot` if (address(_world()) == address(this)) revert BSystemLib_CallingFromRootSystem(); - bytes memory systemCall = abi.encodeCall(BSystem.getValueFromA, ()); + bytes memory systemCall = abi.encodeCall(_IgetValueFromA.getValueFromA, ()); bytes memory worldCall = self.from == address(0) ? abi.encodeCall(IWorldCall.call, (self.systemId, systemCall)) : abi.encodeCall(IWorldCall.callFrom, (self.from, self.systemId, systemCall)); @@ -69,12 +69,12 @@ library BSystemLib { } function setValueInA(RootCallWrapper memory self, ASystemThing memory thing) internal { - bytes memory systemCall = abi.encodeCall(BSystem.setValueInA, (thing)); + bytes memory systemCall = abi.encodeCall(_IsetValueInA_ASystemThing.setValueInA, (thing)); SystemCall.callWithHooksOrRevert(self.from, self.systemId, systemCall, msg.value); } function getValueFromA(RootCallWrapper memory self) internal view returns (uint256) { - bytes memory systemCall = abi.encodeCall(BSystem.getValueFromA, ()); + bytes memory systemCall = abi.encodeCall(_IgetValueFromA.getValueFromA, ()); bytes memory result = SystemCall.staticcallOrRevert(self.from, self.systemId, systemCall); return abi.decode(result, (uint256)); @@ -109,6 +109,18 @@ library BSystemLib { } } +/** + * These interfaces are used to support overloaded functions + */ + +interface _IsetValueInA_ASystemThing { + function setValueInA(ASystemThing memory thing) external; +} + +interface _IgetValueFromA { + function getValueFromA() external; +} + using BSystemLib for BSystemType global; using BSystemLib for CallWrapper global; using BSystemLib for RootCallWrapper global; diff --git a/test/system-libraries/src/namespaces/root/codegen/systems/RootSystemLib.sol b/test/system-libraries/src/namespaces/root/codegen/systems/RootSystemLib.sol index e2cebdbdd9..bd1cd90d47 100644 --- a/test/system-libraries/src/namespaces/root/codegen/systems/RootSystemLib.sol +++ b/test/system-libraries/src/namespaces/root/codegen/systems/RootSystemLib.sol @@ -49,7 +49,7 @@ library RootSystemLib { // if the contract calling this function is a root system, it should use `callAsRoot` if (address(_world()) == address(this)) revert RootSystemLib_CallingFromRootSystem(); - bytes memory systemCall = abi.encodeCall(RootSystem.setValueInA, (thing)); + bytes memory systemCall = abi.encodeCall(_IsetValueInA_ASystemThing.setValueInA, (thing)); self.from == address(0) ? _world().call(self.systemId, systemCall) : _world().callFrom(self.from, self.systemId, systemCall); @@ -59,7 +59,7 @@ library RootSystemLib { // if the contract calling this function is a root system, it should use `callAsRoot` if (address(_world()) == address(this)) revert RootSystemLib_CallingFromRootSystem(); - bytes memory systemCall = abi.encodeCall(RootSystem.getValueFromA, ()); + bytes memory systemCall = abi.encodeCall(_IgetValueFromA.getValueFromA, ()); bytes memory worldCall = self.from == address(0) ? abi.encodeCall(IWorldCall.call, (self.systemId, systemCall)) : abi.encodeCall(IWorldCall.callFrom, (self.from, self.systemId, systemCall)); @@ -71,7 +71,7 @@ library RootSystemLib { } function setValueInA(RootCallWrapper memory self, ASystemThing memory thing) internal { - bytes memory systemCall = abi.encodeCall(RootSystem.setValueInA, (thing)); + bytes memory systemCall = abi.encodeCall(_IsetValueInA_ASystemThing.setValueInA, (thing)); SystemCall.callWithHooksOrRevert(self.from, self.systemId, systemCall, msg.value); } @@ -104,6 +104,18 @@ library RootSystemLib { } } +/** + * These interfaces are used to support overloaded functions + */ + +interface _IsetValueInA_ASystemThing { + function setValueInA(ASystemThing memory thing) external; +} + +interface _IgetValueFromA { + function getValueFromA() external; +} + using RootSystemLib for RootSystemType global; using RootSystemLib for CallWrapper global; using RootSystemLib for RootCallWrapper global;