Skip to content

Commit

Permalink
verify signatures for transfer with auth
Browse files Browse the repository at this point in the history
  • Loading branch information
gsteenkamp89 committed Jan 3, 2025
1 parent 1cbee1f commit c65212b
Showing 1 changed file with 116 additions and 28 deletions.
144 changes: 116 additions & 28 deletions api/relay/_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from "../_spoke-pool-periphery";
import { RelayRequest } from "./_types";
import { redisCache } from "../_cache";
import { getTransferWithAuthTypedData } from "../_transfer-with-auth";

export const GAS_SPONSOR_ADDRESS =
process.env.GAS_SPONSOR_ADDRESS ??
Expand Down Expand Up @@ -131,10 +132,15 @@ export async function verifySignatures({
const { methodName, args } = methodNameAndArgs;

let signatureOwner: string;
let getPermitTypedDataPromise: ReturnType<typeof getPermitTypedData>;
let getPermitTypedDataPromise:
| ReturnType<typeof getPermitTypedData>
| undefined;
let getDepositTypedDataPromise: ReturnType<
typeof getDepositTypedData | typeof getSwapAndDepositTypedData
>;
let getTransferWithAuthTypedDataPromise:
| ReturnType<typeof getTransferWithAuthTypedData>
| undefined;

if (methodName === "depositWithPermit") {
const { signatureOwner: _signatureOwner, deadline, depositData } = args;
Expand Down Expand Up @@ -170,41 +176,123 @@ export async function verifySignatures({
chainId,
swapAndDepositData,
});
} else if (methodName === "depositWithAuthorization") {
const {
signatureOwner: _signatureOwner,
validAfter,
validBefore,
nonce,
depositData,
} = args;
signatureOwner = _signatureOwner;
getTransferWithAuthTypedDataPromise = getTransferWithAuthTypedData({
tokenAddress: depositData.baseDepositData.inputToken,
chainId,
ownerAddress: signatureOwner,
spenderAddress: to, // SpokePoolV3Periphery address
value: depositData.inputAmount,
validAfter: Number(validAfter),
validBefore: Number(validBefore),
nonce,
});
getDepositTypedDataPromise = getDepositTypedData({
chainId,
depositData,
});
} else if (methodName === "swapAndBridgeWithAuthorization") {
const {
signatureOwner: _signatureOwner,
validAfter,
validBefore,
nonce,
swapAndDepositData,
} = args;
signatureOwner = _signatureOwner;
getTransferWithAuthTypedDataPromise = getTransferWithAuthTypedData({
tokenAddress: swapAndDepositData.swapToken,
chainId,
ownerAddress: signatureOwner,
spenderAddress: to, // SpokePoolV3Periphery address
value: swapAndDepositData.swapTokenAmount,
validAfter: Number(validAfter),
validBefore: Number(validBefore),
nonce,
});
getDepositTypedDataPromise = getSwapAndDepositTypedData({
chainId,
swapAndDepositData,
});
} else {
throw new Error(
`Can not verify signatures for invalid method name: ${methodName}`
);
}

const [permitTypedData, depositTypedData] = await Promise.all([
getPermitTypedDataPromise,
getDepositTypedDataPromise,
]);
if (getPermitTypedDataPromise) {
const [permitTypedData, depositTypedData] = await Promise.all([
getPermitTypedDataPromise,
getDepositTypedDataPromise,
]);

const recoveredPermitSignerAddress = utils.verifyTypedData(
permitTypedData.eip712.domain,
permitTypedData.eip712.types,
permitTypedData.eip712.message,
signatures.permit
);

const recoveredPermitSignerAddress = utils.verifyTypedData(
permitTypedData.eip712.domain,
permitTypedData.eip712.types,
permitTypedData.eip712.message,
signatures.permit
);
if (recoveredPermitSignerAddress !== signatureOwner) {
throw new InvalidParamError({
message: "Invalid permit signature",
param: "signatures.permit",
});
}
if (recoveredPermitSignerAddress !== signatureOwner) {
throw new InvalidParamError({
message: "Invalid permit signature",
param: "signatures.permit",
});
}

const recoveredDepositSignerAddress = utils.verifyTypedData(
depositTypedData.eip712.domain,
depositTypedData.eip712.types,
depositTypedData.eip712.message,
signatures.deposit
);
if (recoveredDepositSignerAddress !== signatureOwner) {
throw new InvalidParamError({
message: "Invalid deposit signature",
param: "signatures.deposit",
});
const recoveredDepositSignerAddress = utils.verifyTypedData(
depositTypedData.eip712.domain,
depositTypedData.eip712.types,
depositTypedData.eip712.message,
signatures.deposit
);
if (recoveredDepositSignerAddress !== signatureOwner) {
throw new InvalidParamError({
message: "Invalid deposit signature",
param: "signatures.deposit",
});
}
} else if (getTransferWithAuthTypedDataPromise) {
const [authTypedData, depositTypedData] = await Promise.all([
getTransferWithAuthTypedDataPromise,
getDepositTypedDataPromise,
]);

const recoveredAuthSignerAddress = utils.verifyTypedData(
authTypedData.eip712.domain,
authTypedData.eip712.types,
authTypedData.eip712.message,
signatures.permit
);

if (recoveredAuthSignerAddress !== signatureOwner) {
throw new InvalidParamError({
message: "Invalid Authorization signature",
param: "signatures.permit",
});
}

const recoveredDepositSignerAddress = utils.verifyTypedData(
depositTypedData.eip712.domain,
depositTypedData.eip712.types,
depositTypedData.eip712.message,
signatures.deposit
);

if (recoveredDepositSignerAddress !== signatureOwner) {
throw new InvalidParamError({
message: "Invalid deposit signature",
param: "signatures.deposit",
});
}
}
}

Expand Down

0 comments on commit c65212b

Please sign in to comment.