Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support SpokePoolVerifier contract for native and enabled routes #861

Merged
merged 8 commits into from
Oct 11, 2023
Merged
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should reflect this addition to the Goerli route for consistency

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed here 33a177c

Original file line number Diff line number Diff line change
Expand Up @@ -1708,5 +1708,27 @@
"tokenSymbol": "BOBA",
"isNative": false
}
],
"enabledSpokePoolVerifiers": [
{
"chain": 1,
"address": "0x269727F088F16E1Aea52Cf5a97B1CD41DAA3f02D"
},
{
"chain": 10,
"address": "0x269727F088F16E1Aea52Cf5a97B1CD41DAA3f02D"
},
{
"chain": 137,
"address": "0x269727F088F16E1Aea52Cf5a97B1CD41DAA3f02D"
},
{
"chain": 8453,
"address": "0x269727F088F16E1Aea52Cf5a97B1CD41DAA3f02D"
},
{
"chain": 42161,
"address": "0x269727F088F16E1Aea52Cf5a97B1CD41DAA3f02D"
}
james-a-morris marked this conversation as resolved.
Show resolved Hide resolved
]
}
40 changes: 34 additions & 6 deletions src/utils/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,14 +178,34 @@ export async function sendAcrossDeposit(
}: AcrossDepositArgs
): Promise<ethers.providers.TransactionResponse> {
const config = getConfig();
const spokePool = config.getSpokePool(fromChain);
const provider = getProvider(fromChain);
const code = await provider.getCode(spokePool.address);
if (!code) {

// We send native tokens to the SpokePoolVerifier contract if enabled for the chain.
const shouldUseSpokePoolVerifier =
config.enabledSpokePoolVerifierChains.has(fromChain) && isNative;

const spokePool = config.getSpokePool(fromChain);
const spokePoolVerifier = shouldUseSpokePoolVerifier
? config.getSpokePoolVerifier(fromChain)
: undefined;
james-a-morris marked this conversation as resolved.
Show resolved Hide resolved

const [spokePoolCode, spokePoolVerifierCode] = await Promise.all([
provider.getCode(spokePool.address),
spokePoolVerifier
? await provider.getCode(spokePoolVerifier.address)
james-a-morris marked this conversation as resolved.
Show resolved Hide resolved
: Promise.resolve(true),
james-a-morris marked this conversation as resolved.
Show resolved Hide resolved
]);
if (!spokePoolCode) {
throw new Error(`SpokePool not deployed at ${spokePool.address}`);
}
if (!spokePoolVerifierCode) {
james-a-morris marked this conversation as resolved.
Show resolved Hide resolved
throw new Error(
`SpokePoolVerifier not deployed at ${spokePoolVerifier?.address}`
);
}
james-a-morris marked this conversation as resolved.
Show resolved Hide resolved

const value = isNative ? amount : ethers.constants.Zero;
const tx = await spokePool.populateTransaction.deposit(
const commonArgs = [
recipient,
tokenAddress,
amount,
Expand All @@ -194,8 +214,16 @@ export async function sendAcrossDeposit(
quoteTimestamp,
message,
maxCount,
{ value }
);
{ value },
] as const;

const tx = shouldUseSpokePoolVerifier
? await config
.getSpokePoolVerifier(fromChain)
.populateTransaction.deposit(spokePool.address, ...commonArgs)
: await config
.getSpokePool(fromChain)
.populateTransaction.deposit(...commonArgs);

// do not tag a referrer if data is not provided as a hex string.
tx.data =
Expand Down
28 changes: 27 additions & 1 deletion src/utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
HubPool__factory,
SpokePool,
SpokePool__factory,
SpokePoolVerifier,
SpokePoolVerifier__factory,
AcrossMerkleDistributor,
AcrossMerkleDistributor__factory,
AcceleratingDistributor,
Expand All @@ -34,10 +36,12 @@ export class ConfigClient {
public readonly spokeChains: Set<number> = new Set();
public readonly fromChains: Set<number> = new Set();
public readonly toChains: Set<number> = new Set();
public readonly enabledSpokePoolVerifierChains: Set<number> = new Set();
public tokenOrder: Record<string, number> = {};
public chainOrder: Record<string, number> = {};
public routes: constants.Routes = [];
public pools: constants.Pools = [];
public enabledSpokePoolVerifiers: constants.EnabledSpokePoolVerifiers = [];
constructor(
private config: constants.RouteConfig,
private disabledTokens: string[] = []
Expand Down Expand Up @@ -71,8 +75,12 @@ export class ConfigClient {
this.tokenOrder[route.fromTokenSymbol] + this.chainOrder[route.toChain]
);
});
// prioritize routes based on token symbol and tochain. This just gives us better route prioritization when filtering a fromChain
this.pools = this.config.pools;
this.enabledSpokePoolVerifiers =
this.config.enabledSpokePoolVerifiers || [];
this.enabledSpokePoolVerifierChains = new Set(
this.enabledSpokePoolVerifiers.map(({ chain }) => chain)
);
}
getWethAddress(): string {
return this.config.hubPoolWethAddress;
Expand Down Expand Up @@ -105,6 +113,24 @@ export class ConfigClient {
const provider = signer ?? providerUtils.getProvider(chainId);
return SpokePool__factory.connect(address, provider);
}
getSpokePoolVerifierAddress(chainId: constants.ChainId): string {
const enabledSpokePoolVerifier = this.enabledSpokePoolVerifiers.find(
({ chain }) => chain === chainId
);
assert(
enabledSpokePoolVerifier,
"SpokePoolVerifier not supported on chain: " + chainId
);
return enabledSpokePoolVerifier.address;
}
getSpokePoolVerifier(
chainId: constants.ChainId,
signer?: Signer
): SpokePoolVerifier {
const address = this.getSpokePoolVerifierAddress(chainId);
const provider = signer ?? providerUtils.getProvider(chainId);
return SpokePoolVerifier__factory.connect(address, provider);
}
getHubPoolChainId(): constants.ChainId {
return this.config.hubPoolChain;
}
Expand Down
14 changes: 14 additions & 0 deletions src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -503,10 +503,18 @@ const PoolSS = superstruct.object({
tokenSymbol: superstruct.string(),
isNative: superstruct.boolean(),
});
const EnabledSpokePoolVerifierSS = superstruct.object({
chain: superstruct.number(),
address: superstruct.string(),
});
const EnabledSpokePoolVerifiersSS = superstruct.array(
EnabledSpokePoolVerifierSS
);
const PoolsSS = superstruct.array(PoolSS);
const RouteConfigSS = superstruct.type({
routes: RoutesSS,
pools: PoolsSS,
enabledSpokePoolVerifiers: EnabledSpokePoolVerifiersSS,
hubPoolWethAddress: superstruct.string(),
hubPoolChain: superstruct.number(),
hubPoolAddress: superstruct.string(),
Expand All @@ -520,6 +528,12 @@ export type Route = superstruct.Infer<typeof RouteSS>;
export type Routes = superstruct.Infer<typeof RoutesSS>;
export type Pool = superstruct.Infer<typeof PoolSS>;
export type Pools = superstruct.Infer<typeof PoolsSS>;
export type EnabledSpokePoolVerifier = superstruct.Infer<
typeof EnabledSpokePoolVerifierSS
>;
export type EnabledSpokePoolVerifiers = superstruct.Infer<
typeof EnabledSpokePoolVerifiersSS
>;
export function getRoutes(chainId: ChainId): RouteConfig {
if (chainId === ChainId.MAINNET) {
superstruct.assert(MainnetRoutes, RouteConfigSS);
Expand Down
2 changes: 2 additions & 0 deletions src/utils/typechain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
export { AcrossMerkleDistributor__factory } from "@across-protocol/contracts-v2/dist/typechain/factories/contracts/merkle-distributor/AcrossMerkleDistributor__factory";
export { HubPool__factory } from "@across-protocol/contracts-v2/dist/typechain/factories/contracts/HubPool__factory";
export { SpokePool__factory } from "@across-protocol/contracts-v2/dist/typechain/factories/contracts/SpokePool.sol/SpokePool__factory";
export { SpokePoolVerifier__factory } from "@across-protocol/contracts-v2/dist/typechain/factories/contracts/SpokePoolVerifier__factory";
export { ERC20__factory } from "@across-protocol/contracts-v2/dist/typechain/factories/@openzeppelin/contracts/token/ERC20/ERC20__factory";
export { AcceleratingDistributor__factory } from "@across-protocol/across-token/dist/typechain/factories/AcceleratingDistributor__factory";
export { ClaimAndStake__factory } from "@across-protocol/across-token/dist/typechain/factories/ClaimAndStake__factory";

export type { AcrossMerkleDistributor } from "@across-protocol/contracts-v2/dist/typechain/contracts/merkle-distributor/AcrossMerkleDistributor";
export type { HubPool } from "@across-protocol/contracts-v2/dist/typechain/contracts/HubPool";
export type { SpokePool } from "@across-protocol/contracts-v2/dist/typechain/contracts/SpokePool.sol/SpokePool";
export type { SpokePoolVerifier } from "@across-protocol/contracts-v2/dist/typechain/contracts/SpokePoolVerifier";
export type { AcceleratingDistributor } from "@across-protocol/across-token/dist/typechain/AcceleratingDistributor";
export type { ClaimAndStake } from "@across-protocol/across-token/dist/typechain/ClaimAndStake";
export type {
Expand Down
Loading