Skip to content

Commit

Permalink
Tests for sentOrSignedByModule
Browse files Browse the repository at this point in the history
  • Loading branch information
cristovaoth committed Oct 31, 2023
1 parent d0b988c commit 3d56dc2
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 2 deletions.
4 changes: 4 additions & 0 deletions contracts/test/TestModifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ contract TestModifier is Modifier {
target = _target;
}

function exposeSentOrSignedByModule() external view returns (address) {
return sentOrSignedByModule();
}

function attemptToSetupModules() public {
setupModules();
}
Expand Down
101 changes: 99 additions & 2 deletions test/03_Modifier.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
import { expect } from "chai";
import { PopulatedTransaction } from "ethers";
import { keccak256, toUtf8Bytes } from "ethers/lib/utils";
import { defaultAbiCoder, keccak256, toUtf8Bytes } from "ethers/lib/utils";
import hre from "hardhat";

import { TestAvatar__factory, TestModifier__factory } from "../typechain-types";
Expand All @@ -15,7 +15,7 @@ describe("Modifier", async () => {
const SENTINEL_MODULES = "0x0000000000000000000000000000000000000001";

async function setupTests() {
const [signer] = await hre.ethers.getSigners();
const [signer, alice, bob, charlie] = await hre.ethers.getSigners();
const Avatar = await hre.ethers.getContractFactory("TestAvatar");
const avatar = await Avatar.connect(signer).deploy();
const iAvatar = TestAvatar__factory.connect(avatar.address, signer);
Expand All @@ -42,6 +42,9 @@ describe("Modifier", async () => {
iAvatar,
modifier: TestModifier__factory.connect(modifier.address, signer),
tx,
alice,
bob,
charlie,
};
}

Expand Down Expand Up @@ -700,6 +703,81 @@ describe("Modifier", async () => {
).to.be.revertedWithCustomError(modifier, "HashAlreadyConsumed");
});
});

describe("sentOrSignedByModule", async () => {
it("returns msg.sender if msg.sender is module", async () => {
const { modifier, alice, bob } = await loadFixture(setupTests);

await modifier.enableModule(alice.address);
expect(
await modifier.connect(alice).exposeSentOrSignedByModule()
).to.equal(alice.address);

expect(await modifier.connect(bob).exposeSentOrSignedByModule()).to.equal(
AddressZero
);
});

it("returns msg.sender if msg.sender is module, even if valid sig appended", async () => {
const { modifier, alice, bob, charlie } = await loadFixture(setupTests);

await modifier.enableModule(alice.address);
await modifier.enableModule(bob.address);

const transaction = await signTransaction(
modifier.address,
await modifier.populateTransaction.exposeSentOrSignedByModule(),
keccak256(toUtf8Bytes("something salty")),
bob
);

// if alice sends it, msg.sender is taken into account, because alice module
expect(await alice.call(transaction)).to.equal(
defaultAbiCoder.encode(["address"], [alice.address])
);

// if charlie sends it, signature is taken into account because bob module
expect(await charlie.call(transaction)).to.equal(
defaultAbiCoder.encode(["address"], [bob.address])
);
});

it("returns signer if signer is module", async () => {
const { modifier, alice, charlie } = await loadFixture(setupTests);

await modifier.enableModule(alice.address);

const transaction = await signTransaction(
modifier.address,
await modifier.populateTransaction.exposeSentOrSignedByModule(),
keccak256(toUtf8Bytes("something salty")),
alice
);

// if alice sends it, msg.sender is taken into account, because alice module
expect(await charlie.call(transaction)).to.equal(
defaultAbiCoder.encode(["address"], [alice.address])
);
});

it("returns zero if signer is not module and message sender not a module", async () => {
const { modifier, alice, charlie } = await loadFixture(setupTests);

// no modules enabled

const transaction = await signTransaction(
modifier.address,
await modifier.populateTransaction.exposeSentOrSignedByModule(),
keccak256(toUtf8Bytes("something salty")),
alice
);

// if alice sends it, msg.sender is taken into account, because alice module
expect(await charlie.call(transaction)).to.equal(
defaultAbiCoder.encode(["address"], [AddressZero])
);
});
});
});

async function sign(
Expand All @@ -717,3 +795,22 @@ async function sign(

return `${salt}${signature.slice(2)}`;
}

async function signTransaction(
contract: string,
{ from, ...transaction }: PopulatedTransaction,
salt: string,
signer: SignerWithAddress
) {
const { domain, types, message } = typedDataForTransaction(
{ contract, chainId: 31337, salt },
transaction.data || "0x"
);

const signature = await signer._signTypedData(domain, types, message);

return {
...transaction,
data: `${transaction.data as string}${salt.slice(2)}${signature.slice(2)}`,
};
}

0 comments on commit 3d56dc2

Please sign in to comment.