Skip to content

Commit

Permalink
[#4] Add test case for protocol mediator, run yarn fmt:ts
Browse files Browse the repository at this point in the history
  • Loading branch information
akshay-ap committed Jun 26, 2023
1 parent abc7d00 commit 7c5a350
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 68 deletions.
4 changes: 4 additions & 0 deletions contracts/test/TestModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ abstract contract BaseTestModule is ISafeProtocolModule {
bool public requiresRootAccess = false;

function metaProvider() external view override returns (uint256 providerType, bytes memory location) {}

function setRequiresRootAccess(bool _requiresRootAccess) external {
requiresRootAccess = _requiresRootAccess;
}
}

contract TestModule is BaseTestModule {
Expand Down
165 changes: 102 additions & 63 deletions test/SafeProtocolMediator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,30 @@ import { loadFixture } from "@nomicfoundation/hardhat-toolbox/network-helpers";
import { expect } from "chai";
import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers";
import BigNumber from "bignumber.js";
import { TestModule } from "../typechain-types";

describe("SafeProtocolMediator", async () => {
let deployer: SignerWithAddress, owner: SignerWithAddress, user1: SignerWithAddress, user2: SignerWithAddress;

async function deployContractFixture() {
[deployer, owner, user1, user2]= await hre.ethers.getSigners();
[deployer, owner, user1, user2] = await hre.ethers.getSigners();
const safeProtocolMediator = await (await hre.ethers.getContractFactory("SafeProtocolMediator")).deploy(owner.address);
return { safeProtocolMediator };
}

describe("Setup mediator", async()=>{
describe("Setup mediator", async () => {
it("Should set mediator as a module for a safe", async () => {
const safe = await hre.ethers.deployContract("TestExecutor");

const { safeProtocolMediator } = await loadFixture(deployContractFixture);
await safe.setModule(await safeProtocolMediator.getAddress());
});
})


describe("Modules", async()=>{
});

describe("Modules", async () => {
async function deployContractsFixture() {
// TODO: Reuse parent fixture
[deployer, owner, user1, user2]= await hre.ethers.getSigners();
[deployer, owner, user1, user2] = await hre.ethers.getSigners();
const safeProtocolMediator = await (await hre.ethers.getContractFactory("SafeProtocolMediator")).deploy(owner.address);
const safe = await hre.ethers.deployContract("TestExecutor");
const module = await (await hre.ethers.getContractFactory("TestModule")).deploy();
Expand All @@ -41,63 +40,65 @@ describe("SafeProtocolMediator", async () => {
await safe.exec(await safeProtocolMediator.getAddress(), 0, data);
// TODO: Check for emitted events and param values
expect(await safeProtocolMediator.getModuleInfo(await safe.getAddress(), await module.getAddress())).to.eql([true, false]);

});

it("Should fail to enable a module (with non root access) with root access", async () => {

const { safeProtocolMediator, safe, module } = await loadFixture(deployContractsFixture);
await safe.setModule(await safeProtocolMediator.getAddress());
const data = safeProtocolMediator.interface.encodeFunctionData("enableModule", [await module.getAddress(), true]);

await expect(safe.exec(await safeProtocolMediator.getAddress(), 0, data)).to.be.revertedWithCustomError(safeProtocolMediator, "ModuleAccessMismatch");
expect(await safeProtocolMediator.getModuleInfo(await safe.getAddress(), await module.getAddress())).to.eql([false, false]);

await expect(safe.exec(await safeProtocolMediator.getAddress(), 0, data)).to.be.revertedWithCustomError(
safeProtocolMediator,
"ModuleAccessMismatch",
);
expect(await safeProtocolMediator.getModuleInfo(await safe.getAddress(), await module.getAddress())).to.eql([false, false]);
});

it("Should disable a module", async () => {
const { safeProtocolMediator, safe, module } = await loadFixture(deployContractsFixture);
await safe.setModule(await safeProtocolMediator.getAddress());
const data = safeProtocolMediator.interface.encodeFunctionData("enableModule", [await module.getAddress(), false]);
await safe.exec(await safeProtocolMediator.getAddress(), 0, data);
expect(await safeProtocolMediator.getModuleInfo(await safe.getAddress(), await module.getAddress())).to.eql([true, false]);

const data2 = safeProtocolMediator.interface.encodeFunctionData("disableModule", [await module.getAddress()]);
await safe.exec(await safeProtocolMediator.getAddress(), 0, data2);
// TODO: Check for emitted events and param values
expect(await safeProtocolMediator.getModuleInfo(await safe.getAddress(), await module.getAddress())).to.eql([false, false]);
});
})

describe("Execute transaction from module", async()=>{
});

describe("Execute transaction from module", async () => {
async function deployContractsFixture() {
[deployer, owner, user1, user2]= await hre.ethers.getSigners();
[deployer, owner, user1, user2] = await hre.ethers.getSigners();
const safeProtocolMediator = await (await hre.ethers.getContractFactory("SafeProtocolMediator")).deploy(owner.address);
const safe = await hre.ethers.deployContract("TestExecutor");
await safe.setModule(await safeProtocolMediator.getAddress());

return { safeProtocolMediator, safe };
}

it("Should not allow non-enabled module to execute tx from a safe", async()=>{
it("Should not allow non-enabled module to execute tx from a safe", async () => {
const { safeProtocolMediator, safe } = await loadFixture(deployContractsFixture);
const module = await (await hre.ethers.getContractFactory("TestModule")).deploy();
// TODO: Replace with builder function
const safeTx = {
actions: [
{
to: user2.address,
value: hre.ethers.parseEther("1"),
data: "0x",
}
],
nonce: 1,
metaHash: hre.ethers.randomBytes(32),
};

await expect(module.executeFromModule(safeProtocolMediator, safe, safeTx)).to.be.revertedWithCustomError(safeProtocolMediator, "MoudleNotEnabled");
})
// TODO: Replace with builder function
const safeTx = {
actions: [
{
to: user2.address,
value: hre.ethers.parseEther("1"),
data: "0x",
},
],
nonce: 1,
metaHash: hre.ethers.randomBytes(32),
};

await expect(module.executeFromModule(safeProtocolMediator, safe, safeTx)).to.be.revertedWithCustomError(
safeProtocolMediator,
"MoudleNotEnabled",
);
});

it("Should process a SafeTransaction", async function () {
const { safeProtocolMediator, safe } = await loadFixture(deployContractsFixture);
Expand All @@ -108,22 +109,24 @@ describe("SafeProtocolMediator", async () => {
await safe.exec(await safeProtocolMediator.getAddress(), 0, data);

const amount = hre.ethers.parseEther("1");
await(await deployer.sendTransaction({
to: await safe.getAddress(),
value: amount,
})).wait();
// TODO: Replace with builder function
const safeTx = {
actions: [
{
to: user2.address,
value: hre.ethers.parseEther("1"),
data: "0x",
}
],
nonce: 1,
metaHash: hre.ethers.randomBytes(32),
};
await (
await deployer.sendTransaction({
to: await safe.getAddress(),
value: amount,
})
).wait();
// TODO: Replace with builder function
const safeTx = {
actions: [
{
to: user2.address,
value: hre.ethers.parseEther("1"),
data: "0x",
},
],
nonce: 1,
metaHash: hre.ethers.randomBytes(32),
};

const balanceBefore = (await hre.ethers.provider.getBalance(user2.address)).toString();
const tx = await module.executeFromModule(safeProtocolMediator, safe, safeTx);
Expand All @@ -133,10 +136,12 @@ describe("SafeProtocolMediator", async () => {
expect(BigNumber(balanceAfter)).to.eql(BigNumber(balanceBefore).plus(amount.toString()));
expect((await hre.ethers.provider.getBalance(await safe.getAddress())).toString()).to.eql("0");

await expect(tx).to.emit(safeProtocolMediator, "ActionsExecuted").withArgs(await safe.getAddress(), safeTx.metaHash);
});
await expect(tx)
.to.emit(safeProtocolMediator, "ActionsExecuted")
.withArgs(await safe.getAddress(), safeTx.metaHash);
});

it("Should fail to process a SafeTransaction", async function () {
it("Should fail to process a SafeTransaction", async function () {
const { safeProtocolMediator, safe } = await loadFixture(deployContractsFixture);

// Enable module
Expand All @@ -146,10 +151,10 @@ describe("SafeProtocolMediator", async () => {
const safeTx = {
actions: [
{
to: user2.address,
value: hre.ethers.parseEther("1"),
data: "0x",
}
to: user2.address,
value: hre.ethers.parseEther("1"),
data: "0x",
},
],
nonce: 1,
metaHash: hre.ethers.randomBytes(32),
Expand All @@ -160,11 +165,45 @@ describe("SafeProtocolMediator", async () => {
const balanceAfter = (await hre.ethers.provider.getBalance(user2.address)).toString();
expect(BigNumber(balanceAfter)).to.eql(BigNumber(balanceBefore));

console.log(txr);
await expect(tx)
.to.emit(safeProtocolMediator, "ActionExecutionFailed")
.withArgs(await safe.getAddress(), safeTx.metaHash, 0);
});

it("Should not process a SafeTransaction when executing non-root access from root access module", async function () {
const { safeProtocolMediator, safe } = await loadFixture(deployContractsFixture);

// Enable module
const module = await (await hre.ethers.getContractFactory("TestModule")).deploy();
const data = safeProtocolMediator.interface.encodeFunctionData("enableModule", [await module.getAddress(), false]);
await safe.exec(await safeProtocolMediator.getAddress(), 0, data);

await module.setRequiresRootAccess(true);

const amount = hre.ethers.parseEther("1");
await (
await deployer.sendTransaction({
to: await safe.getAddress(),
value: amount,
})
).wait();
// TODO: Replace with builder function
const safeTx = {
actions: [
{
to: user2.address,
value: hre.ethers.parseEther("1"),
data: "0x",
},
],
nonce: 1,
metaHash: hre.ethers.randomBytes(32),
};

await expect(tx).to.emit(safeProtocolMediator, "ActionExecutionFailed").withArgs(await safe.getAddress(), safeTx.metaHash, 0);
});

await expect(module.executeFromModule(safeProtocolMediator, safe, safeTx)).to.be.revertedWithCustomError(
safeProtocolMediator,
"ModuleRequiresRootAccess",
);
});

});
});
7 changes: 2 additions & 5 deletions test/SafeProtocolRegistry.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe("SafeProtocolRegistry", async () => {
let deployer: SignerWithAddress, owner: SignerWithAddress, user1: SignerWithAddress, user2: SignerWithAddress;

async function deployContractFixture() {
[deployer, owner, user1, user2]= await ethers.getSigners();
[deployer, owner, user1, user2] = await ethers.getSigners();
const safeProtocolRegistry = await ethers.deployContract("SafeProtocolRegistry", [owner.address]);
return { safeProtocolRegistry };
}
Expand All @@ -34,15 +34,12 @@ describe("SafeProtocolRegistry", async () => {
const { safeProtocolRegistry } = await loadFixture(deployContractFixture);
await safeProtocolRegistry.connect(owner).addComponent(AddressZero);

await expect(safeProtocolRegistry.connect(user1).flagComponent(AddressZero)).to.be.revertedWith(
"Ownable: caller is not the owner"
);
await expect(safeProtocolRegistry.connect(user1).flagComponent(AddressZero)).to.be.revertedWith("Ownable: caller is not the owner");

expect(await safeProtocolRegistry.connect(owner).flagComponent(AddressZero));

const [listedAt, flaggedAt] = await safeProtocolRegistry.check(AddressZero);
expect(flaggedAt).to.be.gt(0);

});

it("Should return (0,0) for non-listed component", async () => {
Expand Down

0 comments on commit 7c5a350

Please sign in to comment.