Skip to content

Commit

Permalink
Hot Fix: Safe Nonce Alignment (#81)
Browse files Browse the repository at this point in the history
  • Loading branch information
bh2smith authored Oct 19, 2024
1 parent f23d49b commit 170901e
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 23 deletions.
21 changes: 10 additions & 11 deletions src/lib/safe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,15 @@ export class SafeContractSuite {
this.entryPoint = deployments.entryPoint;
}

async addressForSetup(setup: Hex, saltNonce?: string): Promise<Address> {
async addressForSetup(setup: Hex, saltNonce: string): Promise<Address> {
// bytes32 salt = keccak256(abi.encodePacked(keccak256(initializer), saltNonce));
// cf: https://github.com/safe-global/safe-smart-account/blob/499b17ad0191b575fcadc5cb5b8e3faeae5391ae/contracts/proxies/SafeProxyFactory.sol#L58
const salt = keccak256(
encodePacked(
["bytes32", "uint256"],
[keccak256(setup), BigInt(saltNonce || "0")]
[keccak256(setup), BigInt(saltNonce)]
)
);

// abi.encodePacked(type(SafeProxy).creationCode, uint256(uint160(_singleton)));
// cf: https://github.com/safe-global/safe-smart-account/blob/499b17ad0191b575fcadc5cb5b8e3faeae5391ae/contracts/proxies/SafeProxyFactory.sol#L29
const initCode = encodePacked(
Expand All @@ -85,18 +84,18 @@ export class SafeContractSuite {
abi: this.singleton.abi,
functionName: "setup",
args: [
owners,
1, // We use sign threshold of 1.
this.moduleSetup.address,
owners, // _owners
1, // _threshold
this.moduleSetup.address, // to
encodeFunctionData({
abi: this.moduleSetup.abi,
functionName: "enableModules",
args: [[this.m4337.address]],
}),
this.m4337.address,
zeroAddress,
0,
zeroAddress,
}), // data
this.m4337.address, // fallbackHandler
zeroAddress, // paymentToken
0, // payment
zeroAddress, // paymentReceiver
],
});
}
Expand Down
6 changes: 4 additions & 2 deletions src/near-safe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ export class NearSafe {
* @returns {Promise<NearSafe>} - A promise that resolves to a new `NearSafe` instance.
*/
static async create(config: NearSafeConfig): Promise<NearSafe> {
const { pimlicoKey, safeSaltNonce } = config;
const { pimlicoKey } = config;
const safeSaltNonce = config.safeSaltNonce || DEFAULT_SAFE_SALT_NONCE;

// const nearAdapter = await mockAdapter();
const nearAdapter = await setupAdapter({ ...config });
const safePack = new SafeContractSuite();
Expand All @@ -85,7 +87,7 @@ export class NearSafe {
pimlicoKey,
setup,
safeAddress,
safeSaltNonce || DEFAULT_SAFE_SALT_NONCE
safeSaltNonce
);
}

Expand Down
9 changes: 5 additions & 4 deletions tests/e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import dotenv from "dotenv";

import { NearSafe } from "../src";
import { DEFAULT_SAFE_SALT_NONCE, NearSafe } from "../src";

dotenv.config();
describe("Near Safe Requests", () => {
Expand All @@ -9,6 +9,7 @@ describe("Near Safe Requests", () => {
accountId: "neareth-dev.testnet",
mpcContractId: "v1.signer-prod.testnet",
pimlicoKey: process.env.PIMLICO_KEY!,
safeSaltNonce: DEFAULT_SAFE_SALT_NONCE,
});
const irrelevantData = {
data: "0xbeef",
Expand All @@ -23,10 +24,10 @@ describe("Near Safe Requests", () => {
...irrelevantData,
},
],
usePaymaster: true,
})
).resolves.not.toThrow();
// Can't send raw messages to Safe Contracts.
// Can't send sponsored raw messages to Safe Contracts.
// Because transaction simulation reverts.
await expect(
adapter.buildTransaction({
chainId: 11155111,
Expand All @@ -36,7 +37,7 @@ describe("Near Safe Requests", () => {
...irrelevantData,
},
],
usePaymaster: true,
sponsorshipPolicy: "sp_clear_vampiro",
})
).rejects.toThrow();
});
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/ethers-safe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,14 @@ export class ContractSuite {

async addressForSetup(
setup: ethers.BytesLike,
saltNonce?: string
saltNonce: string
): Promise<Address> {
// bytes32 salt = keccak256(abi.encodePacked(keccak256(initializer), saltNonce));
// cf: https://github.com/safe-global/safe-smart-account/blob/499b17ad0191b575fcadc5cb5b8e3faeae5391ae/contracts/proxies/SafeProxyFactory.sol#L58
const salt = ethers.keccak256(
ethers.solidityPacked(
["bytes32", "uint256"],
[ethers.keccak256(setup), saltNonce || 0]
[ethers.keccak256(setup), saltNonce]
)
);

Expand Down
9 changes: 5 additions & 4 deletions tests/unit/lib/safe.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,13 @@ describe("Safe Pack", () => {
});

it("addressForSetup", async () => {
const saltNonce = "1";
const setup = viemPack.getSetup([zeroAddress]);
const [eps0, vps0, eps1, vps1] = await Promise.all([
ethersPack.addressForSetup(setup),
viemPack.addressForSetup(setup),
ethersPack.addressForSetup(setup, "1"),
viemPack.addressForSetup(setup, "1"),
ethersPack.addressForSetup(setup, saltNonce),
viemPack.addressForSetup(setup, saltNonce),
ethersPack.addressForSetup(setup, saltNonce),
viemPack.addressForSetup(setup, saltNonce),
]);
expect(eps0).toEqual(vps0);
expect(eps1).toEqual(vps1);
Expand Down

0 comments on commit 170901e

Please sign in to comment.