Skip to content

Commit

Permalink
use standard l2 token abi and l2Bridge field for validating standard …
Browse files Browse the repository at this point in the history
…tokens
  • Loading branch information
tremarkley committed Mar 30, 2023
1 parent 320c595 commit a90d1ce
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 995 deletions.
1 change: 1 addition & 0 deletions data/VELO/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "Velodrome",
"symbol": "VELO",
"decimals": 18,
"nobridge": true,
"tokens": {
"optimism": {
"address": "0x3c8B650257cFb5f272f799F5e2b4e65093a11a05"
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@eth-optimism/tokenlist",
"description": "[Optimism] token list",
"version": "5.3.14",
"version": "5.3.15",
"main": "index.js",
"homepage": "https://github.com/ethereum-optimism/tokenlist#readme",
"license": "MIT",
Expand All @@ -24,7 +24,7 @@
"@actions/core": "^1.4.0",
"@babel/eslint-parser": "^7.18.2",
"@eth-optimism/common-ts": "^0.6.5",
"@eth-optimism/contracts": "^0.5.7",
"@eth-optimism/contracts": "^0.5.40",
"@eth-optimism/core-utils": "^0.9.3",
"@types/glob": "^8.0.0",
"@types/jest": "^29.0.3",
Expand Down
33 changes: 0 additions & 33 deletions src/abi.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,3 @@
export const FACTORY_ABI = [
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: 'address',
name: '_l1Token',
type: 'address',
},
{
indexed: true,
internalType: 'address',
name: '_l2Token',
type: 'address',
},
],
name: 'StandardL2TokenCreated',
type: 'event',
},
{
inputs: [
{ internalType: 'address', name: '_l1Token', type: 'address' },
{ internalType: 'string', name: '_name', type: 'string' },
{ internalType: 'string', name: '_symbol', type: 'string' },
],
name: 'createStandardL2Token',
outputs: [],
stateMutability: 'nonpayable',
type: 'function',
},
]

export const TOKEN_ABI = [
{
constant: true,
Expand Down
10 changes: 8 additions & 2 deletions src/chains.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ethers } from 'ethers'

import { Network } from './types'
import { Chain, Network } from './types'

export const NETWORK_DATA: { [network: string]: Network } = {
export const NETWORK_DATA: Record<Chain, Network> = {
ethereum: {
id: 1,
name: 'Mainnet',
Expand Down Expand Up @@ -46,3 +46,9 @@ export const NETWORK_DATA: { [network: string]: Network } = {
bridge: '0x4200000000000000000000000000000000000010',
},
}

export const L2_TO_L1_PAIR: Partial<Record<Chain, Chain>> = {
optimism: 'ethereum',
'optimism-goerli': 'goerli',
'base-goerli': 'goerli',
}
3 changes: 2 additions & 1 deletion src/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ export const generate = (datadir: string) => {
decimals: token.overrides?.decimals ?? data.decimals,
logoURI: `${BASE_URL}/data/${folder}/logo.${logoext}`,
extensions: {
optimismBridgeAddress: token.overrides?.bridge ?? NETWORK_DATA[chain].bridge,
optimismBridgeAddress:
token.overrides?.bridge ?? NETWORK_DATA[chain].bridge,
},
}
if (data.nobridge) {
Expand Down
2 changes: 1 addition & 1 deletion src/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export const TOKEN_DATA_SCHEMA = {
{ required: ['base-goerli'] },
{ required: ['goerli'] },
{ required: ['optimism-goerli'] },
]
],
},
},
additionalProperties: false,
Expand Down
15 changes: 8 additions & 7 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ export interface Token {
}
}

export type Chain =
| 'ethereum'
| 'optimism'
| 'goerli'
| 'optimism-goerli'
| 'base-goerli'

export interface TokenData {
nonstandard?: boolean
nobridge?: boolean
Expand All @@ -19,13 +26,7 @@ export interface TokenData {
decimals: number
description: string
website: string
tokens: {
ethereum?: Token
optimism?: Token
goerli?: Token
'optimism-goerli'?: Token
'base-goerli'?: Token
}
tokens: Partial<Record<Chain, Token>>
}

export interface ValidationResult {
Expand Down
90 changes: 64 additions & 26 deletions src/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ import addFormats from 'ajv-formats'
import { schema } from '@uniswap/token-lists'
import { ethers } from 'ethers'
import { sleep } from '@eth-optimism/core-utils'
import { getContractInterface } from '@eth-optimism/contracts'

import { generate } from './generate'
import { TOKEN_DATA_SCHEMA } from './schemas'
import { NETWORK_DATA } from './chains'
import { FACTORY_ABI, TOKEN_ABI } from './abi'
import { TokenData, ValidationResult } from './types'
import { L2_TO_L1_PAIR, NETWORK_DATA } from './chains'
import { TOKEN_ABI } from './abi'
import { Chain, TokenData, ValidationResult } from './types'

/**
* Validates a token list data folder.
Expand Down Expand Up @@ -86,7 +87,7 @@ export const validate = async (
for (const [chain, token] of Object.entries(data.tokens)) {
// Validate any standard tokens
if (folder !== 'ETH' && data.nonstandard !== true) {
const networkData = NETWORK_DATA[chain]
const networkData = NETWORK_DATA[chain as Chain]
const contract = new ethers.Contract(
token.address,
TOKEN_ABI,
Expand Down Expand Up @@ -183,22 +184,56 @@ export const validate = async (
}

if (networkData.layer === 2) {
const factory = new ethers.Contract(
'0x4200000000000000000000000000000000000012',
FACTORY_ABI,
networkData.provider
)
if (!data.nobridge) {
if (token.overrides?.bridge === undefined) {
try {
const tokenContract = new ethers.Contract(
token.address,
getContractInterface('L2StandardERC20'),
networkData.provider
)

const events = await factory.queryFilter(
factory.filters.StandardL2TokenCreated(undefined, token.address)
)
const l2Bridge = (await tokenContract.l2Bridge()) as string
// Trigger review if the bridge for the token is not set
// to the standard bridge address.
if (
l2Bridge?.toUpperCase() !== networkData.bridge.toUpperCase()
) {
results.push({
type: 'error',
message: `${folder} on chain ${chain} token ${token.address} not using standard bridge`,
})
}

// Trigger review if not created by standard token factory.
if (events.length === 0) {
results.push({
type: 'warning',
message: `${folder} on chain ${chain} token ${token.address} not created by standard token factory`,
})
const l1Token = (await tokenContract.l1Token()) as string
const l1Chain = L2_TO_L1_PAIR[chain as Chain]
const l1ChainData = data.tokens[l1Chain]
if (
l1ChainData &&
l1ChainData.address.toUpperCase() !== l1Token.toUpperCase()
) {
results.push({
type: 'error',
message: `${folder} on chain ${chain} token ${token.address} does not match L1 token address`,
})
}
} catch (e) {
console.error(
`${folder} on chain ${chain} token ${token.address} could not fetch l2Bridge or l1Token`,
e
)
results.push({
type: 'error',
message: `${folder} on chain ${chain} token ${token.address} could not fetch l2Bridge or l1Token.
This token most likely needs nobridge or a bridge override set.`,
})
}
} else {
results.push({
type: 'warning',
message: `${folder} on chain ${chain} token ${token.address} has an overridden bridge`,
})
}
}
} else {
try {
Expand All @@ -207,19 +242,22 @@ export const validate = async (
await sleep(1000)
const { result: etherscanResult } = await (
await fetch(
`https://api${chain === 'ethereum' ? '' : `-${chain}`
`https://api${
chain === 'ethereum' ? '' : `-${chain}`
}.etherscan.io/api?` +
new URLSearchParams({
module: 'contract',
action: 'getsourcecode',
address: token.address,
apikey: process.env.ETHERSCAN_API_KEY,
})
new URLSearchParams({
module: 'contract',
action: 'getsourcecode',
address: token.address,
apikey: process.env.ETHERSCAN_API_KEY,
})
)
).json()

// Trigger review if code not verified on Etherscan
if (etherscanResult[0].ABI === 'Contract source code not verified') {
if (
etherscanResult[0].ABI === 'Contract source code not verified'
) {
results.push({
type: 'warning',
message: `${folder} on chain ${chain} token ${token.address} code not verified on Etherscan`,
Expand Down
Loading

0 comments on commit a90d1ce

Please sign in to comment.