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

Commit

Permalink
Add erc20 decimals and token metadata tooling (#56)
Browse files Browse the repository at this point in the history
* Add decimals to synthetic ERC20

* Update config and tests for default token metadata

* Update example token config to fetch metadata

* Update with router

* Pull in 1.3.1
---------

Co-authored-by: Asa Oines <[email protected]>
  • Loading branch information
yorhodes and asaj authored Apr 6, 2023
1 parent e403671 commit aff4e3a
Show file tree
Hide file tree
Showing 10 changed files with 433 additions and 239 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

This repo contains the base Hyperlane ERC20 and ERC721 tokens (HypERC20 and HypERC721). These tokens extend the base standards with an additional `transferRemote` function. Warp Routes make any token or native asset interchain without custom contracts. Read more about Warp Routes and how to deploy your own at [Warp API docs](https://docs.hyperlane.xyz/docs/developers/warp-api).

**NOTE:** ERC721 collateral variants are assumed to [enumerable](https://docs.openzeppelin.com/contracts/4.x/api/token/erc721#IERC721Enumerable) and [metadata](https://docs.openzeppelin.com/contracts/4.x/api/token/erc721#IERC721Metadata) compliant.

## Versions

| Git Ref | Release Date | Notes |
Expand Down
9 changes: 0 additions & 9 deletions configs/warp-route-token-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,18 @@
},
"alfajores": {
"type": "synthetic",
"name": "Weth",
"symbol": "WETH",
"totalSupply": 0,
"owner": "0x5bA371aeA18734Cb7195650aFdfCa4f9251aa513",
"mailbox": "0xCC737a94FecaeC165AbCf12dED095BB13F037685",
"interchainGasPaymaster": "0xF90cB82a76492614D07B82a7658917f3aC811Ac1"
},
"fuji": {
"type": "synthetic",
"name": "Weth",
"symbol": "WETH",
"totalSupply": 0,
"owner": "0x5bA371aeA18734Cb7195650aFdfCa4f9251aa513",
"mailbox": "0xCC737a94FecaeC165AbCf12dED095BB13F037685",
"interchainGasPaymaster": "0xF90cB82a76492614D07B82a7658917f3aC811Ac1"
},
"moonbasealpha": {
"type": "synthetic",
"name": "Weth",
"symbol": "WETH",
"totalSupply": 0,
"owner": "0x5bA371aeA18734Cb7195650aFdfCa4f9251aa513",
"mailbox": "0xCC737a94FecaeC165AbCf12dED095BB13F037685",
"interchainGasPaymaster": "0xF90cB82a76492614D07B82a7658917f3aC811Ac1"
Expand Down
10 changes: 10 additions & 0 deletions contracts/HypERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/
* @dev Supply on each chain is not constant but the aggregate supply across all chains is.
*/
contract HypERC20 is ERC20Upgradeable, TokenRouter {
uint8 private immutable _decimals;

constructor(uint8 decimals) {
_decimals = decimals;
}

/**
* @notice Initializes the Hyperlane router, ERC20 metadata, and mints initial supply to deployer.
* @param _mailbox The address of the mailbox contract.
Expand All @@ -37,6 +43,10 @@ contract HypERC20 is ERC20Upgradeable, TokenRouter {
_mint(msg.sender, _totalSupply);
}

function decimals() public view override returns (uint8) {
return _decimals;
}

/**
* @dev Burns `_amount` of token from `msg.sender` balance.
* @inheritdoc TokenRouter
Expand Down
4 changes: 2 additions & 2 deletions contracts/test/ERC721Test.sol
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";

contract ERC721Test is ERC721 {
contract ERC721Test is ERC721Enumerable {
constructor(
string memory name,
string memory symbol,
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"name": "@hyperlane-xyz/hyperlane-token",
"description": "A template for interchain ERC20 and ERC721 tokens using Hyperlane",
"version": "1.3.0",
"version": "1.3.1",
"dependencies": {
"@hyperlane-xyz/core": "1.3.0",
"@hyperlane-xyz/sdk": "1.3.0",
"@hyperlane-xyz/utils": "1.3.0",
"@hyperlane-xyz/core": "1.3.1",
"@hyperlane-xyz/sdk": "1.3.1",
"@hyperlane-xyz/utils": "1.3.1",
"@openzeppelin/contracts-upgradeable": "^4.8.0",
"ethers": "^5.7.2"
},
Expand Down
46 changes: 27 additions & 19 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ethers } from 'ethers';

import { GasRouterConfig, RouterConfig } from '@hyperlane-xyz/sdk';
import { GasRouterConfig } from '@hyperlane-xyz/sdk';

export enum TokenType {
synthetic = 'synthetic',
Expand All @@ -10,12 +10,25 @@ export enum TokenType {
native = 'native',
}

export type SyntheticConfig = {
type: TokenType.synthetic | TokenType.syntheticUri;
export type TokenMetadata = {
name: string;
symbol: string;
totalSupply: ethers.BigNumberish;
};

export type ERC20Metadata = TokenMetadata & {
decimals: number;
};

export const isTokenMetadata = (metadata: any): metadata is TokenMetadata =>
metadata.name && metadata.symbol && metadata.totalSupply !== undefined; // totalSupply can be 0

export const isErc20Metadata = (metadata: any): metadata is ERC20Metadata =>
metadata.decimals && isTokenMetadata(metadata);

export type SyntheticConfig = TokenMetadata & {
type: TokenType.synthetic | TokenType.syntheticUri;
};
export type CollateralConfig = {
type: TokenType.collateral | TokenType.collateralUri;
token: string;
Expand Down Expand Up @@ -44,19 +57,14 @@ export const isUriConfig = (config: TokenConfig) =>
config.type === TokenType.syntheticUri ||
config.type === TokenType.collateralUri;

export type HypERC20Config = Partial<GasRouterConfig> &
RouterConfig &
TokenConfig;
export type HypERC20CollateralConfig = Partial<GasRouterConfig> &
RouterConfig &
CollateralConfig;
export type HypNativeConfig = Partial<GasRouterConfig> &
RouterConfig &
NativeConfig;

export type HypERC721Config = Partial<GasRouterConfig> &
RouterConfig &
TokenConfig;
export type HypERC721CollateralConfig = Partial<GasRouterConfig> &
RouterConfig &
CollateralConfig;
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;
Loading

1 comment on commit aff4e3a

@github-actions
Copy link

Choose a reason for hiding this comment

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

Hardhat Coverage Report

Coverage for this commit
91.67% 0.00%
Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
contracts
   HypERC20.sol84.62%100%80%87.50%47
   HypERC20Collateral.sol100%100%100%100%
   HypERC721.sol100%100%100%100%
   HypERC721Collateral.sol84.62%100%83.33%85.71%25
   HypNative.sol86.67%100%80%87.50%65
contracts/extensions
   HypERC721URICollateral.sol100%100%100%100%
   HypERC721URIStorage.sol85.71%100%83.33%87.50%70
contracts/libs
   Message.sol80%100%80%80%23
   TokenRouter.sol100%100%100%100%

Please sign in to comment.