Skip to content

Commit

Permalink
feat(world-modules): add validateCallWithSignature to `Unstable_Cal…
Browse files Browse the repository at this point in the history
…lWithSignatureModule` (#2614)
  • Loading branch information
alvrs authored Apr 5, 2024
1 parent 6c9767c commit 081c396
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 19 deletions.
5 changes: 5 additions & 0 deletions .changeset/fresh-horses-type.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@latticexyz/world-modules": patch
---

Added `validateCallWithSignature` function to `Unstable_CallWithSignatureModule` to validate a signature without executing the call.
2 changes: 1 addition & 1 deletion packages/world-modules/gas-report.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"file": "test/CallWithSignatureModule.t.sol",
"test": "testRegisterDelegationWithSignature",
"name": "register an unlimited delegation with signature",
"gasUsed": 133222
"gasUsed": 133659
},
{
"file": "test/ERC20.t.sol",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import { ResourceId } from "@latticexyz/store/src/ResourceId.sol";
* @dev This interface is automatically generated from the corresponding system contract. Do not edit manually.
*/
interface IUnstable_CallWithSignatureSystem {
error InvalidSignature(address signer);

function callWithSignature(
address signer,
ResourceId systemId,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.24;

interface IUnstable_CallWithSignatureErrors {
/**
* @dev Mismatched signature.
*/
error InvalidSignature(address signer);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@ import { createDelegation } from "@latticexyz/world/src/modules/init/implementat
import { CallWithSignatureNonces } from "./tables/CallWithSignatureNonces.sol";
import { getSignedMessageHash } from "./getSignedMessageHash.sol";
import { ECDSA } from "./ECDSA.sol";
import { validateCallWithSignature } from "./validateCallWithSignature.sol";
import { IUnstable_CallWithSignatureErrors } from "./IUnstable_CallWithSignatureErrors.sol";

contract Unstable_CallWithSignatureSystem is System {
/**
* @dev Mismatched signature.
*/
error InvalidSignature(address signer);

contract Unstable_CallWithSignatureSystem is System, IUnstable_CallWithSignatureErrors {
/**
* @notice Calls a system with a given system ID using the given signature.
* @param signer The address on whose behalf the system is called.
Expand All @@ -30,16 +27,9 @@ contract Unstable_CallWithSignatureSystem is System {
bytes memory callData,
bytes memory signature
) external payable returns (bytes memory) {
uint256 nonce = CallWithSignatureNonces.get(signer);
bytes32 hash = getSignedMessageHash(signer, systemId, callData, nonce, _world());

// If the message was not signed by the delegator or is invalid, revert
address recoveredSigner = ECDSA.recover(hash, signature);
if (recoveredSigner != signer) {
revert InvalidSignature(recoveredSigner);
}
validateCallWithSignature(signer, systemId, callData, signature);

CallWithSignatureNonces.set(signer, nonce + 1);
CallWithSignatureNonces._set(signer, CallWithSignatureNonces._get(signer) + 1);

return SystemCall.callWithHooksOrRevert(signer, systemId, callData, _msgValue());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.24;
import { ResourceId } from "@latticexyz/world/src/WorldResourceId.sol";
import { WorldContextConsumerLib } from "@latticexyz/world/src/WorldContext.sol";
import { CallWithSignatureNonces } from "./tables/CallWithSignatureNonces.sol";
import { getSignedMessageHash } from "./getSignedMessageHash.sol";
import { ECDSA } from "./ECDSA.sol";
import { IUnstable_CallWithSignatureErrors } from "./IUnstable_CallWithSignatureErrors.sol";

/**
* @notice Verifies the given system call corresponds to the given signature.
* @param signer The address on whose behalf the system is called.
* @param systemId The ID of the system to be called.
* @param callData The ABI data for the system call.
* @param signature The EIP712 signature.
* @dev Reverts with InvalidSignature(recoveredSigner) if the signature is invalid.
*/
function validateCallWithSignature(
address signer,
ResourceId systemId,
bytes memory callData,
bytes memory signature
) view {
uint256 nonce = CallWithSignatureNonces._get(signer);
bytes32 hash = getSignedMessageHash(signer, systemId, callData, nonce, WorldContextConsumerLib._world());

// If the message was not signed by the delegator or is invalid, revert
address recoveredSigner = ECDSA.recover(hash, signature);
if (recoveredSigner != signer) {
revert IUnstable_CallWithSignatureErrors.InvalidSignature(recoveredSigner);
}
}
3 changes: 2 additions & 1 deletion packages/world-modules/test/CallWithSignatureModule.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { WorldTestSystem } from "@latticexyz/world/test/World.t.sol";

import { Unstable_CallWithSignatureModule } from "../src/modules/delegation/Unstable_CallWithSignatureModule.sol";
import { Unstable_CallWithSignatureSystem } from "../src/modules/delegation/Unstable_CallWithSignatureSystem.sol";
import { IUnstable_CallWithSignatureErrors } from "../src/modules/delegation/IUnstable_CallWithSignatureErrors.sol";
import { getSignedMessageHash } from "../src/modules/delegation/getSignedMessageHash.sol";
import { ECDSA } from "../src/modules/delegation/ECDSA.sol";

Expand Down Expand Up @@ -102,7 +103,7 @@ contract Unstable_CallWithSignatureModuleTest is Test, GasReporter {
// Attempt to register a limited delegation using an old signature
vm.expectRevert(
abi.encodeWithSelector(
Unstable_CallWithSignatureSystem.InvalidSignature.selector,
IUnstable_CallWithSignatureErrors.InvalidSignature.selector,
0x824E5E0aF3eA693b906527Dc41E4a29F037d515b
)
);
Expand Down

0 comments on commit 081c396

Please sign in to comment.