Skip to content

Commit

Permalink
feat(world-modules): add callWithSignature (#2592)
Browse files Browse the repository at this point in the history
  • Loading branch information
yonadaa authored Apr 3, 2024
1 parent 5a84a2c commit cd7f1c1
Show file tree
Hide file tree
Showing 21 changed files with 207 additions and 305 deletions.
2 changes: 1 addition & 1 deletion e2e/packages/contracts/mud.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export default defineWorld({
},
modules: [
{
name: "Unstable_DelegationWithSignatureModule",
name: "Unstable_CallWithSignatureModule",
root: true,
args: [],
},
Expand Down
108 changes: 0 additions & 108 deletions e2e/packages/sync-test/data/callRegisterDelegationWithSignature.ts

This file was deleted.

37 changes: 37 additions & 0 deletions e2e/packages/sync-test/data/callWithSignature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Page } from "@playwright/test";
import { GetContractReturnType, PublicClient, WalletClient } from "viem";
import { AbiParametersToPrimitiveTypes, ExtractAbiFunction, ExtractAbiFunctionNames } from "abitype";
import CallWithSignatureAbi from "@latticexyz/world-modules/out/Unstable_CallWithSignatureSystem.sol/Unstable_CallWithSignatureSystem.abi.json";

type CallWithSignatureAbi = typeof CallWithSignatureAbi;

type WorldContract = GetContractReturnType<CallWithSignatureAbi, PublicClient, WalletClient>;

type WriteMethodName = ExtractAbiFunctionNames<CallWithSignatureAbi>;
type WriteMethod<TMethod extends WriteMethodName> = ExtractAbiFunction<CallWithSignatureAbi, TMethod>;
type WriteArgs<TMethod extends WriteMethodName> = AbiParametersToPrimitiveTypes<WriteMethod<TMethod>["inputs"]>;

export function callWithSignature(page: Page, args?: WriteArgs<"callWithSignature">) {
return page.evaluate(
([_args, _CallWithSignatureAbi]) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const walletClient = (window as any).walletClient as WalletClient;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const worldContract = (window as any).worldContract as WorldContract;

return walletClient
.writeContract({
address: worldContract.address,
abi: _CallWithSignatureAbi,
functionName: "callWithSignature",
args: _args,
})
.then((tx) => window["waitForTransaction"](tx))
.catch((error) => {
console.error(error);
throw new Error([`Error executing callWithSignature with args:`, JSON.stringify(_args), error].join("\n\n"));
});
},
[args, CallWithSignatureAbi],
);
}
1 change: 1 addition & 0 deletions e2e/packages/sync-test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@latticexyz/store-sync": "link:../../../packages/store-sync",
"@latticexyz/utils": "link:../../../packages/utils",
"@latticexyz/world": "link:../../../packages/world",
"@latticexyz/world-modules": "link:../../../packages/world-modules",
"@viem/anvil": "^0.0.6",
"abitype": "1.0.0",
"chalk": "^5.2.0",
Expand Down
40 changes: 21 additions & 19 deletions e2e/packages/sync-test/registerDelegationWithSignature.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,22 @@ import { deployContracts, startViteServer, startBrowserAndPage, openClientWithRo
import { rpcHttpUrl } from "./setup/constants";
import { waitForInitialSync } from "./data/waitForInitialSync";
import { createBurnerAccount, resourceToHex, transportObserver } from "@latticexyz/common";
import { http, createWalletClient, ClientConfig } from "viem";
import { http, createWalletClient, ClientConfig, encodeFunctionData } from "viem";
import { mudFoundry } from "@latticexyz/common/chains";
import { encodeEntity } from "@latticexyz/store-sync/recs";
import { callPageFunction } from "./data/callPageFunction";
import worldConfig from "@latticexyz/world/mud.config";
import { worldToV1 } from "@latticexyz/world/config/v2";
import { delegationWithSignatureTypes } from "@latticexyz/world/internal";
import { callWithSignatureTypes } from "@latticexyz/world/internal";
import { getWorld } from "./data/getWorld";
import { callRegisterDelegationWithSignature } from "./data/callRegisterDelegationWithSignature";
import { callWithSignature } from "./data/callWithSignature";
import IWorldAbi from "../contracts/out/IWorld.sol/IWorld.abi.json";

const DELEGATOR_PRIVATE_KEY = "0x67bbd1575ecc79b3247c7d7b87a5bc533ccb6a63955a9fefdfaf75853f7cd543";

const worldConfigV1 = worldToV1(worldConfig);

describe("registerDelegationWithSignature", async () => {
describe("callWithSignature", async () => {
const asyncErrorHandler = createAsyncErrorHandler();
let webserver: ViteDevServer;
let browser: Browser;
Expand Down Expand Up @@ -60,38 +61,39 @@ describe("registerDelegationWithSignature", async () => {
});

const worldContract = await getWorld(page);
const systemId = resourceToHex({ type: "system", namespace: "", name: "Registration" });

// Declare delegation parameters
const delegatee = "0x7203e7ADfDF38519e1ff4f8Da7DCdC969371f377";
const delegationControlId = resourceToHex({ type: "system", namespace: "", name: "unlimited" });
const initCallData = "0x";

const callData = encodeFunctionData({
abi: IWorldAbi,
functionName: "registerDelegation",
args: [delegatee, delegationControlId, initCallData],
});

const nonce = 0n;

// Sign registration message
// Sign registration call message
const signature = await delegatorWalletClient.signTypedData({
domain: {
chainId: delegatorWalletClient.chain.id,
verifyingContract: worldContract.address,
},
types: delegationWithSignatureTypes,
primaryType: "Delegation",
types: callWithSignatureTypes,
primaryType: "Call",
message: {
delegatee,
delegationControlId,
initCallData,
delegator: delegator.address,
signer: delegator.address,
systemId,
callData,
nonce,
},
});

// Register the delegation
await callRegisterDelegationWithSignature(page, [
delegatee,
delegationControlId,
initCallData,
delegator.address,
signature,
]);
// Register a delegation
await callWithSignature(page, [delegator.address, systemId, callData, signature]);

// Expect delegation to have been created
const value = await callPageFunction(page, "getComponentValue", [
Expand Down
3 changes: 3 additions & 0 deletions e2e/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions packages/cli/src/utils/defaultModuleContracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import KeysWithValueModuleData from "@latticexyz/world-modules/out/KeysWithValue
import KeysInTableModuleData from "@latticexyz/world-modules/out/KeysInTableModule.sol/KeysInTableModule.json" assert { type: "json" };
import UniqueEntityModuleData from "@latticexyz/world-modules/out/UniqueEntityModule.sol/UniqueEntityModule.json" assert { type: "json" };
// eslint-disable-next-line max-len
import Unstable_DelegationWithSignatureModuleData from "@latticexyz/world-modules/out/Unstable_DelegationWithSignatureModule.sol/Unstable_DelegationWithSignatureModule.json" assert { type: "json" };
import Unstable_CallWithSignatureModuleData from "@latticexyz/world-modules/out/Unstable_CallWithSignatureModule.sol/Unstable_CallWithSignatureModule.json" assert { type: "json" };
import { Abi, Hex, size } from "viem";
import { findPlaceholders } from "./findPlaceholders";

Expand Down Expand Up @@ -30,10 +30,10 @@ export const defaultModuleContracts = [
deployedBytecodeSize: size(UniqueEntityModuleData.deployedBytecode.object as Hex),
},
{
name: "Unstable_DelegationWithSignatureModule",
abi: Unstable_DelegationWithSignatureModuleData.abi as Abi,
bytecode: Unstable_DelegationWithSignatureModuleData.bytecode.object as Hex,
placeholders: findPlaceholders(Unstable_DelegationWithSignatureModuleData.bytecode.linkReferences),
deployedBytecodeSize: size(Unstable_DelegationWithSignatureModuleData.deployedBytecode.object as Hex),
name: "Unstable_CallWithSignatureModule",
abi: Unstable_CallWithSignatureModuleData.abi as Abi,
bytecode: Unstable_CallWithSignatureModuleData.bytecode.object as Hex,
placeholders: findPlaceholders(Unstable_CallWithSignatureModuleData.bytecode.linkReferences),
deployedBytecodeSize: size(Unstable_CallWithSignatureModuleData.deployedBytecode.object as Hex),
},
];
8 changes: 4 additions & 4 deletions packages/world-modules/gas-report.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
[
{
"file": "test/DelegationWithSignatureModule.t.sol",
"file": "test/CallWithSignatureModule.t.sol",
"test": "testInstallRoot",
"name": "install delegation module",
"gasUsed": 689194
"gasUsed": 687912
},
{
"file": "test/DelegationWithSignatureModule.t.sol",
"file": "test/CallWithSignatureModule.t.sol",
"test": "testRegisterDelegationWithSignature",
"name": "register an unlimited delegation with signature",
"gasUsed": 117588
"gasUsed": 133222
},
{
"file": "test/ERC20.t.sol",
Expand Down
8 changes: 4 additions & 4 deletions packages/world-modules/mud.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,9 @@ export default defineWorld({
* REGISTER DELEGATION WITH SIGNATURE MODULE
*
************************************************************************/
UserDelegationNonces: {
schema: { delegator: "address", nonce: "uint256" },
key: ["delegator"],
CallWithSignatureNonces: {
schema: { signer: "address", nonce: "uint256" },
key: ["signer"],
codegen: {
outputDirectory: "modules/delegation/tables",
},
Expand All @@ -291,6 +291,6 @@ export default defineWorld({
"PuppetFactorySystem",
"ERC20System",
"ERC721System",
"Unstable_DelegationWithSignatureSystem",
"Unstable_CallWithSignatureSystem",
],
});
2 changes: 1 addition & 1 deletion packages/world-modules/src/index.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ import { Owners } from "./modules/erc721-puppet/tables/Owners.sol";
import { TokenApproval } from "./modules/erc721-puppet/tables/TokenApproval.sol";
import { OperatorApproval } from "./modules/erc721-puppet/tables/OperatorApproval.sol";
import { ERC721Registry } from "./modules/erc721-puppet/tables/ERC721Registry.sol";
import { UserDelegationNonces } from "./modules/delegation/tables/UserDelegationNonces.sol";
import { CallWithSignatureNonces } from "./modules/delegation/tables/CallWithSignatureNonces.sol";

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,25 @@ import { IBaseWorld } from "@latticexyz/world/src/codegen/interfaces/IBaseWorld.
import { Module } from "@latticexyz/world/src/Module.sol";
import { revertWithBytes } from "@latticexyz/world/src/revertWithBytes.sol";

import { UserDelegationNonces } from "./tables/UserDelegationNonces.sol";
import { Unstable_DelegationWithSignatureSystem } from "./Unstable_DelegationWithSignatureSystem.sol";
import { CallWithSignatureNonces } from "./tables/CallWithSignatureNonces.sol";
import { Unstable_CallWithSignatureSystem } from "./Unstable_CallWithSignatureSystem.sol";

import { DELEGATION_SYSTEM_ID } from "./constants.sol";

contract Unstable_DelegationWithSignatureModule is Module {
Unstable_DelegationWithSignatureSystem private immutable delegationWithSignatureSystem =
new Unstable_DelegationWithSignatureSystem();
contract Unstable_CallWithSignatureModule is Module {
Unstable_CallWithSignatureSystem private immutable callWithSignatureSystem = new Unstable_CallWithSignatureSystem();

function installRoot(bytes memory encodedArgs) public {
requireNotInstalled(__self, encodedArgs);

IBaseWorld world = IBaseWorld(_world());

// Register table
UserDelegationNonces._register();
CallWithSignatureNonces._register();

// Register system
(bool success, bytes memory data) = address(world).delegatecall(
abi.encodeCall(world.registerSystem, (DELEGATION_SYSTEM_ID, delegationWithSignatureSystem, true))
abi.encodeCall(world.registerSystem, (DELEGATION_SYSTEM_ID, callWithSignatureSystem, true))
);
if (!success) revertWithBytes(data);

Expand All @@ -35,8 +34,8 @@ contract Unstable_DelegationWithSignatureModule is Module {
world.registerRootFunctionSelector,
(
DELEGATION_SYSTEM_ID,
"registerDelegationWithSignature(address,bytes32,bytes,address,bytes)",
"registerDelegationWithSignature(address,bytes32,bytes,address,bytes)"
"callWithSignature(address,bytes32,bytes,bytes)",
"callWithSignature(address,bytes32,bytes,bytes)"
)
)
);
Expand Down
Loading

0 comments on commit cd7f1c1

Please sign in to comment.