UNPKG

@safe-global/safe-contracts

Version:
167 lines (141 loc) 7.63 kB
import { expect } from "chai"; import hre, { deployments, waffle } from "hardhat"; import { BigNumber } from "ethers"; import "@nomiclabs/hardhat-ethers"; import { AddressZero } from "@ethersproject/constants"; import { defaultTokenCallbackHandlerContract, defaultTokenCallbackHandlerDeployment, deployContract, getSafeTemplate, } from "../utils/setup"; import { executeContractCallWithSigners } from "../../src/utils/execution"; describe("FallbackManager", async () => { const setupWithTemplate = deployments.createFixture(async ({ deployments }) => { await deployments.fixture(); const source = ` contract Mirror { function lookAtMe() public returns (bytes memory) { return msg.data; } function nowLookAtYou(address you, string memory howYouLikeThat) public returns (bytes memory) { return msg.data; } }`; const mirror = await deployContract(user1, source); return { safe: await getSafeTemplate(), mirror, }; }); const [user1, user2] = waffle.provider.getWallets(); describe("setFallbackManager", async () => { it("is correctly set on deployment", async () => { const { safe } = await setupWithTemplate(); const handler = await defaultTokenCallbackHandlerDeployment(); // Check fallback handler await expect( await hre.ethers.provider.getStorageAt(safe.address, "0x6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d5"), ).to.be.eq("0x" + "".padStart(64, "0")); // Setup Safe await safe.setup([user1.address, user2.address], 1, AddressZero, "0x", handler.address, AddressZero, 0, AddressZero); // Check fallback handler await expect( await hre.ethers.provider.getStorageAt(safe.address, "0x6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d5"), ).to.be.eq("0x" + handler.address.toLowerCase().slice(2).padStart(64, "0")); }); it("is correctly set", async () => { const { safe } = await setupWithTemplate(); const handler = await defaultTokenCallbackHandlerDeployment(); // Setup Safe await safe.setup([user1.address, user2.address], 1, AddressZero, "0x", AddressZero, AddressZero, 0, AddressZero); // Check fallback handler await expect( await hre.ethers.provider.getStorageAt(safe.address, "0x6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d5"), ).to.be.eq("0x" + "".padStart(64, "0")); await expect(executeContractCallWithSigners(safe, safe, "setFallbackHandler", [handler.address], [user1])) .to.emit(safe, "ChangedFallbackHandler") .withArgs(handler.address); // Check fallback handler await expect( await hre.ethers.provider.getStorageAt(safe.address, "0x6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d5"), ).to.be.eq("0x" + handler.address.toLowerCase().slice(2).padStart(64, "0")); }); it("emits event when is set", async () => { const { safe } = await setupWithTemplate(); const handler = await defaultTokenCallbackHandlerDeployment(); // Setup Safe await safe.setup([user1.address, user2.address], 1, AddressZero, "0x", AddressZero, AddressZero, 0, AddressZero); // Check event await expect(executeContractCallWithSigners(safe, safe, "setFallbackHandler", [handler.address], [user1])) .to.emit(safe, "ChangedFallbackHandler") .withArgs(handler.address); }); it("is called when set", async () => { const { safe } = await setupWithTemplate(); const handler = await defaultTokenCallbackHandlerDeployment(); const safeHandler = (await defaultTokenCallbackHandlerContract()).attach(safe.address); // Check that Safe is NOT setup await expect(await safe.getThreshold()).to.be.deep.eq(BigNumber.from(0)); // Check unset callbacks await expect(safeHandler.callStatic.onERC1155Received(AddressZero, AddressZero, 0, 0, "0x")).to.be.reverted; // Setup Safe await safe.setup([user1.address, user2.address], 1, AddressZero, "0x", handler.address, AddressZero, 0, AddressZero); // Check callbacks await expect(await safeHandler.callStatic.onERC1155Received(AddressZero, AddressZero, 0, 0, "0x")).to.be.eq("0xf23a6e61"); }); it("sends along msg.sender on simple call", async () => { const { safe, mirror } = await setupWithTemplate(); // Setup Safe await safe.setup([user1.address, user2.address], 1, AddressZero, "0x", mirror.address, AddressZero, 0, AddressZero); const tx = { to: safe.address, data: mirror.interface.encodeFunctionData("lookAtMe"), }; // Check that mock works as handler const response = await user1.call(tx); expect(response).to.be.eq( "0x" + "0000000000000000000000000000000000000000000000000000000000000020" + "0000000000000000000000000000000000000000000000000000000000000018" + "7f8dc53c" + user1.address.slice(2).toLowerCase() + "0000000000000000", ); }); it("sends along msg.sender on more complex call", async () => { const { safe, mirror } = await setupWithTemplate(); // Setup Safe await safe.setup([user1.address, user2.address], 1, AddressZero, "0x", mirror.address, AddressZero, 0, AddressZero); const tx = { to: safe.address, data: mirror.interface.encodeFunctionData("nowLookAtYou", [user2.address, "pink<>black"]), }; // Check that mock works as handler const response = await user1.call(tx); expect(response).to.be.eq( "0x" + "0000000000000000000000000000000000000000000000000000000000000020" + "0000000000000000000000000000000000000000000000000000000000000098" + // Function call "b2a88d99" + "000000000000000000000000" + user2.address.slice(2).toLowerCase() + "0000000000000000000000000000000000000000000000000000000000000040" + "000000000000000000000000000000000000000000000000000000000000000b" + "70696e6b3c3e626c61636b000000000000000000000000000000000000000000" + user1.address.slice(2).toLowerCase() + "0000000000000000", ); }); it("cannot be set to self", async () => { const { safe } = await setupWithTemplate(); // Setup Safe await safe.setup([user1.address], 1, AddressZero, "0x", AddressZero, AddressZero, 0, AddressZero); // The transaction execution function doesn't bubble up revert messages so we check for a generic transaction fail code GS013 await expect(executeContractCallWithSigners(safe, safe, "setFallbackHandler", [safe.address], [user1])).to.be.revertedWith( "GS013", ); }); }); });