Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
561161a4
Commit
561161a4
authored
Nov 10, 2021
by
Mark Tyneway
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
test: add erc20 test coverage
parent
87c4dc7e
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
149 additions
and
6 deletions
+149
-6
package.json
packages/regenesis-surgery/package.json
+3
-2
classifiers.ts
packages/regenesis-surgery/scripts/classifiers.ts
+4
-1
handlers.ts
packages/regenesis-surgery/scripts/handlers.ts
+5
-0
types.ts
packages/regenesis-surgery/scripts/types.ts
+1
-0
utils.ts
packages/regenesis-surgery/scripts/utils.ts
+44
-1
erc20.spec.ts
packages/regenesis-surgery/test/erc20.spec.ts
+36
-0
provider.spec.ts
packages/regenesis-surgery/test/provider.spec.ts
+1
-1
setup.ts
packages/regenesis-surgery/test/setup.ts
+8
-1
utils.ts
packages/regenesis-surgery/test/utils.ts
+32
-0
yarn.lock
yarn.lock
+15
-0
No files found.
packages/regenesis-surgery/package.json
View file @
561161a4
...
...
@@ -17,6 +17,7 @@
"@discoveryjs/json-ext"
:
"^0.5.3"
,
"@eth-optimism/core-utils"
:
"0.6.0"
,
"@ethersproject/abstract-provider"
:
"^5.5.1"
,
"@ethersproject/abi"
:
"^5.5.0"
,
"@ethersproject/bignumber"
:
"^5.5.0"
,
"@ethersproject/properties"
:
"^5.5.0"
,
"@ethersproject/providers"
:
"^5.5.0"
,
...
...
@@ -45,7 +46,7 @@
"mocha"
:
"^9.1.2"
,
"node-fetch"
:
"2.6.5"
,
"solc"
:
"0.8.7-fixed"
,
"ts-
node"
:
"^10
.0.0"
,
"ts-
mocha"
:
"^8
.0.0"
"ts-
mocha"
:
"^8
.0.0"
,
"ts-
node"
:
"^10
.0.0"
}
}
packages/regenesis-surgery/scripts/classifiers.ts
View file @
561161a4
...
...
@@ -13,7 +13,7 @@ import {
DELETE_CONTRACTS
,
}
from
'
./constants
'
import
{
Account
,
AccountType
,
SurgeryDataSources
}
from
'
./types
'
import
{
hexStringEqual
}
from
'
./utils
'
import
{
hexStringEqual
,
isBytecodeERC20
}
from
'
./utils
'
export
const
classifiers
:
{
[
key
in
AccountType
]:
(
account
:
Account
,
data
:
SurgeryDataSources
)
=>
boolean
...
...
@@ -90,6 +90,9 @@ export const classifiers: {
[
AccountType
.
VERIFIED
]:
(
account
,
data
)
=>
{
return
!
classifiers
[
AccountType
.
UNVERIFIED
](
account
,
data
)
},
[
AccountType
.
ERC20
]:
(
account
)
=>
{
return
isBytecodeERC20
(
account
.
code
)
},
}
export
const
classify
=
(
...
...
packages/regenesis-surgery/scripts/handlers.ts
View file @
561161a4
...
...
@@ -434,4 +434,9 @@ export const handlers: {
code
:
bytecode
,
}
},
[
AccountType
.
ERC20
]:
async
(
account
)
=>
{
throw
new
Error
(
`Unexpected ERC20 classification, this should never happen:
${
account
.
address
}
`
)
},
}
packages/regenesis-surgery/scripts/types.ts
View file @
561161a4
...
...
@@ -59,6 +59,7 @@ export enum AccountType {
UNISWAP_V3_OTHER
,
UNVERIFIED
,
VERIFIED
,
ERC20
,
}
export
interface
UniswapPoolData
{
...
...
packages/regenesis-surgery/scripts/utils.ts
View file @
561161a4
/* eslint @typescript-eslint/no-var-requires: "off" */
import
{
ethers
}
from
'
ethers
'
import
{
abi
as
UNISWAP_FACTORY_ABI
}
from
'
@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json
'
import
{
Interface
}
from
'
@ethersproject/abi
'
import
{
parseChunked
}
from
'
@discoveryjs/json-ext
'
import
{
createReadStream
}
from
'
fs
'
import
*
as
fs
from
'
fs
'
import
byline
from
'
byline
'
import
*
as
dotenv
from
'
dotenv
'
import
*
as
assert
from
'
assert
'
import
{
reqenv
,
getenv
}
from
'
@eth-optimism/core-utils
'
import
{
reqenv
,
getenv
,
remove0x
}
from
'
@eth-optimism/core-utils
'
import
{
Account
,
EtherscanContract
,
...
...
@@ -114,6 +115,48 @@ export const getMappingKey = (keys: any[], slot: number) => {
return
key
}
// ERC20 interface
const
iface
=
new
Interface
([
'
function balanceOf(address)
'
,
'
function name()
'
,
'
function symbol()
'
,
'
function decimals()
'
,
'
function totalSupply()
'
,
'
function transfer(address,uint256)
'
,
])
// PUSH4 should prefix any 4 byte selector
const
PUSH4
=
0x63
const
erc20Sighashes
=
new
Set
()
// Build the set of erc20 4 byte selectors
for
(
const
fn
of
Object
.
keys
(
iface
.
functions
))
{
const
sighash
=
iface
.
getSighash
(
fn
)
erc20Sighashes
.
add
(
sighash
)
}
export
const
isBytecodeERC20
=
(
bytecode
:
string
):
boolean
=>
{
if
(
bytecode
===
'
0x
'
||
bytecode
===
undefined
)
{
return
false
}
const
seen
=
new
Set
()
const
buf
=
Buffer
.
from
(
remove0x
(
bytecode
),
'
hex
'
)
for
(
const
[
i
,
byte
]
of
buf
.
entries
())
{
// Track all of the observed 4 byte selectors that follow a PUSH4
// and are also present in the set of erc20Sighashes
if
(
byte
===
PUSH4
)
{
const
sighash
=
'
0x
'
+
buf
.
slice
(
i
+
1
,
i
+
5
).
toString
(
'
hex
'
)
if
(
erc20Sighashes
.
has
(
sighash
))
{
seen
.
add
(
sighash
)
}
}
}
// create a set that contains those elements of set
// erc20Sighashes that are not in set seen
const
elements
=
[...
erc20Sighashes
].
filter
((
x
)
=>
!
seen
.
has
(
x
))
return
!
elements
.
length
}
export
const
getUniswapV3Factory
=
(
signerOrProvider
:
any
):
ethers
.
Contract
=>
{
return
new
ethers
.
Contract
(
UNISWAP_V3_FACTORY_ADDRESS
,
...
...
packages/regenesis-surgery/test/erc20.spec.ts
0 → 100644
View file @
561161a4
import
{
expect
}
from
'
@eth-optimism/core-utils/test/setup
'
import
{
BigNumber
}
from
'
ethers
'
import
{
env
}
from
'
./setup
'
describe
(
'
erc20
'
,
()
=>
{
describe
(
'
standard ERC20
'
,
()
=>
{
before
(
async
()
=>
{
await
env
.
init
()
})
it
(
'
ERC20s
'
,
()
=>
{
for
(
const
[
i
,
erc20
]
of
env
.
erc20s
.
entries
())
{
describe
(
`erc20
${
i
}
/
${
env
.
erc20s
.
length
}
(
${
erc20
.
address
}
)`
,
()
=>
{
it
(
'
should have the same storage
'
,
async
()
=>
{
const
account
=
env
.
surgeryDataSources
.
dump
.
find
(
(
a
)
=>
a
.
address
===
erc20
.
address
)
if
(
account
.
storage
)
{
for
(
const
key
of
Object
.
keys
(
account
.
storage
))
{
const
pre
=
await
env
.
preL2Provider
.
getStorageAt
(
account
.
address
,
BigNumber
.
from
(
key
)
)
const
post
=
await
env
.
postL2Provider
.
getStorageAt
(
account
.
address
,
BigNumber
.
from
(
key
)
)
expect
(
pre
).
to
.
deep
.
eq
(
post
)
}
}
})
})
}
})
})
})
packages/regenesis-surgery/test/provider.spec.ts
View file @
561161a4
...
...
@@ -49,7 +49,7 @@ const genesis: Genesis = {
},
}
describe
.
only
(
'
GenesisJsonProvider
'
,
()
=>
{
describe
(
'
GenesisJsonProvider
'
,
()
=>
{
let
provider
before
(()
=>
{
provider
=
new
GenesisJsonProvider
(
genesis
)
...
...
packages/regenesis-surgery/test/setup.ts
View file @
561161a4
...
...
@@ -7,7 +7,7 @@ import { getenv, remove0x } from '@eth-optimism/core-utils'
import
{
providers
,
BigNumber
}
from
'
ethers
'
import
{
SurgeryDataSources
,
Account
,
AccountType
}
from
'
../scripts/types
'
import
{
loadSurgeryData
}
from
'
../scripts/data
'
import
{
classify
}
from
'
../scripts/classifiers
'
import
{
classify
,
classifiers
}
from
'
../scripts/classifiers
'
import
{
GenesisJsonProvider
}
from
'
./provider
'
// Chai plugins go here.
...
...
@@ -64,6 +64,9 @@ class TestEnv {
// List of typed accounts in the input dump
accounts
:
TypedAccount
[]
=
[]
// List of erc20 contracts in input dump
erc20s
:
Account
[]
=
[]
constructor
(
opts
:
TestEnvConfig
)
{
this
.
config
=
opts
// If the pre provider url is provided, use a json rpc provider.
...
...
@@ -138,6 +141,10 @@ class TestEnv {
...
account
,
type
:
accountType
,
})
if
(
classifiers
[
AccountType
.
ERC20
](
account
,
this
.
surgeryDataSources
))
{
this
.
erc20s
.
push
(
account
)
}
}
}
}
...
...
packages/regenesis-surgery/test/utils.ts
0 → 100644
View file @
561161a4
import
{
expect
}
from
'
@eth-optimism/core-utils/test/setup
'
import
fs
from
'
fs/promises
'
import
path
from
'
path
'
import
{
isBytecodeERC20
}
from
'
../scripts/utils
'
describe
(
'
Utils
'
,
()
=>
{
// Read in the mock data
const
contracts
=
{}
before
(
async
()
=>
{
const
files
=
await
fs
.
readdir
(
path
.
join
(
__dirname
,
'
data
'
))
for
(
const
filename
of
files
)
{
const
file
=
await
fs
.
readFile
(
path
.
join
(
__dirname
,
'
data
'
,
filename
))
const
name
=
path
.
parse
(
filename
).
name
const
json
=
JSON
.
parse
(
file
.
toString
())
contracts
[
name
]
=
{
bytecode
:
json
.
bytecode
.
toString
().
trim
(),
expected
:
json
.
expected
,
}
}
})
it
(
'
isBytecodeERC20
'
,
()
=>
{
for
(
const
[
name
,
contract
]
of
Object
.
entries
(
contracts
))
{
describe
(
`contract
${
name
}
`
,
()
=>
{
it
(
'
should be identified erc20
'
,
()
=>
{
const
result
=
isBytecodeERC20
((
contract
as
any
).
bytecode
as
string
)
expect
(
result
).
to
.
eq
((
contract
as
any
).
expected
)
})
})
}
})
})
yarn.lock
View file @
561161a4
...
...
@@ -734,6 +734,21 @@
"@ethersproject/properties" "^5.4.0"
"@ethersproject/strings" "^5.4.0"
"@ethersproject/abi@^5.5.0":
version "5.5.0"
resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.5.0.tgz#fb52820e22e50b854ff15ce1647cc508d6660613"
integrity sha512-loW7I4AohP5KycATvc0MgujU6JyCHPqHdeoo9z3Nr9xEiNioxa65ccdm1+fsoJhkuhdRtfcL8cfyGamz2AxZ5w==
dependencies:
"@ethersproject/address" "^5.5.0"
"@ethersproject/bignumber" "^5.5.0"
"@ethersproject/bytes" "^5.5.0"
"@ethersproject/constants" "^5.5.0"
"@ethersproject/hash" "^5.5.0"
"@ethersproject/keccak256" "^5.5.0"
"@ethersproject/logger" "^5.5.0"
"@ethersproject/properties" "^5.5.0"
"@ethersproject/strings" "^5.5.0"
"@ethersproject/abstract-provider@5.4.1", "@ethersproject/abstract-provider@^5.0.0", "@ethersproject/abstract-provider@^5.4.0", "@ethersproject/abstract-provider@^5.4.1":
version "5.4.1"
resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.4.1.tgz#e404309a29f771bd4d28dbafadcaa184668c2a6e"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment