diff --git a/packages/world/src/ICustomUnregisterDelegation.sol b/packages/world/src/ICustomUnregisterDelegation.sol new file mode 100644 index 0000000000..80fc597355 --- /dev/null +++ b/packages/world/src/ICustomUnregisterDelegation.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.24; + +import { IERC165 } from "./IERC165.sol"; + +interface ICustomUnregisterDelegation is IERC165 { + function canUnregister() external returns (bool); +} diff --git a/packages/world/src/IWorldErrors.sol b/packages/world/src/IWorldErrors.sol index e702f86695..c0167a89dc 100644 --- a/packages/world/src/IWorldErrors.sol +++ b/packages/world/src/IWorldErrors.sol @@ -80,6 +80,12 @@ interface IWorldErrors { */ error World_UnlimitedDelegationNotAllowed(); + /** + * @notice Raised when unregister delegation is called but a custom unregister delegation blocks it + * e.g. if the delegation agreement wanted to enforce some conditions before allowing the delegation to be removed + */ + error World_CustomUnregisterDelegationNotAllowed(); + /** * @notice Raised when there's an insufficient balance for a particular operation. * @param balance The current balance. diff --git a/packages/world/src/modules/init/implementations/WorldRegistrationSystem.sol b/packages/world/src/modules/init/implementations/WorldRegistrationSystem.sol index a7d3dc1fe3..195e593c03 100644 --- a/packages/world/src/modules/init/implementations/WorldRegistrationSystem.sol +++ b/packages/world/src/modules/init/implementations/WorldRegistrationSystem.sol @@ -21,6 +21,8 @@ import { NamespaceDelegationControl } from "../../../codegen/tables/NamespaceDel import { ISystemHook } from "../../../ISystemHook.sol"; import { IWorldErrors } from "../../../IWorldErrors.sol"; import { IDelegationControl } from "../../../IDelegationControl.sol"; +import { ICustomUnregisterDelegation } from "../../../ICustomUnregisterDelegation.sol"; +import { ERC165Checker } from "../../../ERC165Checker.sol"; import { SystemHooks } from "../../../codegen/tables/SystemHooks.sol"; import { SystemRegistry } from "../../../codegen/tables/SystemRegistry.sol"; @@ -293,6 +295,15 @@ contract WorldRegistrationSystem is System, IWorldErrors, LimitedCallContext { * @param delegatee The address of the delegatee */ function unregisterDelegation(address delegatee) public onlyDelegatecall { + if (ERC165Checker.supportsInterface(delegatee, type(ICustomUnregisterDelegation).interfaceId)) { + (bool canUnregisterSuccess, bytes memory canUnregisterReturnData) = delegatee.call( + abi.encodeCall(ICustomUnregisterDelegation.canUnregister, ()) + ); + if (!canUnregisterSuccess) revert World_CustomUnregisterDelegationNotAllowed(); + canUnregisterSuccess = abi.decode(canUnregisterReturnData, (bool)); + if (!canUnregisterSuccess) revert World_CustomUnregisterDelegationNotAllowed(); + } + // Delete the delegation control contract address UserDelegationControl.deleteRecord({ delegator: _msgSender(), delegatee: delegatee }); }