Skip to content
This repository has been archived by the owner on Jul 10, 2023. It is now read-only.

Refactor and renames #61

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import {Message} from "./libs/Message.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";

/**
* @title Hyperlane Native Token Router that extends ERC20 with remote transfer functionality.
* @title Hyperlane Native Collateral Token Router that extends native asset with remote transfer functionality.
* @author Abacus Works
* @dev Supply on each chain is not constant but the aggregate supply across all chains is.
*/
contract HypNative is TokenRouter {
contract HypNativeCollateral is TokenRouter {
Copy link
Contributor

Choose a reason for hiding this comment

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

Much better name

/**
* @notice Initializes the Hyperlane router, ERC20 metadata, and mints initial supply to deployer.
* @param _mailbox The address of the mailbox contract.
Expand Down
38 changes: 30 additions & 8 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,33 @@ import { BigNumberish } from 'ethers';
import { ChainName, HyperlaneContracts, RouterApp } from '@hyperlane-xyz/sdk';
import { types } from '@hyperlane-xyz/utils';

import { TokenType } from './config';
import {
HypERC20Factories,
HypERC721Factories,
TokenFactories,
} from './contracts';
import { TokenRouter } from './types';
import {
HypERC20,
HypERC20Collateral,
HypERC721,
HypERC721Collateral,
HypNativeCollateral,
TokenRouter,
} from './types';

class HyperlaneTokenApp<
abstract class HyperlaneTokenApp<
Factories extends TokenFactories,
> extends RouterApp<Factories> {
router(contracts: HyperlaneContracts<TokenFactories>): TokenRouter {
return contracts.router;
}
abstract router(contracts: HyperlaneContracts<Factories>): TokenRouter;

async transfer(
origin: ChainName,
destination: ChainName,
recipient: types.Address,
amountOrId: BigNumberish,
) {
const originRouter = this.getContracts(origin).router;
const originRouter = this.router(this.getContracts(origin));
Copy link
Contributor

Choose a reason for hiding this comment

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

This fn does not support native collateral, since value should be gasPayment + amountOrId

const destProvider = this.multiProvider.getProvider(destination);
const destinationNetwork = await destProvider.getNetwork();
const gasPayment = await originRouter.quoteGasPayment(
Expand All @@ -44,13 +50,23 @@ class HyperlaneTokenApp<
}

export class HypERC20App extends HyperlaneTokenApp<HypERC20Factories> {
router(
contracts: HyperlaneContracts<HypERC20Factories>,
): HypERC20 | HypERC20Collateral | HypNativeCollateral {
return (
contracts[TokenType.synthetic] ||
contracts[TokenType.collateral] ||
contracts[TokenType.native]
);
}

async transfer(
origin: ChainName,
destination: ChainName,
recipient: types.Address,
amount: BigNumberish,
) {
const originRouter = this.getContracts(origin).router;
const originRouter = this.router(this.getContracts(origin));
Copy link
Contributor

Choose a reason for hiding this comment

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

I would really like us to detect the contract type and:

  • approve ERC20Collateral
  • Set msg.value if NativeCollateral

Copy link
Contributor

Choose a reason for hiding this comment

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

Probably best for a follow up PR that covers what we discussed yesterday (i.e. passing chain/tokenType to the app constructor)

Copy link
Contributor

Choose a reason for hiding this comment

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

Another request I'd love to have in that PR is a getBalance(chain) function that will give you the balance of the native asset, collateral asset, or wrapped asset, depending on the chain

const signerAddress = await this.multiProvider.getSignerAddress(origin);
const balance = await originRouter.balanceOf(signerAddress);
if (balance.lt(amount))
Expand All @@ -62,13 +78,19 @@ export class HypERC20App extends HyperlaneTokenApp<HypERC20Factories> {
}

export class HypERC721App extends HyperlaneTokenApp<HypERC721Factories> {
router(
contracts: HyperlaneContracts<HypERC721Factories>,
): HypERC721 | HypERC721Collateral {
return contracts[TokenType.synthetic] || contracts[TokenType.collateral];
}

async transfer(
origin: ChainName,
destination: ChainName,
recipient: types.Address,
tokenId: BigNumberish,
) {
const originRouter = this.getContracts(origin).router;
const originRouter = this.router(this.getContracts(origin));
const signerAddress = await this.multiProvider.getSignerAddress(origin);
const owner = await originRouter.ownerOf(tokenId);
if (signerAddress != owner)
Expand Down
29 changes: 7 additions & 22 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,45 +26,30 @@ export const isTokenMetadata = (metadata: any): metadata is TokenMetadata =>
export const isErc20Metadata = (metadata: any): metadata is ERC20Metadata =>
metadata.decimals && isTokenMetadata(metadata);

export type SyntheticConfig = TokenMetadata & {
export type SyntheticConfig = Partial<TokenMetadata> & {
type: TokenType.synthetic | TokenType.syntheticUri;
};
export type CollateralConfig = {
type: TokenType.collateral | TokenType.collateralUri;
token: string;
};
export type NativeConfig = {
type: TokenType.native;
type: TokenType.collateral | TokenType.collateralUri | TokenType.native;
token?: string; // no token implies native collateral
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Maybe token not required for native collateral

Just b/c the type is not implied by the presence/absence of token, it's explicit in the type

};

export type TokenConfig = SyntheticConfig | CollateralConfig | NativeConfig;
export type TokenConfig = SyntheticConfig | CollateralConfig;

export const isCollateralConfig = (
config: TokenConfig,
): config is CollateralConfig =>
config.type === TokenType.collateral ||
config.type === TokenType.collateralUri;
config.type === TokenType.collateralUri ||
config.type === TokenType.native;

export const isSyntheticConfig = (
config: TokenConfig,
): config is SyntheticConfig =>
config.type === TokenType.synthetic || config.type === TokenType.syntheticUri;

export const isNativeConfig = (config: TokenConfig): config is NativeConfig =>
config.type === TokenType.native;

export const isUriConfig = (config: TokenConfig) =>
config.type === TokenType.syntheticUri ||
config.type === TokenType.collateralUri;

export type HypERC20Config = GasRouterConfig & SyntheticConfig & ERC20Metadata;
export type HypERC20CollateralConfig = GasRouterConfig & CollateralConfig;
export type HypNativeConfig = GasRouterConfig & NativeConfig;
export type ERC20RouterConfig =
| HypERC20Config
| HypERC20CollateralConfig
| HypNativeConfig;

export type HypERC721Config = GasRouterConfig & SyntheticConfig;
export type HypERC721CollateralConfig = GasRouterConfig & CollateralConfig;
export type ERC721RouterConfig = HypERC721Config | HypERC721CollateralConfig;
export type TokenRouterConfig = TokenConfig & GasRouterConfig;
31 changes: 22 additions & 9 deletions src/contracts.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
import { HyperlaneFactories } from '@hyperlane-xyz/sdk';
import { TokenType } from './config';
import {
HypERC20Collateral__factory,
HypERC20__factory,
HypERC721Collateral__factory,
HypERC721URICollateral__factory,
HypERC721URIStorage__factory,
HypERC721__factory,
HypNative__factory,
HypNativeCollateral__factory,
TokenRouter,
} from './types';

export type HypERC20Factories = {
router: HypERC20__factory | HypERC20Collateral__factory | HypNative__factory;
type TokenRouterFactory = { deploy(...args: any[]): Promise<TokenRouter>; };

export type TokenFactories = Partial<Record<TokenType, TokenRouterFactory>> & HyperlaneFactories;

export const hypErc20Factories = {
[TokenType.synthetic]: new HypERC20__factory(),
[TokenType.collateral]: new HypERC20Collateral__factory(),
[TokenType.native]: new HypNativeCollateral__factory(),
};
export type HypERC721Factories = {
router:
| HypERC721__factory
| HypERC721Collateral__factory
| HypERC721URICollateral__factory;

export type HypERC20Factories = typeof hypErc20Factories;

export const hypErc721Factories = {
[TokenType.synthetic]: new HypERC721__factory(),
[TokenType.syntheticUri]: new HypERC721URIStorage__factory(),
[TokenType.collateral]: new HypERC721Collateral__factory(),
[TokenType.collateralUri]: new HypERC721URICollateral__factory(),
};

export type TokenFactories = HypERC20Factories | HypERC721Factories;
export type HypERC721Factories = typeof hypErc721Factories;
Loading