Commit 9dc2386a authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into ctb/portal-immutables

parents 3c35aaeb d003f600
...@@ -5,8 +5,8 @@ go 1.20 ...@@ -5,8 +5,8 @@ go 1.20
require github.com/ethereum-optimism/optimism v0.0.0 require github.com/ethereum-optimism/optimism v0.0.0
require ( require (
golang.org/x/crypto v0.8.0 // indirect golang.org/x/crypto v0.12.0 // indirect
golang.org/x/sys v0.7.0 // indirect golang.org/x/sys v0.11.0 // indirect
) )
replace github.com/ethereum-optimism/optimism v0.0.0 => ../../.. replace github.com/ethereum-optimism/optimism v0.0.0 => ../../..
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
module hello module hello
go 1.20
...@@ -23,7 +23,7 @@ require ( ...@@ -23,7 +23,7 @@ require (
github.com/ipfs/go-datastore v0.6.0 github.com/ipfs/go-datastore v0.6.0
github.com/ipfs/go-ds-leveldb v0.5.0 github.com/ipfs/go-ds-leveldb v0.5.0
github.com/jackc/pgtype v1.14.0 github.com/jackc/pgtype v1.14.0
github.com/jackc/pgx/v5 v5.3.1 github.com/jackc/pgx/v5 v5.4.3
github.com/lib/pq v1.10.9 github.com/lib/pq v1.10.9
github.com/libp2p/go-libp2p v0.25.1 github.com/libp2p/go-libp2p v0.25.1
github.com/libp2p/go-libp2p-pubsub v0.9.3 github.com/libp2p/go-libp2p-pubsub v0.9.3
...@@ -40,10 +40,10 @@ require ( ...@@ -40,10 +40,10 @@ require (
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/urfave/cli v1.22.14 github.com/urfave/cli v1.22.14
github.com/urfave/cli/v2 v2.25.7 github.com/urfave/cli/v2 v2.25.7
golang.org/x/crypto v0.8.0 golang.org/x/crypto v0.12.0
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df
golang.org/x/sync v0.3.0 golang.org/x/sync v0.3.0
golang.org/x/term v0.7.0 golang.org/x/term v0.11.0
golang.org/x/time v0.3.0 golang.org/x/time v0.3.0
gorm.io/driver/postgres v1.5.2 gorm.io/driver/postgres v1.5.2
gorm.io/gorm v1.25.2 gorm.io/gorm v1.25.2
...@@ -185,9 +185,9 @@ require ( ...@@ -185,9 +185,9 @@ require (
go.uber.org/multierr v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect
go.uber.org/zap v1.24.0 // indirect go.uber.org/zap v1.24.0 // indirect
golang.org/x/mod v0.11.0 // indirect golang.org/x/mod v0.11.0 // indirect
golang.org/x/net v0.9.0 // indirect golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.7.0 // indirect golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.9.0 // indirect golang.org/x/text v0.12.0 // indirect
golang.org/x/tools v0.7.0 // indirect golang.org/x/tools v0.7.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
......
...@@ -405,8 +405,8 @@ github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9 ...@@ -405,8 +405,8 @@ github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c h1:Dznn52SgVIVst9UyOT9brctYUgxs+CvVfPaC3jKrA50= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c h1:Dznn52SgVIVst9UyOT9brctYUgxs+CvVfPaC3jKrA50=
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU= github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
...@@ -860,8 +860,8 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm ...@@ -860,8 +860,8 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
...@@ -911,8 +911,8 @@ golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qx ...@@ -911,8 +911,8 @@ golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
...@@ -982,13 +982,13 @@ golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBc ...@@ -982,13 +982,13 @@ golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
...@@ -997,8 +997,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= ...@@ -997,8 +997,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
......
...@@ -16,17 +16,15 @@ type PaginationResponse struct { ...@@ -16,17 +16,15 @@ type PaginationResponse struct {
HasNextPage bool `json:"hasNextPage"` HasNextPage bool `json:"hasNextPage"`
} }
func (a *Api) DepositsHandler(w http.ResponseWriter, r *http.Request) { func (a *Api) L1DepositsHandler(w http.ResponseWriter, r *http.Request) {
bv := a.bridgeView bv := a.BridgeTransfersView
address := common.HexToAddress(chi.URLParam(r, "address")) address := common.HexToAddress(chi.URLParam(r, "address"))
// limit := getIntFromQuery(r, "limit", 10) // limit := getIntFromQuery(r, "limit", 10)
// cursor := r.URL.Query().Get("cursor") // cursor := r.URL.Query().Get("cursor")
// sortDirection := r.URL.Query().Get("sortDirection") // sortDirection := r.URL.Query().Get("sortDirection")
deposits, err := bv.DepositsByAddress(address) deposits, err := bv.L1BridgeDepositsByAddress(address)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
...@@ -43,17 +41,15 @@ func (a *Api) DepositsHandler(w http.ResponseWriter, r *http.Request) { ...@@ -43,17 +41,15 @@ func (a *Api) DepositsHandler(w http.ResponseWriter, r *http.Request) {
jsonResponse(w, response, http.StatusOK) jsonResponse(w, response, http.StatusOK)
} }
func (a *Api) WithdrawalsHandler(w http.ResponseWriter, r *http.Request) { func (a *Api) L2WithdrawalsHandler(w http.ResponseWriter, r *http.Request) {
bv := a.bridgeView bv := a.BridgeTransfersView
address := common.HexToAddress(chi.URLParam(r, "address")) address := common.HexToAddress(chi.URLParam(r, "address"))
// limit := getIntFromQuery(r, "limit", 10) // limit := getIntFromQuery(r, "limit", 10)
// cursor := r.URL.Query().Get("cursor") // cursor := r.URL.Query().Get("cursor")
// sortDirection := r.URL.Query().Get("sortDirection") // sortDirection := r.URL.Query().Get("sortDirection")
withdrawals, err := bv.WithdrawalsByAddress(address) withdrawals, err := bv.L2BridgeWithdrawalsByAddress(address)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
...@@ -83,22 +79,20 @@ func jsonResponse(w http.ResponseWriter, data interface{}, statusCode int) { ...@@ -83,22 +79,20 @@ func jsonResponse(w http.ResponseWriter, data interface{}, statusCode int) {
} }
type Api struct { type Api struct {
Router *chi.Mux Router *chi.Mux
bridgeView database.BridgeView BridgeTransfersView database.BridgeTransfersView
} }
func NewApi(bv database.BridgeView) *Api { func NewApi(bv database.BridgeTransfersView) *Api {
r := chi.NewRouter() r := chi.NewRouter()
api := &Api{ api := &Api{Router: r, BridgeTransfersView: bv}
Router: r,
bridgeView: bv,
}
// these regex are .+ because I wasn't sure what they should be // these regex are .+ because I wasn't sure what they should be
// don't want a regex for addresses because would prefer to validate the address // don't want a regex for addresses because would prefer to validate the address
// with go-ethereum and throw a friendly error message // with go-ethereum and throw a friendly error message
r.Get("/api/v0/deposits/{address:.+}", api.DepositsHandler) r.Get("/api/v0/deposits/{address:.+}", api.L1DepositsHandler)
r.Get("/api/v0/withdrawals/{address:.+}", api.WithdrawalsHandler) r.Get("/api/v0/withdrawals/{address:.+}", api.L2WithdrawalsHandler)
r.Get("/healthz", api.HealthzHandler) r.Get("/healthz", api.HealthzHandler)
return api return api
......
...@@ -12,89 +12,67 @@ import ( ...@@ -12,89 +12,67 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
// MockBridgeView mocks the BridgeView interface // MockBridgeTransfersView mocks the BridgeTransfersView interface
type MockBridgeView struct{} type MockBridgeTransfersView struct{}
const ( const (
guid1 = "8408b6d2-7c90-4cfc-8604-b2204116cb6a" guid1 = "8408b6d2-7c90-4cfc-8604-b2204116cb6a"
guid2 = "8408b6d2-7c90-4cfc-8604-b2204116cb6b" guid2 = "8408b6d2-7c90-4cfc-8604-b2204116cb6b"
) )
// DepositsByAddress mocks returning deposits by an address var (
func (mbv *MockBridgeView) DepositsByAddress(address common.Address) ([]*database.DepositWithTransactionHashes, error) { deposit = database.L1BridgeDeposit{
return []*database.DepositWithTransactionHashes{
{
Deposit: database.Deposit{
GUID: uuid.MustParse(guid1),
InitiatedL1EventGUID: uuid.MustParse(guid2),
Tx: database.Transaction{},
TokenPair: database.TokenPair{},
},
L1TransactionHash: common.HexToHash("0x123"),
},
}, nil
}
// DepositsByAddress mocks returning deposits by an address
func (mbv *MockBridgeView) DepositByMessageNonce(nonce *big.Int) (*database.Deposit, error) {
return &database.Deposit{
GUID: uuid.MustParse(guid1), GUID: uuid.MustParse(guid1),
InitiatedL1EventGUID: uuid.MustParse(guid2), InitiatedL1EventGUID: uuid.MustParse(guid2),
Tx: database.Transaction{}, Tx: database.Transaction{},
TokenPair: database.TokenPair{}, TokenPair: database.TokenPair{},
}, nil }
withdrawal = database.L2BridgeWithdrawal{
GUID: uuid.MustParse(guid2),
InitiatedL2EventGUID: uuid.MustParse(guid1),
WithdrawalHash: common.HexToHash("0x456"),
Tx: database.Transaction{},
TokenPair: database.TokenPair{},
}
)
func (mbv *MockBridgeTransfersView) L1BridgeDeposit(hash common.Hash) (*database.L1BridgeDeposit, error) {
return &deposit, nil
} }
// LatestDepositMessageNonce mocks returning the latest cross domain message nonce for a deposit func (mbv *MockBridgeTransfersView) L1BridgeDepositByCrossDomainMessengerNonce(nonce *big.Int) (*database.L1BridgeDeposit, error) {
func (mbv *MockBridgeView) LatestDepositMessageNonce() (*big.Int, error) { return &deposit, nil
return big.NewInt(0), nil
} }
// WithdrawalsByAddress mocks returning withdrawals by an address func (mbv *MockBridgeTransfersView) L1BridgeDepositsByAddress(address common.Address) ([]*database.L1BridgeDepositWithTransactionHashes, error) {
func (mbv *MockBridgeView) WithdrawalsByAddress(address common.Address) ([]*database.WithdrawalWithTransactionHashes, error) { return []*database.L1BridgeDepositWithTransactionHashes{
return []*database.WithdrawalWithTransactionHashes{
{ {
Withdrawal: database.Withdrawal{ L1BridgeDeposit: deposit,
GUID: uuid.MustParse(guid2), L1TransactionHash: common.HexToHash("0x123"),
InitiatedL2EventGUID: uuid.MustParse(guid1),
WithdrawalHash: common.HexToHash("0x456"),
Tx: database.Transaction{},
TokenPair: database.TokenPair{},
},
L2TransactionHash: common.HexToHash("0x789"),
}, },
}, nil }, nil
} }
// WithdrawalsByMessageNonce mocks returning withdrawals by a withdrawal hash func (mbv *MockBridgeTransfersView) L2BridgeWithdrawalByWithdrawalHash(address common.Hash) (*database.L2BridgeWithdrawal, error) {
func (mbv *MockBridgeView) WithdrawalByMessageNonce(nonce *big.Int) (*database.Withdrawal, error) { return &withdrawal, nil
return &database.Withdrawal{
GUID: uuid.MustParse(guid2),
InitiatedL2EventGUID: uuid.MustParse(guid1),
WithdrawalHash: common.HexToHash("0x456"),
Tx: database.Transaction{},
TokenPair: database.TokenPair{},
}, nil
} }
// WithdrawalsByHash mocks returning withdrawals by a withdrawal hash func (mbv *MockBridgeTransfersView) L2BridgeWithdrawalByCrossDomainMessengerNonce(nonce *big.Int) (*database.L2BridgeWithdrawal, error) {
func (mbv *MockBridgeView) WithdrawalByHash(address common.Hash) (*database.Withdrawal, error) { return &withdrawal, nil
return &database.Withdrawal{
GUID: uuid.MustParse(guid2),
InitiatedL2EventGUID: uuid.MustParse(guid1),
WithdrawalHash: common.HexToHash("0x456"),
Tx: database.Transaction{},
TokenPair: database.TokenPair{},
}, nil
} }
// LatestWithdrawalMessageNonce mocks returning the latest cross domain message nonce for a withdrawal func (mbv *MockBridgeTransfersView) L2BridgeWithdrawalsByAddress(address common.Address) ([]*database.L2BridgeWithdrawalWithTransactionHashes, error) {
func (mbv *MockBridgeView) LatestWithdrawalMessageNonce() (*big.Int, error) { return []*database.L2BridgeWithdrawalWithTransactionHashes{
return big.NewInt(0), nil {
L2BridgeWithdrawal: withdrawal,
L2TransactionHash: common.HexToHash("0x789"),
},
}, nil
} }
func TestHealthz(t *testing.T) { func TestHealthz(t *testing.T) {
api := NewApi(&MockBridgeView{}) api := NewApi(&MockBridgeTransfersView{})
request, err := http.NewRequest("GET", "/healthz", nil) request, err := http.NewRequest("GET", "/healthz", nil)
assert.Nil(t, err) assert.Nil(t, err)
...@@ -104,8 +82,8 @@ func TestHealthz(t *testing.T) { ...@@ -104,8 +82,8 @@ func TestHealthz(t *testing.T) {
assert.Equal(t, http.StatusOK, responseRecorder.Code) assert.Equal(t, http.StatusOK, responseRecorder.Code)
} }
func TestDepositsHandler(t *testing.T) { func TestL1BridgeDepositsHandler(t *testing.T) {
api := NewApi(&MockBridgeView{}) api := NewApi(&MockBridgeTransfersView{})
request, err := http.NewRequest("GET", "/api/v0/deposits/0x123", nil) request, err := http.NewRequest("GET", "/api/v0/deposits/0x123", nil)
assert.Nil(t, err) assert.Nil(t, err)
...@@ -115,8 +93,8 @@ func TestDepositsHandler(t *testing.T) { ...@@ -115,8 +93,8 @@ func TestDepositsHandler(t *testing.T) {
assert.Equal(t, http.StatusOK, responseRecorder.Code) assert.Equal(t, http.StatusOK, responseRecorder.Code)
} }
func TestWithdrawalsHandler(t *testing.T) { func TestL2BridgeWithdrawalsByAddressHandler(t *testing.T) {
api := NewApi(&MockBridgeView{}) api := NewApi(&MockBridgeTransfersView{})
request, err := http.NewRequest("GET", "/api/v0/withdrawals/0x123", nil) request, err := http.NewRequest("GET", "/api/v0/withdrawals/0x123", nil)
assert.Nil(t, err) assert.Nil(t, err)
......
...@@ -23,15 +23,16 @@ type Cli struct { ...@@ -23,15 +23,16 @@ type Cli struct {
} }
func runIndexer(ctx *cli.Context) error { func runIndexer(ctx *cli.Context) error {
logger := log.NewLogger(log.ReadCLIConfig(ctx))
configPath := ctx.String(ConfigFlag.Name) configPath := ctx.String(ConfigFlag.Name)
cfg, err := config.LoadConfig(configPath) cfg, err := config.LoadConfig(configPath)
if err != nil { if err != nil {
logger.Error("failed to load config", "err", err)
return err return err
} }
// setup logger cfg.Logger = logger
cfg.Logger = log.NewLogger(log.ReadCLIConfig(ctx))
indexer, err := indexer.NewIndexer(cfg) indexer, err := indexer.NewIndexer(cfg)
if err != nil { if err != nil {
return err return err
...@@ -47,17 +48,20 @@ func runIndexer(ctx *cli.Context) error { ...@@ -47,17 +48,20 @@ func runIndexer(ctx *cli.Context) error {
} }
func runApi(ctx *cli.Context) error { func runApi(ctx *cli.Context) error {
configPath := ctx.String(ConfigFlag.Name) logger := log.NewLogger(log.ReadCLIConfig(ctx))
conf, err := config.LoadConfig(configPath)
fmt.Println(conf)
configPath := ctx.String(ConfigFlag.Name)
cfg, err := config.LoadConfig(configPath)
if err != nil { if err != nil {
panic(err) logger.Error("failed to load config", "err", err)
return err
} }
cfg.Logger = logger
fmt.Println(cfg)
// finish me // finish me
return nil return err
} }
var ( var (
......
...@@ -9,7 +9,6 @@ import ( ...@@ -9,7 +9,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/google/uuid" "github.com/google/uuid"
) )
...@@ -30,17 +29,11 @@ type TokenPair struct { ...@@ -30,17 +29,11 @@ type TokenPair struct {
L2TokenAddress common.Address `gorm:"serializer:json"` L2TokenAddress common.Address `gorm:"serializer:json"`
} }
type Deposit struct { type L1BridgeDeposit struct {
GUID uuid.UUID `gorm:"primaryKey"` GUID uuid.UUID `gorm:"primaryKey"`
InitiatedL1EventGUID uuid.UUID InitiatedL1EventGUID uuid.UUID
// Since we're only currently indexing a single StandardBridge, CrossDomainMessengerNonce U256
// the message nonce serves as a unique identifier for this
// deposit. Once this generalizes to more than 1 deployed
// bridge, we need to include the `CrossDomainMessenger` address
// such that the (messenger_addr, nonce) is the unique identifier
// for a bridge msg
SentMessageNonce U256
FinalizedL2EventGUID *uuid.UUID FinalizedL2EventGUID *uuid.UUID
...@@ -48,24 +41,18 @@ type Deposit struct { ...@@ -48,24 +41,18 @@ type Deposit struct {
TokenPair TokenPair `gorm:"embedded"` TokenPair TokenPair `gorm:"embedded"`
} }
type DepositWithTransactionHashes struct { type L1BridgeDepositWithTransactionHashes struct {
Deposit Deposit `gorm:"embedded"` L1BridgeDeposit L1BridgeDeposit `gorm:"embedded"`
L1TransactionHash common.Hash `gorm:"serializer:json"`
L1TransactionHash common.Hash `gorm:"serializer:json"`
FinalizedL2TransactionHash common.Hash `gorm:"serializer:json"` FinalizedL2TransactionHash common.Hash `gorm:"serializer:json"`
} }
type Withdrawal struct { type L2BridgeWithdrawal struct {
GUID uuid.UUID `gorm:"primaryKey"` GUID uuid.UUID `gorm:"primaryKey"`
InitiatedL2EventGUID uuid.UUID InitiatedL2EventGUID uuid.UUID
// Since we're only currently indexing a single StandardBridge, CrossDomainMessengerNonce U256
// the message nonce serves as a unique identifier for this
// withdrawal. Once this generalizes to more than 1 deployed
// bridge, we need to include the `CrossDomainMessenger` address
// such that the (messenger_addr, nonce) is the unique identifier
// for a bridge msg
SentMessageNonce U256
WithdrawalHash common.Hash `gorm:"serializer:json"` WithdrawalHash common.Hash `gorm:"serializer:json"`
ProvenL1EventGUID *uuid.UUID ProvenL1EventGUID *uuid.UUID
...@@ -75,108 +62,96 @@ type Withdrawal struct { ...@@ -75,108 +62,96 @@ type Withdrawal struct {
TokenPair TokenPair `gorm:"embedded"` TokenPair TokenPair `gorm:"embedded"`
} }
type WithdrawalWithTransactionHashes struct { type L2BridgeWithdrawalWithTransactionHashes struct {
Withdrawal Withdrawal `gorm:"embedded"` L2BridgeWithdrawal L2BridgeWithdrawal `gorm:"embedded"`
L2TransactionHash common.Hash `gorm:"serializer:json"` L2TransactionHash common.Hash `gorm:"serializer:json"`
ProvenL1TransactionHash common.Hash `gorm:"serializer:json"` ProvenL1TransactionHash common.Hash `gorm:"serializer:json"`
FinalizedL1TransactionHash common.Hash `gorm:"serializer:json"` FinalizedL1TransactionHash common.Hash `gorm:"serializer:json"`
} }
type BridgeView interface { type BridgeTransfersView interface {
DepositsByAddress(address common.Address) ([]*DepositWithTransactionHashes, error) L1BridgeDepositByCrossDomainMessengerNonce(*big.Int) (*L1BridgeDeposit, error)
DepositByMessageNonce(*big.Int) (*Deposit, error) L1BridgeDepositsByAddress(common.Address) ([]*L1BridgeDepositWithTransactionHashes, error)
LatestDepositMessageNonce() (*big.Int, error)
WithdrawalsByAddress(address common.Address) ([]*WithdrawalWithTransactionHashes, error) L2BridgeWithdrawalByWithdrawalHash(common.Hash) (*L2BridgeWithdrawal, error)
WithdrawalByMessageNonce(*big.Int) (*Withdrawal, error) L2BridgeWithdrawalByCrossDomainMessengerNonce(*big.Int) (*L2BridgeWithdrawal, error)
WithdrawalByHash(common.Hash) (*Withdrawal, error) L2BridgeWithdrawalsByAddress(common.Address) ([]*L2BridgeWithdrawalWithTransactionHashes, error)
LatestWithdrawalMessageNonce() (*big.Int, error)
} }
type BridgeDB interface { type BridgeTransfersDB interface {
BridgeView BridgeTransfersView
StoreDeposits([]*Deposit) error StoreL1BridgeDeposits([]*L1BridgeDeposit) error
MarkFinalizedDepositEvent(uuid.UUID, uuid.UUID) error MarkFinalizedL1BridgeDepositEvent(uuid.UUID, uuid.UUID) error
StoreWithdrawals([]*Withdrawal) error StoreL2BridgeWithdrawals([]*L2BridgeWithdrawal) error
MarkProvenWithdrawalEvent(uuid.UUID, uuid.UUID) error MarkProvenL2BridgeWithdrawalEvent(uuid.UUID, uuid.UUID) error
MarkFinalizedWithdrawalEvent(uuid.UUID, uuid.UUID) error MarkFinalizedL2BridgeWithdrawalEvent(uuid.UUID, uuid.UUID) error
} }
/** /**
* Implementation * Implementation
*/ */
type bridgeDB struct { type bridgeTransfersDB struct {
gorm *gorm.DB gorm *gorm.DB
} }
func newBridgeDB(db *gorm.DB) BridgeDB { func newBridgeTransfersDB(db *gorm.DB) BridgeTransfersDB {
return &bridgeDB{gorm: db} return &bridgeTransfersDB{gorm: db}
} }
// Deposits /**
* Tokens Bridged (Deposited) from L1
*/
func (db *bridgeDB) StoreDeposits(deposits []*Deposit) error { func (db *bridgeTransfersDB) StoreL1BridgeDeposits(deposits []*L1BridgeDeposit) error {
result := db.gorm.Create(&deposits) result := db.gorm.Create(&deposits)
return result.Error return result.Error
} }
func (db *bridgeDB) DepositsByAddress(address common.Address) ([]*DepositWithTransactionHashes, error) { // L1BridgeDepositByMessageNonce retrieves tokens deposited, specified by the associated `L1CrossDomainMessenger` nonce.
depositsQuery := db.gorm.Table("deposits").Select("deposits.*, l1_contract_events.transaction_hash AS l1_transaction_hash, l2_contract_events.transaction_hash AS finalized_l2_transaction_hash") // All tokens bridged via the StandardBridge flows through the L1CrossDomainMessenger
func (db *bridgeTransfersDB) L1BridgeDepositByCrossDomainMessengerNonce(nonce *big.Int) (*L1BridgeDeposit, error) {
initiatedJoinQuery := depositsQuery.Joins("LEFT JOIN l1_contract_events ON deposits.initiated_l1_event_guid = l1_contract_events.guid") var deposit L1BridgeDeposit
finalizedJoinQuery := initiatedJoinQuery.Joins("LEFT JOIN l2_contract_events ON deposits.finalized_l2_event_guid = l2_contract_events.guid") result := db.gorm.Where(&L1BridgeDeposit{CrossDomainMessengerNonce: U256{Int: nonce}}).Take(&deposit)
// add in cursoring options
filteredQuery := finalizedJoinQuery.Where(&Transaction{FromAddress: address}).Order("deposits.timestamp DESC").Limit(100)
deposits := make([]*DepositWithTransactionHashes, 100)
result := filteredQuery.Scan(&deposits)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil return nil, nil
} }
return nil, result.Error return nil, result.Error
} }
return deposits, nil return &deposit, nil
} }
func (db *bridgeDB) DepositByMessageNonce(nonce *big.Int) (*Deposit, error) { // L1BridgeDepositsByAddress retrieves a list of deposits intiated by the specified address, coupled with the L1/L2 transaction
var deposit Deposit // hashes that complete the bridge transaction.
result := db.gorm.Where(&Deposit{SentMessageNonce: U256{Int: nonce}}).Take(&deposit) func (db *bridgeTransfersDB) L1BridgeDepositsByAddress(address common.Address) ([]*L1BridgeDepositWithTransactionHashes, error) {
if result.Error != nil { depositsQuery := db.gorm.Table("l1_bridge_deposits").Select("l1_bridge_deposits.*, l1_contract_events.transaction_hash AS l1_transaction_hash, l2_contract_events.transaction_hash AS finalized_l2_transaction_hash")
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error initiatedJoinQuery := depositsQuery.Joins("LEFT JOIN l1_contract_events ON l1_bridge_deposits.initiated_l1_event_guid = l1_contract_events.guid")
} finalizedJoinQuery := initiatedJoinQuery.Joins("LEFT JOIN l2_contract_events ON l1_bridge_deposits.finalized_l2_event_guid = l2_contract_events.guid")
return &deposit, nil // add in cursoring options
} filteredQuery := finalizedJoinQuery.Where(&Transaction{FromAddress: address}).Order("l1_bridge_deposits.timestamp DESC").Limit(100)
func (db *bridgeDB) LatestDepositMessageNonce() (*big.Int, error) { deposits := []*L1BridgeDepositWithTransactionHashes{}
var deposit Deposit result := filteredQuery.Scan(&deposits)
result := db.gorm.Order("sent_message_nonce DESC").Take(&deposit)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil return nil, nil
} }
return nil, result.Error return nil, result.Error
} }
return deposit.SentMessageNonce.Int, nil return deposits, nil
} }
func (db *bridgeDB) MarkFinalizedDepositEvent(guid, finalizationEventGUID uuid.UUID) error { func (db *bridgeTransfersDB) MarkFinalizedL1BridgeDepositEvent(guid, finalizationEventGUID uuid.UUID) error {
var deposit Deposit var deposit L1BridgeDeposit
result := db.gorm.Where(&Deposit{GUID: guid}).Take(&deposit) result := db.gorm.Where(&L1BridgeDeposit{GUID: guid}).Take(&deposit)
if result.Error != nil { if result.Error != nil {
return result.Error return result.Error
} }
...@@ -186,102 +161,91 @@ func (db *bridgeDB) MarkFinalizedDepositEvent(guid, finalizationEventGUID uuid.U ...@@ -186,102 +161,91 @@ func (db *bridgeDB) MarkFinalizedDepositEvent(guid, finalizationEventGUID uuid.U
return result.Error return result.Error
} }
// Withdrawals /**
* Tokens Bridged (Withdrawn) from L2
*/
func (db *bridgeDB) StoreWithdrawals(withdrawals []*Withdrawal) error { func (db *bridgeTransfersDB) StoreL2BridgeWithdrawals(withdrawals []*L2BridgeWithdrawal) error {
result := db.gorm.Create(&withdrawals) result := db.gorm.Create(&withdrawals)
return result.Error return result.Error
} }
func (db *bridgeDB) MarkProvenWithdrawalEvent(guid, provenL1EventGuid uuid.UUID) error { func (db *bridgeTransfersDB) L2BridgeWithdrawalByWithdrawalHash(withdrawalHash common.Hash) (*L2BridgeWithdrawal, error) {
var withdrawal Withdrawal var withdrawal L2BridgeWithdrawal
result := db.gorm.Where(&Withdrawal{GUID: guid}).Take(&withdrawal) result := db.gorm.Where(&L2BridgeWithdrawal{WithdrawalHash: withdrawalHash}).Take(&withdrawal)
if result.Error != nil { if result.Error != nil {
return result.Error if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
} }
withdrawal.ProvenL1EventGUID = &provenL1EventGuid return &withdrawal, nil
result = db.gorm.Save(&withdrawal)
return result.Error
} }
func (db *bridgeDB) MarkFinalizedWithdrawalEvent(guid, finalizedL1EventGuid uuid.UUID) error { // L2BridgeWithdrawalByCrossDomainMessengerNonce retrieves tokens withdrawn, specified by the associated `L2CrossDomainMessenger` nonce.
var withdrawal Withdrawal // All tokens bridged via the StandardBridge flows through the L2CrossDomainMessenger
result := db.gorm.Where(&Withdrawal{GUID: guid}).Take(&withdrawal) func (db *bridgeTransfersDB) L2BridgeWithdrawalByCrossDomainMessengerNonce(nonce *big.Int) (*L2BridgeWithdrawal, error) {
var withdrawal L2BridgeWithdrawal
result := db.gorm.Where(&L2BridgeWithdrawal{CrossDomainMessengerNonce: U256{Int: nonce}}).Take(&withdrawal)
if result.Error != nil { if result.Error != nil {
return result.Error if errors.Is(result.Error, gorm.ErrRecordNotFound) {
} return nil, nil
}
if withdrawal.ProvenL1EventGUID == nil { return nil, result.Error
return fmt.Errorf("withdrawal %s marked finalized prior to being proven", guid)
} }
withdrawal.FinalizedL1EventGUID = &finalizedL1EventGuid return &withdrawal, nil
result = db.gorm.Save(&withdrawal)
return result.Error
} }
func (db *bridgeDB) WithdrawalsByAddress(address common.Address) ([]*WithdrawalWithTransactionHashes, error) { // L2BridgeDepositsByAddress retrieves a list of deposits intiated by the specified address, coupled with the L1/L2 transaction hashes
withdrawalsQuery := db.gorm.Table("withdrawals").Select("withdrawals.*, l2_contract_events.transaction_hash AS l2_transaction_hash, proven_l1_contract_events.transaction_hash AS proven_l1_transaction_hash, finalized_l1_contract_events.transaction_hash AS finalized_l1_transaction_hash") // that complete the bridge transaction. The hashes that correspond to with the Bedrock multistep withdrawal process are also surfaced
func (db *bridgeTransfersDB) L2BridgeWithdrawalsByAddress(address common.Address) ([]*L2BridgeWithdrawalWithTransactionHashes, error) {
withdrawalsQuery := db.gorm.Table("l2_bridge_withdrawals").Select("l2_bridge_withdrawals.*, l2_contract_events.transaction_hash AS l2_transaction_hash, proven_l1_contract_events.transaction_hash AS proven_l1_transaction_hash, finalized_l1_contract_events.transaction_hash AS finalized_l1_transaction_hash")
eventsJoinQuery := withdrawalsQuery.Joins("LEFT JOIN l2_contract_events ON withdrawals.initiated_l2_event_guid = l2_contract_events.guid") eventsJoinQuery := withdrawalsQuery.Joins("LEFT JOIN l2_contract_events ON l2_bridge_withdrawals.initiated_l2_event_guid = l2_contract_events.guid")
provenJoinQuery := eventsJoinQuery.Joins("LEFT JOIN l1_contract_events AS proven_l1_contract_events ON withdrawals.proven_l1_event_guid = proven_l1_contract_events.guid") provenJoinQuery := eventsJoinQuery.Joins("LEFT JOIN l1_contract_events AS proven_l1_contract_events ON l2_bridge_withdrawals.proven_l1_event_guid = proven_l1_contract_events.guid")
finalizedJoinQuery := provenJoinQuery.Joins("LEFT JOIN l1_contract_events AS finalized_l1_contract_events ON withdrawals.finalized_l1_event_guid = finalized_l1_contract_events.guid") finalizedJoinQuery := provenJoinQuery.Joins("LEFT JOIN l1_contract_events AS finalized_l1_contract_events ON l2_bridge_withdrawals.finalized_l1_event_guid = finalized_l1_contract_events.guid")
// add in cursoring options // add in cursoring options
filteredQuery := finalizedJoinQuery.Where(&Transaction{FromAddress: address}).Order("withdrawals.timestamp DESC").Limit(100) filteredQuery := finalizedJoinQuery.Where(&Transaction{FromAddress: address}).Order("l2_bridge_withdrawals.timestamp DESC").Limit(100)
withdrawals := make([]*WithdrawalWithTransactionHashes, 100) withdrawals := []*L2BridgeWithdrawalWithTransactionHashes{}
result := filteredQuery.Scan(&withdrawals) result := filteredQuery.Scan(&withdrawals)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil return nil, nil
} }
return nil, result.Error return nil, result.Error
} }
return withdrawals, nil return withdrawals, nil
} }
func (db *bridgeDB) WithdrawalByMessageNonce(nonce *big.Int) (*Withdrawal, error) { func (db *bridgeTransfersDB) MarkProvenL2BridgeWithdrawalEvent(guid, provenL1EventGuid uuid.UUID) error {
var withdrawal Withdrawal var withdrawal L2BridgeWithdrawal
result := db.gorm.Where(&Withdrawal{SentMessageNonce: U256{Int: nonce}}).Take(&withdrawal) result := db.gorm.Where(&L2BridgeWithdrawal{GUID: guid}).Take(&withdrawal)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { return result.Error
return nil, nil
}
return nil, result.Error
} }
return &withdrawal, nil withdrawal.ProvenL1EventGUID = &provenL1EventGuid
result = db.gorm.Save(&withdrawal)
return result.Error
} }
func (db *bridgeDB) WithdrawalByHash(hash common.Hash) (*Withdrawal, error) { func (db *bridgeTransfersDB) MarkFinalizedL2BridgeWithdrawalEvent(guid, finalizedL1EventGuid uuid.UUID) error {
var withdrawal Withdrawal var withdrawal L2BridgeWithdrawal
result := db.gorm.Where(&Withdrawal{WithdrawalHash: hash}).Take(&withdrawal) result := db.gorm.Where(&L2BridgeWithdrawal{GUID: guid}).Take(&withdrawal)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { return result.Error
return nil, nil
}
return nil, result.Error
} }
return &withdrawal, nil if withdrawal.ProvenL1EventGUID == nil {
} return fmt.Errorf("withdrawal %s marked finalized prior to being proven", guid)
func (db *bridgeDB) LatestWithdrawalMessageNonce() (*big.Int, error) {
var withdrawal Withdrawal
result := db.gorm.Order("sent_message_nonce DESC").Take(&withdrawal)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
} }
return withdrawal.SentMessageNonce.Int, nil withdrawal.FinalizedL1EventGUID = &finalizedL1EventGuid
result = db.gorm.Save(&withdrawal)
return result.Error
} }
...@@ -10,9 +10,9 @@ import ( ...@@ -10,9 +10,9 @@ import (
type DB struct { type DB struct {
gorm *gorm.DB gorm *gorm.DB
Blocks BlocksDB Blocks BlocksDB
ContractEvents ContractEventsDB ContractEvents ContractEventsDB
Bridge BridgeDB BridgeTransfers BridgeTransfersDB
} }
func NewDB(dsn string) (*DB, error) { func NewDB(dsn string) (*DB, error) {
...@@ -31,10 +31,10 @@ func NewDB(dsn string) (*DB, error) { ...@@ -31,10 +31,10 @@ func NewDB(dsn string) (*DB, error) {
} }
db := &DB{ db := &DB{
gorm: gorm, gorm: gorm,
Blocks: newBlocksDB(gorm), Blocks: newBlocksDB(gorm),
ContractEvents: newContractEventsDB(gorm), ContractEvents: newContractEventsDB(gorm),
Bridge: newBridgeDB(gorm), BridgeTransfers: newBridgeTransfersDB(gorm),
} }
return db, nil return db, nil
...@@ -59,9 +59,9 @@ func (db *DB) Close() error { ...@@ -59,9 +59,9 @@ func (db *DB) Close() error {
func dbFromGormTx(tx *gorm.DB) *DB { func dbFromGormTx(tx *gorm.DB) *DB {
return &DB{ return &DB{
gorm: tx, gorm: tx,
Blocks: newBlocksDB(tx), Blocks: newBlocksDB(tx),
ContractEvents: newContractEventsDB(tx), ContractEvents: newContractEventsDB(tx),
Bridge: newBridgeDB(tx), BridgeTransfers: newBridgeTransfersDB(tx),
} }
} }
package e2e_tests
import (
"context"
"math/big"
"testing"
"time"
"github.com/ethereum-optimism/optimism/indexer/processor"
"github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
)
func TestE2EBridge(t *testing.T) {
testSuite := createE2ETestSuite(t)
l1Client := testSuite.OpSys.Clients["l1"]
l2Client := testSuite.OpSys.Clients["sequencer"]
l1StandardBridge, err := bindings.NewL1StandardBridge(testSuite.OpCfg.L1Deployments.L1StandardBridgeProxy, l1Client)
require.NoError(t, err)
l2StandardBridge, err := bindings.NewL2StandardBridge(predeploys.L2StandardBridgeAddr, l2Client)
require.NoError(t, err)
// pre-emptively conduct a deposit & withdrawal to speed up the test
setupCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice
l1Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L1ChainIDBig())
require.NoError(t, err)
l2Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L2ChainIDBig())
require.NoError(t, err)
l1Opts.Value = big.NewInt(params.Ether)
l2Opts.Value = big.NewInt(params.Ether)
depositTx, err := l1StandardBridge.DepositETH(l1Opts, 200_000, []byte{byte(1)})
require.NoError(t, err)
withdrawTx, err := l2StandardBridge.Withdraw(l2Opts, processor.EthAddress, big.NewInt(params.Ether), 200_000, []byte{byte(1)})
require.NoError(t, err)
depositReceipt, err := utils.WaitReceiptOK(setupCtx, l1Client, depositTx.Hash())
require.NoError(t, err)
withdrawalReceipt, err := utils.WaitReceiptOK(setupCtx, l2Client, withdrawTx.Hash())
require.NoError(t, err)
t.Run("indexes ETH deposits", func(t *testing.T) {
testCtx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
// Pause the L2Processor so that we can test for finalization separately. A pause is
// required since deposit inclusion is apart of the L2 block derivation process
testSuite.Indexer.L2Processor.PauseForTest()
// (1) Test Deposit Initiation
// wait for processor catchup
require.NoError(t, utils.WaitFor(testCtx, 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= depositReceipt.BlockNumber.Uint64(), nil
}))
aliceDeposits, err := testSuite.DB.Bridge.DepositsByAddress(aliceAddr)
require.NoError(t, err)
require.Len(t, aliceDeposits, 1)
require.Equal(t, depositTx.Hash(), aliceDeposits[0].L1TransactionHash)
require.Empty(t, aliceDeposits[0].FinalizedL2TransactionHash)
deposit := aliceDeposits[0].Deposit
require.Nil(t, deposit.FinalizedL2EventGUID)
require.Equal(t, processor.EthAddress, deposit.TokenPair.L1TokenAddress)
require.Equal(t, processor.EthAddress, deposit.TokenPair.L2TokenAddress)
require.Equal(t, big.NewInt(params.Ether), deposit.Tx.Amount.Int)
require.Equal(t, aliceAddr, deposit.Tx.FromAddress)
require.Equal(t, aliceAddr, deposit.Tx.ToAddress)
require.Equal(t, byte(1), deposit.Tx.Data[0])
// (2) Test Deposit Finalization
testSuite.Indexer.L2Processor.ResumeForTest()
// finalization hash can be deterministically derived from TransactionDeposited log
var depositTxHash common.Hash
for _, log := range depositReceipt.Logs {
if log.Topics[0] == derive.DepositEventABIHash {
deposit, err := derive.UnmarshalDepositLogEvent(log)
require.NoError(t, err)
depositTxHash = types.NewTx(deposit).Hash()
break
}
}
// wait for the l2 processor to catch this deposit in the derivation process
_, err = utils.WaitReceiptOK(testCtx, l2Client, depositTxHash)
require.NoError(t, err)
l2Height, err := l2Client.BlockNumber(testCtx)
require.NoError(t, err)
require.NoError(t, utils.WaitFor(testCtx, 500*time.Millisecond, func() (bool, error) {
l2Header := testSuite.Indexer.L2Processor.LatestProcessedHeader()
return l2Header != nil && l2Header.Number.Uint64() >= l2Height, nil
}))
aliceDeposits, err = testSuite.DB.Bridge.DepositsByAddress(aliceAddr)
require.NoError(t, err)
require.Equal(t, depositTxHash, aliceDeposits[0].FinalizedL2TransactionHash)
require.NotNil(t, aliceDeposits[0].Deposit.FinalizedL2EventGUID)
})
t.Run("indexes ETH withdrawals", func(t *testing.T) {
testCtx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
defer cancel()
// (1) Test Withdrawal Initiation
// wait for processor catchup
require.NoError(t, utils.WaitFor(testCtx, 500*time.Millisecond, func() (bool, error) {
l2Header := testSuite.Indexer.L2Processor.LatestProcessedHeader()
return l2Header != nil && l2Header.Number.Uint64() >= withdrawalReceipt.BlockNumber.Uint64(), nil
}))
aliceWithdrawals, err := testSuite.DB.Bridge.WithdrawalsByAddress(aliceAddr)
require.NoError(t, err)
require.Len(t, aliceWithdrawals, 1)
require.Equal(t, withdrawTx.Hash(), aliceWithdrawals[0].L2TransactionHash)
require.Empty(t, aliceWithdrawals[0].ProvenL1TransactionHash)
require.Empty(t, aliceWithdrawals[0].FinalizedL1TransactionHash)
withdrawal := aliceWithdrawals[0].Withdrawal
require.Nil(t, withdrawal.ProvenL1EventGUID)
require.Nil(t, withdrawal.FinalizedL1EventGUID)
require.Equal(t, processor.EthAddress, withdrawal.TokenPair.L1TokenAddress)
require.Equal(t, processor.EthAddress, withdrawal.TokenPair.L2TokenAddress)
require.Equal(t, big.NewInt(params.Ether), withdrawal.Tx.Amount.Int)
require.Equal(t, aliceAddr, withdrawal.Tx.FromAddress)
require.Equal(t, aliceAddr, withdrawal.Tx.ToAddress)
require.Equal(t, byte(1), withdrawal.Tx.Data[0])
// (2) Test Withdrawal Proven
// prove & wait for processor catchup
withdrawParams, proveReceipt := op_e2e.ProveWithdrawal(t, *testSuite.OpCfg, l1Client, testSuite.OpSys.Nodes["sequencer"], testSuite.OpCfg.Secrets.Alice, withdrawalReceipt)
require.NoError(t, utils.WaitFor(testCtx, 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= proveReceipt.BlockNumber.Uint64(), nil
}))
aliceWithdrawals, err = testSuite.DB.Bridge.WithdrawalsByAddress(aliceAddr)
require.NoError(t, err)
require.Empty(t, aliceWithdrawals[0].FinalizedL1TransactionHash)
require.Equal(t, proveReceipt.TxHash, aliceWithdrawals[0].ProvenL1TransactionHash)
// (3) Test Withdrawal Finalization
// finalize & wait for processor catchup
finalizeReceipt := op_e2e.FinalizeWithdrawal(t, *testSuite.OpCfg, l1Client, testSuite.OpCfg.Secrets.Alice, proveReceipt, withdrawParams)
require.NoError(t, utils.WaitFor(testCtx, 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil
}))
aliceWithdrawals, err = testSuite.DB.Bridge.WithdrawalsByAddress(aliceAddr)
require.NoError(t, err)
require.Equal(t, finalizeReceipt.TxHash, aliceWithdrawals[0].FinalizedL1TransactionHash)
})
}
...@@ -23,25 +23,19 @@ import ( ...@@ -23,25 +23,19 @@ import (
func TestE2EBlockHeaders(t *testing.T) { func TestE2EBlockHeaders(t *testing.T) {
testSuite := createE2ETestSuite(t) testSuite := createE2ETestSuite(t)
l1Client := testSuite.OpSys.Clients["l1"] l2OutputOracle, err := bindings.NewL2OutputOracle(testSuite.OpCfg.L1Deployments.L2OutputOracleProxy, testSuite.L1Client)
l2Client := testSuite.OpSys.Clients["sequencer"]
l2OutputOracle, err := bindings.NewL2OutputOracleCaller(testSuite.OpCfg.L1Deployments.L2OutputOracleProxy, l1Client)
require.NoError(t, err) require.NoError(t, err)
// a minute for total setup to finish
setupCtx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
// wait for at least 10 L2 blocks to be created & posted on L1 // wait for at least 10 L2 blocks to be created & posted on L1
require.NoError(t, utils.WaitFor(setupCtx, time.Second, func() (bool, error) { require.NoError(t, utils.WaitFor(context.Background(), time.Second, func() (bool, error) {
l2Height, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{Context: setupCtx}) l2Height, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{Context: context.Background()})
return l2Height != nil && l2Height.Uint64() >= 9, err return l2Height != nil && l2Height.Uint64() >= 9, err
})) }))
// ensure the processors are caught up to this state // ensure the processors are caught up to this state
l1Height, err := l1Client.BlockNumber(setupCtx) l1Height, err := testSuite.L1Client.BlockNumber(context.Background())
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, utils.WaitFor(setupCtx, time.Second, func() (bool, error) { require.NoError(t, utils.WaitFor(context.Background(), time.Second, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader() l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
l2Header := testSuite.Indexer.L2Processor.LatestProcessedHeader() l2Header := testSuite.Indexer.L2Processor.LatestProcessedHeader()
return (l1Header != nil && l1Header.Number.Uint64() >= l1Height) && (l2Header != nil && l2Header.Number.Uint64() >= 9), nil return (l1Header != nil && l1Header.Number.Uint64() >= l1Height) && (l2Header != nil && l2Header.Number.Uint64() >= 9), nil
...@@ -60,7 +54,7 @@ func TestE2EBlockHeaders(t *testing.T) { ...@@ -60,7 +54,7 @@ func TestE2EBlockHeaders(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, indexedHeader) require.NotNil(t, indexedHeader)
header, err := l2Client.HeaderByNumber(context.Background(), height) header, err := testSuite.L2Client.HeaderByNumber(context.Background(), height)
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, indexedHeader) require.NotNil(t, indexedHeader)
...@@ -93,7 +87,7 @@ func TestE2EBlockHeaders(t *testing.T) { ...@@ -93,7 +87,7 @@ func TestE2EBlockHeaders(t *testing.T) {
require.NotEmpty(t, output.L1ContractEventGUID) require.NotEmpty(t, output.L1ContractEventGUID)
// we may as well check the integrity of the output root // we may as well check the integrity of the output root
l2Block, err := l2Client.BlockByNumber(context.Background(), blockNumber) l2Block, err := testSuite.L2Client.BlockByNumber(context.Background(), blockNumber)
require.NoError(t, err) require.NoError(t, err)
messagePasserStorageHash, err := l2EthClient.StorageHash(predeploys.L2ToL1MessagePasserAddr, blockNumber) messagePasserStorageHash, err := l2EthClient.StorageHash(predeploys.L2ToL1MessagePasserAddr, blockNumber)
require.NoError(t, err) require.NoError(t, err)
...@@ -111,12 +105,10 @@ func TestE2EBlockHeaders(t *testing.T) { ...@@ -111,12 +105,10 @@ func TestE2EBlockHeaders(t *testing.T) {
testCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) testCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel() defer cancel()
devContracts := make([]common.Address, 0) l1Contracts := []common.Address{}
testSuite.OpCfg.L1Deployments.ForEach(func(name string, address common.Address) { testSuite.OpCfg.L1Deployments.ForEach(func(name string, addr common.Address) { l1Contracts = append(l1Contracts, addr) })
devContracts = append(devContracts, address) logFilter := ethereum.FilterQuery{FromBlock: big.NewInt(0), ToBlock: big.NewInt(int64(l1Height)), Addresses: l1Contracts}
}) logs, err := testSuite.L1Client.FilterLogs(testCtx, logFilter) // []types.Log
logFilter := ethereum.FilterQuery{FromBlock: big.NewInt(0), ToBlock: big.NewInt(int64(l1Height)), Addresses: devContracts}
logs, err := l1Client.FilterLogs(testCtx, logFilter) // []types.Log
require.NoError(t, err) require.NoError(t, err)
for _, log := range logs { for _, log := range logs {
...@@ -128,7 +120,7 @@ func TestE2EBlockHeaders(t *testing.T) { ...@@ -128,7 +120,7 @@ func TestE2EBlockHeaders(t *testing.T) {
require.Equal(t, log.Index, uint(contractEvent.LogIndex)) require.Equal(t, log.Index, uint(contractEvent.LogIndex))
// ensure the block is also indexed // ensure the block is also indexed
block, err := l1Client.BlockByNumber(testCtx, big.NewInt(int64(log.BlockNumber))) block, err := testSuite.L1Client.BlockByNumber(testCtx, big.NewInt(int64(log.BlockNumber)))
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, block.Time(), contractEvent.Timestamp) require.Equal(t, block.Time(), contractEvent.Timestamp)
......
package e2e_tests
import (
"context"
"math/big"
"testing"
"time"
e2etest_utils "github.com/ethereum-optimism/optimism/indexer/e2e_tests/utils"
op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
"github.com/ethereum-optimism/optimism/op-node/withdrawals"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
)
func TestE2EBridgeTransfersStandardBridgeETHDeposit(t *testing.T) {
testSuite := createE2ETestSuite(t)
l1StandardBridge, err := bindings.NewL1StandardBridge(testSuite.OpCfg.L1Deployments.L1StandardBridgeProxy, testSuite.L1Client)
require.NoError(t, err)
// 1 ETH transfer
aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice
l1Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L1ChainIDBig())
require.NoError(t, err)
l1Opts.Value = big.NewInt(params.Ether)
// Pause the L2Processor so that we can test for finalization separately. A pause is
// required since deposit inclusion is apart of the L2 block derivation process
testSuite.Indexer.L2Processor.PauseForTest()
// (1) Test Deposit Initiation
depositTx, err := l1StandardBridge.DepositETH(l1Opts, 200_000, []byte{byte(1)})
require.NoError(t, err)
depositReceipt, err := utils.WaitReceiptOK(context.Background(), testSuite.L1Client, depositTx.Hash())
require.NoError(t, err)
depositInfo, err := e2etest_utils.ParseDepositInfo(depositReceipt)
require.NoError(t, err)
// wait for processor catchup
require.NoError(t, utils.WaitFor(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= depositReceipt.BlockNumber.Uint64(), nil
}))
aliceDeposits, err := testSuite.DB.BridgeTransfers.L1BridgeDepositsByAddress(aliceAddr)
require.NoError(t, err)
require.Len(t, aliceDeposits, 1)
require.Equal(t, depositTx.Hash(), aliceDeposits[0].L1TransactionHash)
require.Empty(t, aliceDeposits[0].FinalizedL2TransactionHash)
deposit := aliceDeposits[0].L1BridgeDeposit
require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.L1TokenAddress)
require.Equal(t, predeploys.LegacyERC20ETHAddr, deposit.TokenPair.L2TokenAddress)
require.Equal(t, big.NewInt(params.Ether), deposit.Tx.Amount.Int)
require.Equal(t, aliceAddr, deposit.Tx.FromAddress)
require.Equal(t, aliceAddr, deposit.Tx.ToAddress)
require.Equal(t, byte(1), deposit.Tx.Data[0])
// (2) Test Deposit Finalization
require.Nil(t, deposit.FinalizedL2EventGUID)
testSuite.Indexer.L2Processor.ResumeForTest()
// wait for the l2 processor to catch this deposit in the derivation process
depositReceipt, err = utils.WaitReceiptOK(context.Background(), testSuite.L2Client, types.NewTx(depositInfo.DepositTx).Hash())
require.NoError(t, err)
require.NoError(t, utils.WaitFor(context.Background(), 500*time.Millisecond, func() (bool, error) {
l2Header := testSuite.Indexer.L2Processor.LatestProcessedHeader()
return l2Header != nil && l2Header.Number.Uint64() >= depositReceipt.BlockNumber.Uint64(), nil
}))
aliceDeposits, err = testSuite.DB.BridgeTransfers.L1BridgeDepositsByAddress(aliceAddr)
require.NoError(t, err)
require.NotNil(t, aliceDeposits[0].L1BridgeDeposit.FinalizedL2EventGUID)
require.Equal(t, types.NewTx(depositInfo.DepositTx).Hash(), aliceDeposits[0].FinalizedL2TransactionHash)
}
func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) {
testSuite := createE2ETestSuite(t)
optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client)
require.NoError(t, err)
l2StandardBridge, err := bindings.NewL2StandardBridge(predeploys.L2StandardBridgeAddr, testSuite.L2Client)
require.NoError(t, err)
// 1 ETH transfer
aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice
l2Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L2ChainIDBig())
require.NoError(t, err)
l2Opts.Value = big.NewInt(params.Ether)
// Ensure L1 has enough funds for the withdrawal by depositing an equal amount into the OptimismPortal
l1Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L1ChainIDBig())
require.NoError(t, err)
l1Opts.Value = l2Opts.Value
depositTx, err := optimismPortal.Receive(l1Opts)
require.NoError(t, err)
_, err = utils.WaitReceiptOK(context.Background(), testSuite.L1Client, depositTx.Hash())
require.NoError(t, err)
// (1) Test Withdrawal Initiation
withdrawTx, err := l2StandardBridge.Withdraw(l2Opts, predeploys.LegacyERC20ETHAddr, l2Opts.Value, 200_000, []byte{byte(1)})
require.NoError(t, err)
withdrawReceipt, err := utils.WaitReceiptOK(context.Background(), testSuite.L2Client, withdrawTx.Hash())
require.NoError(t, err)
// wait for processor catchup
require.NoError(t, utils.WaitFor(context.Background(), 500*time.Millisecond, func() (bool, error) {
l2Header := testSuite.Indexer.L2Processor.LatestProcessedHeader()
return l2Header != nil && l2Header.Number.Uint64() >= withdrawReceipt.BlockNumber.Uint64(), nil
}))
aliceWithdrawals, err := testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr)
require.NoError(t, err)
require.Len(t, aliceWithdrawals, 1)
require.Equal(t, withdrawTx.Hash(), aliceWithdrawals[0].L2TransactionHash)
msgPassed, err := withdrawals.ParseMessagePassed(withdrawReceipt)
require.NoError(t, err)
withdrawalHash, err := withdrawals.WithdrawalHash(msgPassed)
require.NoError(t, err)
withdrawal := aliceWithdrawals[0].L2BridgeWithdrawal
require.Equal(t, withdrawalHash, withdrawal.WithdrawalHash)
require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.L1TokenAddress)
require.Equal(t, predeploys.LegacyERC20ETHAddr, withdrawal.TokenPair.L2TokenAddress)
require.Equal(t, big.NewInt(params.Ether), withdrawal.Tx.Amount.Int)
require.Equal(t, aliceAddr, withdrawal.Tx.FromAddress)
require.Equal(t, aliceAddr, withdrawal.Tx.ToAddress)
require.Equal(t, byte(1), withdrawal.Tx.Data[0])
// (2) Test Withdrawal Proven/Finalized. Test the sql join queries to populate the right transaction
require.Nil(t, withdrawal.ProvenL1EventGUID)
require.Nil(t, withdrawal.FinalizedL1EventGUID)
require.Empty(t, aliceWithdrawals[0].ProvenL1TransactionHash)
require.Empty(t, aliceWithdrawals[0].FinalizedL1TransactionHash)
// wait for processor catchup
proveReceipt, finalizeReceipt := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, testSuite.OpSys.Nodes["sequencer"], testSuite.OpCfg.Secrets.Alice, withdrawReceipt)
require.NoError(t, utils.WaitFor(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil
}))
aliceWithdrawals, err = testSuite.DB.BridgeTransfers.L2BridgeWithdrawalsByAddress(aliceAddr)
require.NoError(t, err)
require.NotNil(t, aliceWithdrawals[0].L2BridgeWithdrawal.ProvenL1EventGUID)
require.NotNil(t, aliceWithdrawals[0].L2BridgeWithdrawal.FinalizedL1EventGUID)
require.Equal(t, proveReceipt.TxHash, aliceWithdrawals[0].ProvenL1TransactionHash)
require.Equal(t, finalizeReceipt.TxHash, aliceWithdrawals[0].FinalizedL1TransactionHash)
}
...@@ -17,6 +17,7 @@ import ( ...@@ -17,6 +17,7 @@ import (
op_e2e "github.com/ethereum-optimism/optimism/op-e2e" op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
"github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
_ "github.com/jackc/pgx/v5/stdlib" _ "github.com/jackc/pgx/v5/stdlib"
...@@ -33,6 +34,10 @@ type E2ETestSuite struct { ...@@ -33,6 +34,10 @@ type E2ETestSuite struct {
// Rollup // Rollup
OpCfg *op_e2e.SystemConfig OpCfg *op_e2e.SystemConfig
OpSys *op_e2e.System OpSys *op_e2e.System
// Clients
L1Client *ethclient.Client
L2Client *ethclient.Client
} }
func createE2ETestSuite(t *testing.T) E2ETestSuite { func createE2ETestSuite(t *testing.T) E2ETestSuite {
...@@ -48,16 +53,9 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { ...@@ -48,16 +53,9 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite {
opSys, err := opCfg.Start() opSys, err := opCfg.Start()
require.NoError(t, err) require.NoError(t, err)
l1Contracts := processor.L1Contracts{
OptimismPortal: opCfg.L1Deployments.OptimismPortalProxy,
L2OutputOracle: opCfg.L1Deployments.L2OutputOracleProxy,
L1CrossDomainMessenger: opCfg.L1Deployments.L1CrossDomainMessengerProxy,
L1StandardBridge: opCfg.L1Deployments.L1StandardBridgeProxy,
L1ERC721Bridge: opCfg.L1Deployments.L1ERC721BridgeProxy,
}
// Indexer Configuration and Start // Indexer Configuration and Start
indexerCfg := config.Config{ indexerCfg := config.Config{
Logger: logger,
DB: config.DBConfig{ DB: config.DBConfig{
Host: "127.0.0.1", Host: "127.0.0.1",
Port: 5432, Port: 5432,
...@@ -68,9 +66,14 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { ...@@ -68,9 +66,14 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite {
L1RPC: opSys.Nodes["l1"].HTTPEndpoint(), L1RPC: opSys.Nodes["l1"].HTTPEndpoint(),
L2RPC: opSys.Nodes["sequencer"].HTTPEndpoint(), L2RPC: opSys.Nodes["sequencer"].HTTPEndpoint(),
}, },
Logger: logger,
Chain: config.ChainConfig{ Chain: config.ChainConfig{
L1Contracts: l1Contracts, L1Contracts: processor.L1Contracts{
OptimismPortal: opCfg.L1Deployments.OptimismPortalProxy,
L2OutputOracle: opCfg.L1Deployments.L2OutputOracleProxy,
L1CrossDomainMessenger: opCfg.L1Deployments.L1CrossDomainMessengerProxy,
L1StandardBridge: opCfg.L1Deployments.L1StandardBridgeProxy,
L1ERC721Bridge: opCfg.L1Deployments.L1ERC721BridgeProxy,
},
}, },
} }
...@@ -99,11 +102,13 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { ...@@ -99,11 +102,13 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite {
}) })
return E2ETestSuite{ return E2ETestSuite{
t: t, t: t,
DB: db, DB: db,
Indexer: indexer, Indexer: indexer,
OpCfg: &opCfg, OpCfg: &opCfg,
OpSys: opSys, OpSys: opSys,
L1Client: opSys.Clients["l1"],
L2Client: opSys.Clients["sequencer"],
} }
} }
......
package utils
import (
"errors"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
type DepositInfo struct {
*bindings.OptimismPortalTransactionDeposited
DepositTx *types.DepositTx
}
func ParseDepositInfo(depositReceipt *types.Receipt) (*DepositInfo, error) {
optimismPortal, err := bindings.NewOptimismPortal(common.Address{}, nil)
if err != nil {
return nil, err
}
for _, log := range depositReceipt.Logs {
if log.Topics[0] == derive.DepositEventABIHash {
portalTxDeposited, err := optimismPortal.ParseTransactionDeposited(*log)
if err != nil {
return nil, err
}
depositTx, err := derive.UnmarshalDepositLogEvent(log)
if err != nil {
return nil, err
}
return &DepositInfo{portalTxDeposited, depositTx}, nil
}
}
return nil, errors.New("cannot find deposit event in receipt")
}
...@@ -72,21 +72,30 @@ func NewIndexer(cfg config.Config) (*Indexer, error) { ...@@ -72,21 +72,30 @@ func NewIndexer(cfg config.Config) (*Indexer, error) {
// Start starts the indexing service on L1 and L2 chains // Start starts the indexing service on L1 and L2 chains
func (i *Indexer) Run(ctx context.Context) error { func (i *Indexer) Run(ctx context.Context) error {
var wg sync.WaitGroup var wg sync.WaitGroup
errCh := make(chan error) errCh := make(chan error, 1)
// If either processor errors out, we stop // If either processor errors out, we stop
processorCtx, cancel := context.WithCancel(ctx) processorCtx, cancel := context.WithCancel(ctx)
run := func(start func(ctx context.Context) error) { run := func(start func(ctx context.Context) error) {
wg.Add(1) wg.Add(1)
defer wg.Done() defer func() {
if err := recover(); err != nil {
i.log.Error("halting indexer on panic", "err", err)
errCh <- fmt.Errorf("panic: %v", err)
}
wg.Done()
}()
err := start(processorCtx) err := start(processorCtx)
if err != nil { if err != nil {
i.log.Error("halting indexer on error", "err", err) i.log.Error("halting indexer on error", "err", err)
cancel() cancel()
errCh <- err
} }
// Send a value down regardless if we've received an error or halted
// via cancellation where err == nil
errCh <- err
} }
// Kick off the processors // Kick off the processors
......
...@@ -67,12 +67,12 @@ CREATE TABLE IF NOT EXISTS output_proposals ( ...@@ -67,12 +67,12 @@ CREATE TABLE IF NOT EXISTS output_proposals (
* BRIDGING DATA * BRIDGING DATA
*/ */
CREATE TABLE IF NOT EXISTS deposits ( CREATE TABLE IF NOT EXISTS l1_bridge_deposits (
guid VARCHAR PRIMARY KEY NOT NULL, guid VARCHAR PRIMARY KEY NOT NULL,
-- Event causing the deposit -- Event causing the deposit
initiated_l1_event_guid VARCHAR NOT NULL REFERENCES l1_contract_events(guid), initiated_l1_event_guid VARCHAR NOT NULL REFERENCES l1_contract_events(guid),
sent_message_nonce UINT256 UNIQUE, cross_domain_messenger_nonce UINT256 UNIQUE,
-- Finalization marker for the deposit -- Finalization marker for the deposit
finalized_l2_event_guid VARCHAR REFERENCES l2_contract_events(guid), finalized_l2_event_guid VARCHAR REFERENCES l2_contract_events(guid),
...@@ -88,12 +88,12 @@ CREATE TABLE IF NOT EXISTS deposits ( ...@@ -88,12 +88,12 @@ CREATE TABLE IF NOT EXISTS deposits (
timestamp INTEGER NOT NULL CHECK (timestamp > 0) timestamp INTEGER NOT NULL CHECK (timestamp > 0)
); );
CREATE TABLE IF NOT EXISTS withdrawals ( CREATE TABLE IF NOT EXISTS l2_bridge_withdrawals (
guid VARCHAR PRIMARY KEY NOT NULL, guid VARCHAR PRIMARY KEY NOT NULL,
-- Event causing this withdrawal -- Event causing this withdrawal
initiated_l2_event_guid VARCHAR NOT NULL REFERENCES l2_contract_events(guid), initiated_l2_event_guid VARCHAR NOT NULL REFERENCES l2_contract_events(guid),
sent_message_nonce UINT256 UNIQUE, cross_domain_messenger_nonce UINT256 UNIQUE,
-- Multistep (bedrock) process of a withdrawal -- Multistep (bedrock) process of a withdrawal
withdrawal_hash VARCHAR NOT NULL, withdrawal_hash VARCHAR NOT NULL,
......
...@@ -255,13 +255,13 @@ func l1BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl ...@@ -255,13 +255,13 @@ func l1BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl
return err return err
} }
deposits := make([]*database.Deposit, len(initiatedDepositEvents)) deposits := make([]*database.L1BridgeDeposit, len(initiatedDepositEvents))
for i, initiatedBridgeEvent := range initiatedDepositEvents { for i, initiatedBridgeEvent := range initiatedDepositEvents {
deposits[i] = &database.Deposit{ deposits[i] = &database.L1BridgeDeposit{
GUID: uuid.New(), GUID: uuid.New(),
InitiatedL1EventGUID: initiatedBridgeEvent.RawEvent.GUID, InitiatedL1EventGUID: initiatedBridgeEvent.RawEvent.GUID,
SentMessageNonce: database.U256{Int: initiatedBridgeEvent.CrossDomainMessengerNonce}, CrossDomainMessengerNonce: database.U256{Int: initiatedBridgeEvent.CrossDomainMessengerNonce},
TokenPair: database.TokenPair{L1TokenAddress: initiatedBridgeEvent.LocalToken, L2TokenAddress: initiatedBridgeEvent.RemoteToken}, TokenPair: database.TokenPair{L1TokenAddress: initiatedBridgeEvent.LocalToken, L2TokenAddress: initiatedBridgeEvent.RemoteToken},
Tx: database.Transaction{ Tx: database.Transaction{
FromAddress: initiatedBridgeEvent.From, FromAddress: initiatedBridgeEvent.From,
ToAddress: initiatedBridgeEvent.To, ToAddress: initiatedBridgeEvent.To,
...@@ -274,7 +274,7 @@ func l1BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl ...@@ -274,7 +274,7 @@ func l1BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl
if len(deposits) > 0 { if len(deposits) > 0 {
processLog.Info("detected L1StandardBridge deposits", "num", len(deposits)) processLog.Info("detected L1StandardBridge deposits", "num", len(deposits))
err := db.Bridge.StoreDeposits(deposits) err := db.BridgeTransfers.StoreL1BridgeDeposits(deposits)
if err != nil { if err != nil {
return err return err
} }
...@@ -286,47 +286,39 @@ func l1BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl ...@@ -286,47 +286,39 @@ func l1BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl
return err return err
} }
// we manually keep track since not every proven withdrawal is a standard bridge withdrawal latestL2Header, err := db.Blocks.LatestL2BlockHeader()
if err != nil {
return err
} else if len(provenWithdrawalEvents) > 0 && latestL2Header == nil {
return errors.New("no indexed L2 state to process any proven L1 transactions")
}
numProvenWithdrawals := 0 numProvenWithdrawals := 0
for _, provenWithdrawalEvent := range provenWithdrawalEvents { for _, provenWithdrawalEvent := range provenWithdrawalEvents {
withdrawalHash := provenWithdrawalEvent.WithdrawalHash withdrawalHash := provenWithdrawalEvent.WithdrawalHash
withdrawal, err := db.Bridge.WithdrawalByHash(withdrawalHash) withdrawal, err := db.BridgeTransfers.L2BridgeWithdrawalByWithdrawalHash(withdrawalHash)
if err != nil { if err != nil {
return err return err
} } else if withdrawal == nil {
// NOTE: This needs to be updated to identify if this CrossDomainMessenger message is a StandardBridge message. This
// Check if the L2Processor is behind or really has missed an event. We can compare against the // will be easier to do once we index cross domain messages and track its lifecyle separately
// OptimismPortal#ProvenWithdrawal on-chain mapping relative to the latest indexed L2 height
if withdrawal == nil {
// This needs to be updated to read from config as well as correctly identify if the CrossDomainMessenger message is a standard
// bridge message. This will easier to do once we index passed messages separately which will include the right To/From fields
if provenWithdrawalEvent.From != common.HexToAddress("0x4200000000000000000000000000000000000007") || provenWithdrawalEvent.To != l1Contracts.L1CrossDomainMessenger { if provenWithdrawalEvent.From != common.HexToAddress("0x4200000000000000000000000000000000000007") || provenWithdrawalEvent.To != l1Contracts.L1CrossDomainMessenger {
// non-bridge withdrawal // non-bridge withdrawal
continue continue
} }
// Query for the the proven withdrawal on-chain // Check if the L2Processor is behind or really has missed an event. Since L2 timestamps
provenWithdrawal, err := OptimismPortalQueryProvenWithdrawal(rawEthClient, l1Contracts.OptimismPortal, withdrawalHash) // are derived from L1, we can simply compare timestamps
if err != nil { if provenWithdrawalEvent.RawEvent.Timestamp > latestL2Header.Timestamp {
return err processLog.Warn("behind on indexed L2StandardBridge withdrawals")
}
latestL2Header, err := db.Blocks.LatestL2BlockHeader()
if err != nil {
return err
}
if latestL2Header == nil || provenWithdrawal.L2OutputIndex.Cmp(latestL2Header.Number.Int) > 0 {
processLog.Warn("behind on indexed L2 withdrawals")
return errors.New("waiting for L2Processor to catch up") return errors.New("waiting for L2Processor to catch up")
} else { } else {
processLog.Crit("missing indexed withdrawal for this proven event") processLog.Crit("missing indexed L2StandardBridge withdrawal for this proven event")
return errors.New("missing withdrawal message") return errors.New("missing withdrawal message")
} }
} }
err = db.Bridge.MarkProvenWithdrawalEvent(withdrawal.GUID, provenWithdrawalEvent.RawEvent.GUID) err = db.BridgeTransfers.MarkProvenL2BridgeWithdrawalEvent(withdrawal.GUID, provenWithdrawalEvent.RawEvent.GUID)
if err != nil { if err != nil {
return err return err
} }
...@@ -346,7 +338,7 @@ func l1BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl ...@@ -346,7 +338,7 @@ func l1BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl
for _, finalizedBridgeEvent := range finalizedWithdrawalEvents { for _, finalizedBridgeEvent := range finalizedWithdrawalEvents {
nonce := finalizedBridgeEvent.CrossDomainMessengerNonce nonce := finalizedBridgeEvent.CrossDomainMessengerNonce
withdrawal, err := db.Bridge.WithdrawalByMessageNonce(nonce) withdrawal, err := db.BridgeTransfers.L2BridgeWithdrawalByCrossDomainMessengerNonce(nonce)
if err != nil { if err != nil {
processLog.Error("error querying associated withdrawal messsage using nonce", "cross_domain_messenger_nonce", nonce) processLog.Error("error querying associated withdrawal messsage using nonce", "cross_domain_messenger_nonce", nonce)
return err return err
...@@ -359,7 +351,7 @@ func l1BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl ...@@ -359,7 +351,7 @@ func l1BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl
return errors.New("missing withdrawal message") return errors.New("missing withdrawal message")
} }
err = db.Bridge.MarkFinalizedWithdrawalEvent(withdrawal.GUID, finalizedBridgeEvent.RawEvent.GUID) err = db.BridgeTransfers.MarkFinalizedL2BridgeWithdrawalEvent(withdrawal.GUID, finalizedBridgeEvent.RawEvent.GUID)
if err != nil { if err != nil {
processLog.Error("error finalizing withdrawal", "err", err) processLog.Error("error finalizing withdrawal", "err", err)
return err return err
......
...@@ -183,7 +183,7 @@ func l2BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl ...@@ -183,7 +183,7 @@ func l2BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl
return err return err
} }
withdrawals := make([]*database.Withdrawal, len(initiatedWithdrawalEvents)) withdrawals := make([]*database.L2BridgeWithdrawal, len(initiatedWithdrawalEvents))
for i, initiatedBridgeEvent := range initiatedWithdrawalEvents { for i, initiatedBridgeEvent := range initiatedWithdrawalEvents {
log := events.eventLog[initiatedBridgeEvent.RawEvent.GUID] log := events.eventLog[initiatedBridgeEvent.RawEvent.GUID]
...@@ -195,12 +195,12 @@ func l2BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl ...@@ -195,12 +195,12 @@ func l2BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl
return err return err
} }
withdrawals[i] = &database.Withdrawal{ withdrawals[i] = &database.L2BridgeWithdrawal{
GUID: uuid.New(), GUID: uuid.New(),
InitiatedL2EventGUID: initiatedBridgeEvent.RawEvent.GUID, InitiatedL2EventGUID: initiatedBridgeEvent.RawEvent.GUID,
SentMessageNonce: database.U256{Int: initiatedBridgeEvent.CrossDomainMessengerNonce}, CrossDomainMessengerNonce: database.U256{Int: initiatedBridgeEvent.CrossDomainMessengerNonce},
WithdrawalHash: msgPassedData.WithdrawalHash, WithdrawalHash: msgPassedData.WithdrawalHash,
TokenPair: database.TokenPair{L1TokenAddress: initiatedBridgeEvent.LocalToken, L2TokenAddress: initiatedBridgeEvent.RemoteToken}, TokenPair: database.TokenPair{L1TokenAddress: initiatedBridgeEvent.LocalToken, L2TokenAddress: initiatedBridgeEvent.RemoteToken},
Tx: database.Transaction{ Tx: database.Transaction{
FromAddress: initiatedBridgeEvent.From, FromAddress: initiatedBridgeEvent.From,
ToAddress: initiatedBridgeEvent.To, ToAddress: initiatedBridgeEvent.To,
...@@ -213,7 +213,7 @@ func l2BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl ...@@ -213,7 +213,7 @@ func l2BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl
if len(withdrawals) > 0 { if len(withdrawals) > 0 {
processLog.Info("detected L2StandardBridge withdrawals", "num", len(withdrawals)) processLog.Info("detected L2StandardBridge withdrawals", "num", len(withdrawals))
err := db.Bridge.StoreWithdrawals(withdrawals) err := db.BridgeTransfers.StoreL2BridgeWithdrawals(withdrawals)
if err != nil { if err != nil {
return err return err
} }
...@@ -225,30 +225,33 @@ func l2BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl ...@@ -225,30 +225,33 @@ func l2BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl
return err return err
} }
latestL1Header, err := db.Blocks.LatestL1BlockHeader()
if err != nil {
return err
} else if len(finalizationBridgeEvents) > 0 && latestL1Header == nil {
return errors.New("no indexed L1 state to process any L2 bridge finalizations")
}
for _, finalizedBridgeEvent := range finalizationBridgeEvents { for _, finalizedBridgeEvent := range finalizationBridgeEvents {
nonce := finalizedBridgeEvent.CrossDomainMessengerNonce nonce := finalizedBridgeEvent.CrossDomainMessengerNonce
deposit, err := db.Bridge.DepositByMessageNonce(nonce) deposit, err := db.BridgeTransfers.L1BridgeDepositByCrossDomainMessengerNonce(nonce)
if err != nil { if err != nil {
processLog.Error("error querying associated deposit messsage using nonce", "cross_domain_messenger_nonce", nonce) processLog.Error("error querying associated deposit messsage using nonce", "cross_domain_messenger_nonce", nonce)
return err return err
} else if deposit == nil { } else if deposit == nil {
latestNonce, err := db.Bridge.LatestDepositMessageNonce() // Check if the L1Processor is behind or really has missed an event. Since L2 timestamps
if err != nil { // are derived from L1, we can simply compare timestamps
return err if finalizedBridgeEvent.RawEvent.Timestamp > latestL1Header.Timestamp {
} processLog.Warn("behind on indexed L1StandardBridge deposits")
// Check if the L1Processor is behind or really has missed an event
if latestNonce == nil || nonce.Cmp(latestNonce) > 0 {
processLog.Warn("behind on indexed L1 deposits")
return errors.New("waiting for L1Processor to catch up") return errors.New("waiting for L1Processor to catch up")
} else { } else {
processLog.Crit("missing indexed deposit for this finalization event") processLog.Crit("missing indexed L1StandardBridge deposit for this finalization event")
return errors.New("missing deposit message") return errors.New("missing deposit message")
} }
} }
err = db.Bridge.MarkFinalizedDepositEvent(deposit.GUID, finalizedBridgeEvent.RawEvent.GUID) err = db.BridgeTransfers.MarkFinalizedL1BridgeDepositEvent(deposit.GUID, finalizedBridgeEvent.RawEvent.GUID)
if err != nil { if err != nil {
processLog.Error("error finalizing deposit", "err", err) processLog.Error("error finalizing deposit", "err", err)
return err return err
......
...@@ -9,19 +9,15 @@ import ( ...@@ -9,19 +9,15 @@ import (
"github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
) )
var (
EthAddress = common.HexToAddress("0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000")
)
type StandardBridgeInitiatedEvent struct { type StandardBridgeInitiatedEvent struct {
// We hardcode to ERC20 since ETH can be pseudo-represented as an ERC20 utilizing // We hardcode to ERC20 since ETH can be pseudo-represented as an ERC20 utilizing
// the hardcoded ETH address // the hardcoded ETH address
*bindings.L1StandardBridgeERC20BridgeInitiated *bindings.StandardBridgeERC20BridgeInitiated
CrossDomainMessengerNonce *big.Int CrossDomainMessengerNonce *big.Int
RawEvent *database.ContractEvent RawEvent *database.ContractEvent
...@@ -30,7 +26,7 @@ type StandardBridgeInitiatedEvent struct { ...@@ -30,7 +26,7 @@ type StandardBridgeInitiatedEvent struct {
type StandardBridgeFinalizedEvent struct { type StandardBridgeFinalizedEvent struct {
// We hardcode to ERC20 since ETH can be pseudo-represented as an ERC20 utilizing // We hardcode to ERC20 since ETH can be pseudo-represented as an ERC20 utilizing
// the hardcoded ETH address // the hardcoded ETH address
*bindings.L1StandardBridgeERC20BridgeFinalized *bindings.StandardBridgeERC20BridgeFinalized
CrossDomainMessengerNonce *big.Int CrossDomainMessengerNonce *big.Int
RawEvent *database.ContractEvent RawEvent *database.ContractEvent
...@@ -39,12 +35,12 @@ type StandardBridgeFinalizedEvent struct { ...@@ -39,12 +35,12 @@ type StandardBridgeFinalizedEvent struct {
// StandardBridgeInitiatedEvents extracts all initiated bridge events from the contracts that follow the StandardBridge ABI. The // StandardBridgeInitiatedEvents extracts all initiated bridge events from the contracts that follow the StandardBridge ABI. The
// correlated CrossDomainMessenger nonce is also parsed from the associated messenger events. // correlated CrossDomainMessenger nonce is also parsed from the associated messenger events.
func StandardBridgeInitiatedEvents(events *ProcessedContractEvents) ([]StandardBridgeInitiatedEvent, error) { func StandardBridgeInitiatedEvents(events *ProcessedContractEvents) ([]StandardBridgeInitiatedEvent, error) {
ethBridgeInitiatedEvents, err := _standardBridgeInitiatedEvents[bindings.L1StandardBridgeETHBridgeInitiated](events) ethBridgeInitiatedEvents, err := _standardBridgeInitiatedEvents[bindings.StandardBridgeETHBridgeInitiated](events)
if err != nil { if err != nil {
return nil, err return nil, err
} }
erc20BridgeInitiatedEvents, err := _standardBridgeInitiatedEvents[bindings.L1StandardBridgeERC20BridgeInitiated](events) erc20BridgeInitiatedEvents, err := _standardBridgeInitiatedEvents[bindings.StandardBridgeERC20BridgeInitiated](events)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -55,12 +51,12 @@ func StandardBridgeInitiatedEvents(events *ProcessedContractEvents) ([]StandardB ...@@ -55,12 +51,12 @@ func StandardBridgeInitiatedEvents(events *ProcessedContractEvents) ([]StandardB
// StandardBridgeFinalizedEvents extracts all finalization bridge events from the contracts that follow the StandardBridge ABI. The // StandardBridgeFinalizedEvents extracts all finalization bridge events from the contracts that follow the StandardBridge ABI. The
// correlated CrossDomainMessenger nonce is also parsed by looking at the parameters of the corresponding relayMessage transaction data. // correlated CrossDomainMessenger nonce is also parsed by looking at the parameters of the corresponding relayMessage transaction data.
func StandardBridgeFinalizedEvents(rawEthClient *ethclient.Client, events *ProcessedContractEvents) ([]StandardBridgeFinalizedEvent, error) { func StandardBridgeFinalizedEvents(rawEthClient *ethclient.Client, events *ProcessedContractEvents) ([]StandardBridgeFinalizedEvent, error) {
ethBridgeFinalizedEvents, err := _standardBridgeFinalizedEvents[bindings.L1StandardBridgeETHBridgeFinalized](rawEthClient, events) ethBridgeFinalizedEvents, err := _standardBridgeFinalizedEvents[bindings.StandardBridgeETHBridgeFinalized](rawEthClient, events)
if err != nil { if err != nil {
return nil, err return nil, err
} }
erc20BridgeFinalizedEvents, err := _standardBridgeFinalizedEvents[bindings.L1StandardBridgeERC20BridgeFinalized](rawEthClient, events) erc20BridgeFinalizedEvents, err := _standardBridgeFinalizedEvents[bindings.StandardBridgeERC20BridgeFinalized](rawEthClient, events)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -69,10 +65,10 @@ func StandardBridgeFinalizedEvents(rawEthClient *ethclient.Client, events *Proce ...@@ -69,10 +65,10 @@ func StandardBridgeFinalizedEvents(rawEthClient *ethclient.Client, events *Proce
} }
// parse out eth or erc20 bridge initiated events // parse out eth or erc20 bridge initiated events
func _standardBridgeInitiatedEvents[BridgeEvent bindings.L1StandardBridgeETHBridgeInitiated | bindings.L1StandardBridgeERC20BridgeInitiated]( func _standardBridgeInitiatedEvents[BridgeEvent bindings.StandardBridgeETHBridgeInitiated | bindings.StandardBridgeERC20BridgeInitiated](
events *ProcessedContractEvents, events *ProcessedContractEvents,
) ([]StandardBridgeInitiatedEvent, error) { ) ([]StandardBridgeInitiatedEvent, error) {
l1StandardBridgeABI, err := bindings.L1StandardBridgeMetaData.GetAbi() StandardBridgeABI, err := bindings.StandardBridgeMetaData.GetAbi()
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -88,23 +84,23 @@ func _standardBridgeInitiatedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid ...@@ -88,23 +84,23 @@ func _standardBridgeInitiatedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid
var eventName string var eventName string
var finalizeMethodName string var finalizeMethodName string
switch any(tmp).(type) { switch any(tmp).(type) {
case bindings.L1StandardBridgeETHBridgeInitiated: case bindings.StandardBridgeETHBridgeInitiated:
eventName = "ETHBridgeInitiated" eventName = "ETHBridgeInitiated"
finalizeMethodName = "finalizeBridgeETH" finalizeMethodName = "finalizeBridgeETH"
case bindings.L1StandardBridgeERC20BridgeInitiated: case bindings.StandardBridgeERC20BridgeInitiated:
eventName = "ERC20BridgeInitiated" eventName = "ERC20BridgeInitiated"
finalizeMethodName = "finalizeBridgeERC20" finalizeMethodName = "finalizeBridgeERC20"
default: default:
panic("should not be here") panic("should not be here")
} }
processedInitiatedBridgeEvents := events.eventsBySignature[l1StandardBridgeABI.Events[eventName].ID] processedInitiatedBridgeEvents := events.eventsBySignature[StandardBridgeABI.Events[eventName].ID]
initiatedBridgeEvents := make([]StandardBridgeInitiatedEvent, len(processedInitiatedBridgeEvents)) initiatedBridgeEvents := make([]StandardBridgeInitiatedEvent, len(processedInitiatedBridgeEvents))
for i, bridgeInitiatedEvent := range processedInitiatedBridgeEvents { for i, bridgeInitiatedEvent := range processedInitiatedBridgeEvents {
log := events.eventLog[bridgeInitiatedEvent.GUID] log := events.eventLog[bridgeInitiatedEvent.GUID]
bridgeData := new(BridgeEvent) var bridgeData BridgeEvent
err := UnpackLog(bridgeData, log, eventName, l1StandardBridgeABI) err := UnpackLog(&bridgeData, log, eventName, StandardBridgeABI)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -119,28 +115,28 @@ func _standardBridgeInitiatedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid ...@@ -119,28 +115,28 @@ func _standardBridgeInitiatedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid
return nil, err return nil, err
} }
var erc20BridgeData *bindings.L1StandardBridgeERC20BridgeInitiated var erc20BridgeData *bindings.StandardBridgeERC20BridgeInitiated
var expectedCrossDomainMessage []byte var expectedCrossDomainMessage []byte
switch any(bridgeData).(type) { switch any(bridgeData).(type) {
case *bindings.L1StandardBridgeETHBridgeInitiated: case bindings.StandardBridgeETHBridgeInitiated:
ethBridgeData := any(bridgeData).(*bindings.L1StandardBridgeETHBridgeInitiated) ethBridgeData := any(bridgeData).(bindings.StandardBridgeETHBridgeInitiated)
expectedCrossDomainMessage, err = l1StandardBridgeABI.Pack(finalizeMethodName, ethBridgeData.From, ethBridgeData.To, ethBridgeData.Amount, ethBridgeData.ExtraData) expectedCrossDomainMessage, err = StandardBridgeABI.Pack(finalizeMethodName, ethBridgeData.From, ethBridgeData.To, ethBridgeData.Amount, ethBridgeData.ExtraData)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// represent eth bridge as an erc20 // represent eth bridge as an erc20
erc20BridgeData = &bindings.L1StandardBridgeERC20BridgeInitiated{ erc20BridgeData = &bindings.StandardBridgeERC20BridgeInitiated{
// Represent ETH using the hardcoded address // Represent ETH using the hardcoded address
LocalToken: EthAddress, RemoteToken: EthAddress, LocalToken: predeploys.LegacyERC20ETHAddr, RemoteToken: predeploys.LegacyERC20ETHAddr,
// Bridge data // Bridge data
From: ethBridgeData.From, To: ethBridgeData.To, Amount: ethBridgeData.Amount, ExtraData: ethBridgeData.ExtraData, From: ethBridgeData.From, To: ethBridgeData.To, Amount: ethBridgeData.Amount, ExtraData: ethBridgeData.ExtraData,
} }
case *bindings.L1StandardBridgeERC20BridgeInitiated: case bindings.StandardBridgeERC20BridgeInitiated:
_temp := any(bridgeData).(bindings.L1StandardBridgeERC20BridgeInitiated) _temp := any(bridgeData).(bindings.StandardBridgeERC20BridgeInitiated)
erc20BridgeData = &_temp erc20BridgeData = &_temp
expectedCrossDomainMessage, err = l1StandardBridgeABI.Pack(finalizeMethodName, erc20BridgeData.RemoteToken, erc20BridgeData.LocalToken, erc20BridgeData.From, erc20BridgeData.To, erc20BridgeData.Amount, erc20BridgeData.ExtraData) expectedCrossDomainMessage, err = StandardBridgeABI.Pack(finalizeMethodName, erc20BridgeData.RemoteToken, erc20BridgeData.LocalToken, erc20BridgeData.From, erc20BridgeData.To, erc20BridgeData.Amount, erc20BridgeData.ExtraData)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -157,11 +153,11 @@ func _standardBridgeInitiatedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid ...@@ -157,11 +153,11 @@ func _standardBridgeInitiatedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid
} }
// parse out eth or erc20 bridge finalization events // parse out eth or erc20 bridge finalization events
func _standardBridgeFinalizedEvents[BridgeEvent bindings.L1StandardBridgeETHBridgeFinalized | bindings.L1StandardBridgeERC20BridgeFinalized]( func _standardBridgeFinalizedEvents[BridgeEvent bindings.StandardBridgeETHBridgeFinalized | bindings.StandardBridgeERC20BridgeFinalized](
rawEthClient *ethclient.Client, rawEthClient *ethclient.Client,
events *ProcessedContractEvents, events *ProcessedContractEvents,
) ([]StandardBridgeFinalizedEvent, error) { ) ([]StandardBridgeFinalizedEvent, error) {
l1StandardBridgeABI, err := bindings.L1StandardBridgeMetaData.GetAbi() StandardBridgeABI, err := bindings.StandardBridgeMetaData.GetAbi()
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -183,21 +179,21 @@ func _standardBridgeFinalizedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid ...@@ -183,21 +179,21 @@ func _standardBridgeFinalizedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid
var bridgeData BridgeEvent var bridgeData BridgeEvent
var eventName string var eventName string
switch any(bridgeData).(type) { switch any(bridgeData).(type) {
case bindings.L1StandardBridgeETHBridgeFinalized: case bindings.StandardBridgeETHBridgeFinalized:
eventName = "ETHBridgeFinalized" eventName = "ETHBridgeFinalized"
case bindings.L1StandardBridgeERC20BridgeFinalized: case bindings.StandardBridgeERC20BridgeFinalized:
eventName = "ERC20BridgeFinalized" eventName = "ERC20BridgeFinalized"
default: default:
panic("should not be here") panic("should not be here")
} }
processedFinalizedBridgeEvents := events.eventsBySignature[l1StandardBridgeABI.Events[eventName].ID] processedFinalizedBridgeEvents := events.eventsBySignature[StandardBridgeABI.Events[eventName].ID]
finalizedBridgeEvents := make([]StandardBridgeFinalizedEvent, len(processedFinalizedBridgeEvents)) finalizedBridgeEvents := make([]StandardBridgeFinalizedEvent, len(processedFinalizedBridgeEvents))
for i, bridgeFinalizedEvent := range processedFinalizedBridgeEvents { for i, bridgeFinalizedEvent := range processedFinalizedBridgeEvents {
log := events.eventLog[bridgeFinalizedEvent.GUID] log := events.eventLog[bridgeFinalizedEvent.GUID]
var bridgeData BridgeEvent var bridgeData BridgeEvent
err := UnpackLog(&bridgeData, log, eventName, l1StandardBridgeABI) err := UnpackLog(&bridgeData, log, eventName, StandardBridgeABI)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -256,19 +252,19 @@ func _standardBridgeFinalizedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid ...@@ -256,19 +252,19 @@ func _standardBridgeFinalizedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid
return nil, errors.New("unable to extract `_nonce` parameter from relayMessage calldata") return nil, errors.New("unable to extract `_nonce` parameter from relayMessage calldata")
} }
var erc20BridgeData *bindings.L1StandardBridgeERC20BridgeFinalized var erc20BridgeData *bindings.StandardBridgeERC20BridgeFinalized
switch any(bridgeData).(type) { switch any(bridgeData).(type) {
case bindings.L1StandardBridgeETHBridgeInitiated: case bindings.StandardBridgeETHBridgeFinalized:
ethBridgeData := any(bridgeData).(bindings.L1StandardBridgeETHBridgeFinalized) ethBridgeData := any(bridgeData).(bindings.StandardBridgeETHBridgeFinalized)
erc20BridgeData = &bindings.L1StandardBridgeERC20BridgeFinalized{ erc20BridgeData = &bindings.StandardBridgeERC20BridgeFinalized{
// Represent ETH using the hardcoded address // Represent ETH using the hardcoded address
LocalToken: EthAddress, RemoteToken: EthAddress, LocalToken: predeploys.LegacyERC20ETHAddr, RemoteToken: predeploys.LegacyERC20ETHAddr,
// Bridge data // Bridge data
From: ethBridgeData.From, To: ethBridgeData.To, Amount: ethBridgeData.Amount, ExtraData: ethBridgeData.ExtraData, From: ethBridgeData.From, To: ethBridgeData.To, Amount: ethBridgeData.Amount, ExtraData: ethBridgeData.ExtraData,
} }
case bindings.L1StandardBridgeERC20BridgeInitiated: case bindings.StandardBridgeERC20BridgeFinalized:
_temp := any(bridgeData).(bindings.L1StandardBridgeERC20BridgeFinalized) _temp := any(bridgeData).(bindings.StandardBridgeERC20BridgeFinalized)
erc20BridgeData = &_temp erc20BridgeData = &_temp
} }
......
...@@ -31,7 +31,7 @@ var ( ...@@ -31,7 +31,7 @@ var (
// AlphabetVMMetaData contains all meta data concerning the AlphabetVM contract. // AlphabetVMMetaData contains all meta data concerning the AlphabetVM contract.
var AlphabetVMMetaData = &bind.MetaData{ var AlphabetVMMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"Claim\",\"name\":\"_absolutePrestate\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contractIPreimageOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_stateData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"step\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"postState_\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", ABI: "[{\"inputs\":[{\"internalType\":\"Claim\",\"name\":\"_absolutePrestate\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contractIPreimageOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_stateData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"step\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"postState_\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
Bin: "0x60a060405234801561001057600080fd5b5060405161039838038061039883398101604081905261002f9161007a565b608081905261003c610062565b600080546001600160a01b0319166001600160a01b039290921691909117905550610093565b6460016000f36000908152600580601b83f091505090565b60006020828403121561008c57600080fd5b5051919050565b6080516102eb6100ad600039600060ad01526102eb6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80637dc0d1d01461003b578063f8e0cb9614610085575b600080fd5b60005461005b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100986100933660046101a8565b6100a6565b60405190815260200161007c565b60008060007f000000000000000000000000000000000000000000000000000000000000000087876040516100dc929190610214565b60405180910390200361010057600091506100f986880188610224565b905061011f565b61010c8688018861023d565b90925090508161011b8161028e565b9250505b8161012b8260016102c6565b6040805160208101939093528201526060016040516020818303038152906040528051906020012092505050949350505050565b60008083601f84011261017157600080fd5b50813567ffffffffffffffff81111561018957600080fd5b6020830191508360208285010111156101a157600080fd5b9250929050565b600080600080604085870312156101be57600080fd5b843567ffffffffffffffff808211156101d657600080fd5b6101e28883890161015f565b909650945060208701359150808211156101fb57600080fd5b506102088782880161015f565b95989497509550505050565b8183823760009101908152919050565b60006020828403121561023657600080fd5b5035919050565b6000806040838503121561025057600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036102bf576102bf61025f565b5060010190565b600082198211156102d9576102d961025f565b50019056fea164736f6c634300080f000a", Bin: "0x60a060405234801561001057600080fd5b50604051610a73380380610a7383398101604081905261002f91610090565b608081905260405161004090610083565b604051809103906000f08015801561005c573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b0392909216919091179055506100a9565b6106c5806103ae83390190565b6000602082840312156100a257600080fd5b5051919050565b6080516102eb6100c3600039600060ad01526102eb6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80637dc0d1d01461003b578063f8e0cb9614610085575b600080fd5b60005461005b9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100986100933660046101a8565b6100a6565b60405190815260200161007c565b60008060007f000000000000000000000000000000000000000000000000000000000000000087876040516100dc929190610214565b60405180910390200361010057600091506100f986880188610224565b905061011f565b61010c8688018861023d565b90925090508161011b8161028e565b9250505b8161012b8260016102c6565b6040805160208101939093528201526060016040516020818303038152906040528051906020012092505050949350505050565b60008083601f84011261017157600080fd5b50813567ffffffffffffffff81111561018957600080fd5b6020830191508360208285010111156101a157600080fd5b9250929050565b600080600080604085870312156101be57600080fd5b843567ffffffffffffffff808211156101d657600080fd5b6101e28883890161015f565b909650945060208701359150808211156101fb57600080fd5b506102088782880161015f565b95989497509550505050565b8183823760009101908152919050565b60006020828403121561023657600080fd5b5035919050565b6000806040838503121561025057600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036102bf576102bf61025f565b5060010190565b600082198211156102d9576102d961025f565b50019056fea164736f6c634300080f000a608060405234801561001057600080fd5b506106a5806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063e03110e11161005b578063e03110e114610111578063e159261114610139578063fe4ac08e1461014e578063fef2b4ed146101c357600080fd5b806361238bde146100825780638542cf50146100c05780639a1f5e7f146100fe575b600080fd5b6100ad610090366004610551565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6100ee6100ce366004610551565b600260209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016100b7565b6100ad61010c366004610573565b6101e3565b61012461011f366004610551565b6102b6565b604080519283526020830191909152016100b7565b61014c6101473660046105a5565b6103a7565b005b61014c61015c366004610573565b6000838152600260209081526040808320878452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558684528252808320968352958152858220939093559283529082905291902055565b6100ad6101d1366004610621565b60006020819052908152604090205481565b60006101ee856104b0565b90506101fb836008610669565b8211806102085750602083115b1561023f576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845287528083209483529386528382205581815293849052922055919050565b6000828152600260209081526040808320848452909152812054819060ff1661033f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b506000838152602081815260409091205461035b816008610669565b610366856020610669565b106103845783610377826008610669565b6103819190610681565b91505b506000938452600160209081526040808620948652939052919092205492909150565b604435600080600883018611156103c65763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82161761054b81600090815233602052604090207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b92915050565b6000806040838503121561056457600080fd5b50508035926020909101359150565b6000806000806080858703121561058957600080fd5b5050823594602084013594506040840135936060013592509050565b6000806000604084860312156105ba57600080fd5b83359250602084013567ffffffffffffffff808211156105d957600080fd5b818601915086601f8301126105ed57600080fd5b8135818111156105fc57600080fd5b87602082850101111561060e57600080fd5b6020830194508093505050509250925092565b60006020828403121561063357600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561067c5761067c61063a565b500190565b6000828210156106935761069361063a565b50039056fea164736f6c634300080f000a",
} }
// AlphabetVMABI is the input ABI used to generate the binding from. // AlphabetVMABI is the input ABI used to generate the binding from.
......
...@@ -31,7 +31,7 @@ var ( ...@@ -31,7 +31,7 @@ var (
// DisputeGameFactoryMetaData contains all meta data concerning the DisputeGameFactory contract. // DisputeGameFactoryMetaData contains all meta data concerning the DisputeGameFactory contract.
var DisputeGameFactoryMetaData = &bind.MetaData{ var DisputeGameFactoryMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"Hash\",\"name\":\"uuid\",\"type\":\"bytes32\"}],\"name\":\"GameAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"}],\"name\":\"NoImplementation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"disputeProxy\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"Claim\",\"name\":\"rootClaim\",\"type\":\"bytes32\"}],\"name\":\"DisputeGameCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"impl\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"}],\"name\":\"ImplementationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"rootClaim\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"create\",\"outputs\":[{\"internalType\":\"contractIDisputeGame\",\"name\":\"proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"gameAtIndex\",\"outputs\":[{\"internalType\":\"contractIDisputeGame\",\"name\":\"proxy_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gameCount_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"\",\"type\":\"uint8\"}],\"name\":\"gameImpls\",\"outputs\":[{\"internalType\":\"contractIDisputeGame\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"_gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"_rootClaim\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"games\",\"outputs\":[{\"internalType\":\"contractIDisputeGame\",\"name\":\"proxy_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"rootClaim\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"getGameUUID\",\"outputs\":[{\"internalType\":\"Hash\",\"name\":\"_uuid\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"internalType\":\"contractIDisputeGame\",\"name\":\"impl\",\"type\":\"address\"}],\"name\":\"setImplementation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"Hash\",\"name\":\"uuid\",\"type\":\"bytes32\"}],\"name\":\"GameAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"}],\"name\":\"NoImplementation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"disputeProxy\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"Claim\",\"name\":\"rootClaim\",\"type\":\"bytes32\"}],\"name\":\"DisputeGameCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"impl\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"}],\"name\":\"ImplementationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"rootClaim\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"create\",\"outputs\":[{\"internalType\":\"contractIDisputeGame\",\"name\":\"proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"gameAtIndex\",\"outputs\":[{\"internalType\":\"contractIDisputeGame\",\"name\":\"proxy_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gameCount_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"\",\"type\":\"uint8\"}],\"name\":\"gameImpls\",\"outputs\":[{\"internalType\":\"contractIDisputeGame\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"_gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"_rootClaim\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"games\",\"outputs\":[{\"internalType\":\"contractIDisputeGame\",\"name\":\"proxy_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timestamp_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"rootClaim\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"getGameUUID\",\"outputs\":[{\"internalType\":\"Hash\",\"name\":\"_uuid\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType\",\"type\":\"uint8\"},{\"internalType\":\"contractIDisputeGame\",\"name\":\"impl\",\"type\":\"address\"}],\"name\":\"setImplementation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
Bin: "0x60e06040523480156200001157600080fd5b506000608081905260a0819052600260c0526200002e9062000034565b620002a2565b600054610100900460ff1615808015620000555750600054600160ff909116105b8062000085575062000072306200017260201b6200097e1760201c565b15801562000085575060005460ff166001145b620000ee5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000112576000805461ff0019166101001790555b6200011c62000181565b6200012782620001e9565b80156200016e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001dd5760405162461bcd60e51b815260206004820152602b6024820152600080516020620015af83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000e5565b620001e76200023b565b565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620002975760405162461bcd60e51b815260206004820152602b6024820152600080516020620015af83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000e5565b620001e733620001e9565b60805160a05160c0516112dd620002d26000396000610605015260006105dc015260006105b301526112dd6000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063c4d66de81161005b578063c4d66de81461026d578063dfa162d314610280578063f2fde38b146102b657600080fd5b80638da5cb5b146101fd578063bb8aa1fc1461021b578063c49d52711461025a57600080fd5b80634d1975b4116100b25780634d1975b4146101d857806354fd4d50146101e0578063715018a6146101f557600080fd5b806326daafbe146100d95780633142e55e1461018b57806345583b7a146101c3575b600080fd5b6101786100e7366004610e82565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0810180517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0830180517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086018051988652968352606087529451609f0190941683209190925291905291905290565b6040519081526020015b60405180910390f35b61019e610199366004610f6b565b6102c9565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610182565b6101d66101d1366004611014565b610525565b005b606754610178565b6101e86105ac565b604051610182919061107b565b6101d661064f565b60335473ffffffffffffffffffffffffffffffffffffffff1661019e565b61022e6102293660046110cc565b610663565b6040805173ffffffffffffffffffffffffffffffffffffffff9093168352602083019190915201610182565b61022e610268366004610f6b565b6106ad565b6101d661027b3660046110e5565b61072b565b61019e61028e366004611109565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6101d66102c43660046110e5565b6108c7565b60ff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff1680610333576040517f44265d6f00000000000000000000000000000000000000000000000000000000815260ff871660048201526024015b60405180910390fd5b61039685858560405160200161034b93929190611124565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff83169061099a565b91508173ffffffffffffffffffffffffffffffffffffffff16638129fc1c6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156103e057600080fd5b505af11580156103f4573d6000803e3d6000fd5b50505050600061043b878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506100e792505050565b60008181526066602052604090205490915015610487576040517f014f6fe50000000000000000000000000000000000000000000000000000000081526004810182905260240161032a565b60004260a01b8417600083815260666020526040808220839055606780546001810182559083527f9787eeb91fe3101235e4a76063c7023ecb40f923f97916639c598592fa30d6ae0183905551919250889160ff8b169173ffffffffffffffffffffffffffffffffffffffff8816917ffad0599ff449d8d9685eadecca8cb9e00924c5fd8367c1c09469824939e1ffec9190a4505050949350505050565b61052d610ace565b60ff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917f623713f72f6e427a8044bb8b3bd6834357cf285decbaa21bcc73c1d0632c4d8491a35050565b60606105d77f0000000000000000000000000000000000000000000000000000000000000000610b4f565b6106007f0000000000000000000000000000000000000000000000000000000000000000610b4f565b6106297f0000000000000000000000000000000000000000000000000000000000000000610b4f565b60405160200161063b9392919061113e565b604051602081830303815290604052905090565b610657610ace565b6106616000610c8c565b565b60008060006067848154811061067b5761067b6111b4565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff81169560a09190911c945092505050565b60008060006106f3878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506100e792505050565b60009081526066602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c975095505050505050565b600054610100900460ff161580801561074b5750600054600160ff909116105b806107655750303b158015610765575060005460ff166001145b6107f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161032a565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561084f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610857610d03565b61086082610c8c565b80156108c357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6108cf610ace565b73ffffffffffffffffffffffffffffffffffffffff8116610972576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161032a565b61097b81610c8c565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60006002825101603f8101600a81036040518360581b8260e81b177f6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d7300001781528660601b601e8201527f5af43d3d93803e603357fd5bf300000000000000000000000000000000000000603282015285519150603f8101602087015b60208410610a5257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09093019260209182019101610a15565b517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602085900360031b1b16815260f085901b9083015282816000f0945084610abf577febfef1880000000000000000000000000000000000000000000000000000000060005260206000fd5b90910160405250909392505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610661576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161032a565b606081600003610b9257505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610bbc5780610ba681611212565b9150610bb59050600a83611279565b9150610b96565b60008167ffffffffffffffff811115610bd757610bd7610e53565b6040519080825280601f01601f191660200182016040528015610c01576020820181803683370190505b5090505b8415610c8457610c1660018361128d565b9150610c23600a866112a4565b610c2e9060306112b8565b60f81b818381518110610c4357610c436111b4565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610c7d600a86611279565b9450610c05565b949350505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610d9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161032a565b610661600054610100900460ff16610e34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161032a565b61066133610c8c565b803560ff81168114610e4e57600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060608486031215610e9757600080fd5b610ea084610e3d565b925060208401359150604084013567ffffffffffffffff80821115610ec457600080fd5b818601915086601f830112610ed857600080fd5b813581811115610eea57610eea610e53565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610f3057610f30610e53565b81604052828152896020848701011115610f4957600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60008060008060608587031215610f8157600080fd5b610f8a85610e3d565b935060208501359250604085013567ffffffffffffffff80821115610fae57600080fd5b818701915087601f830112610fc257600080fd5b813581811115610fd157600080fd5b886020828501011115610fe357600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461097b57600080fd5b6000806040838503121561102757600080fd5b61103083610e3d565b9150602083013561104081610ff2565b809150509250929050565b60005b8381101561106657818101518382015260200161104e565b83811115611075576000848401525b50505050565b602081526000825180602084015261109a81604085016020870161104b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000602082840312156110de57600080fd5b5035919050565b6000602082840312156110f757600080fd5b813561110281610ff2565b9392505050565b60006020828403121561111b57600080fd5b61110282610e3d565b838152818360208301376000910160200190815292915050565b6000845161115081846020890161104b565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161118c816001850160208a0161104b565b600192019182015283516111a781600284016020880161104b565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611243576112436111e3565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826112885761128861124a565b500490565b60008282101561129f5761129f6111e3565b500390565b6000826112b3576112b361124a565b500690565b600082198211156112cb576112cb6111e3565b50019056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", Bin: "0x60e06040523480156200001157600080fd5b506000608081905260a0819052600360c0526200002e9062000034565b620002a2565b600054610100900460ff1615808015620000555750600054600160ff909116105b8062000085575062000072306200017260201b6200097e1760201c565b15801562000085575060005460ff166001145b620000ee5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000112576000805461ff0019166101001790555b6200011c62000181565b6200012782620001e9565b80156200016e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001dd5760405162461bcd60e51b815260206004820152602b6024820152600080516020620015af83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000e5565b620001e76200023b565b565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620002975760405162461bcd60e51b815260206004820152602b6024820152600080516020620015af83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000e5565b620001e733620001e9565b60805160a05160c0516112dd620002d26000396000610605015260006105dc015260006105b301526112dd6000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063c4d66de81161005b578063c4d66de81461026d578063dfa162d314610280578063f2fde38b146102b657600080fd5b80638da5cb5b146101fd578063bb8aa1fc1461021b578063c49d52711461025a57600080fd5b80634d1975b4116100b25780634d1975b4146101d857806354fd4d50146101e0578063715018a6146101f557600080fd5b806326daafbe146100d95780633142e55e1461018b57806345583b7a146101c3575b600080fd5b6101786100e7366004610e82565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0810180517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0830180517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086018051988652968352606087529451609f0190941683209190925291905291905290565b6040519081526020015b60405180910390f35b61019e610199366004610f6b565b6102c9565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610182565b6101d66101d1366004611014565b610525565b005b606754610178565b6101e86105ac565b604051610182919061107b565b6101d661064f565b60335473ffffffffffffffffffffffffffffffffffffffff1661019e565b61022e6102293660046110cc565b610663565b6040805173ffffffffffffffffffffffffffffffffffffffff9093168352602083019190915201610182565b61022e610268366004610f6b565b6106ad565b6101d661027b3660046110e5565b61072b565b61019e61028e366004611109565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6101d66102c43660046110e5565b6108c7565b60ff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff1680610333576040517f44265d6f00000000000000000000000000000000000000000000000000000000815260ff871660048201526024015b60405180910390fd5b61039685858560405160200161034b93929190611124565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff83169061099a565b91508173ffffffffffffffffffffffffffffffffffffffff16638129fc1c6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156103e057600080fd5b505af11580156103f4573d6000803e3d6000fd5b50505050600061043b878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506100e792505050565b60008181526066602052604090205490915015610487576040517f014f6fe50000000000000000000000000000000000000000000000000000000081526004810182905260240161032a565b60004260a01b8417600083815260666020526040808220839055606780546001810182559083527f9787eeb91fe3101235e4a76063c7023ecb40f923f97916639c598592fa30d6ae0183905551919250889160ff8b169173ffffffffffffffffffffffffffffffffffffffff8816917ffad0599ff449d8d9685eadecca8cb9e00924c5fd8367c1c09469824939e1ffec9190a4505050949350505050565b61052d610ace565b60ff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917f623713f72f6e427a8044bb8b3bd6834357cf285decbaa21bcc73c1d0632c4d8491a35050565b60606105d77f0000000000000000000000000000000000000000000000000000000000000000610b4f565b6106007f0000000000000000000000000000000000000000000000000000000000000000610b4f565b6106297f0000000000000000000000000000000000000000000000000000000000000000610b4f565b60405160200161063b9392919061113e565b604051602081830303815290604052905090565b610657610ace565b6106616000610c8c565b565b60008060006067848154811061067b5761067b6111b4565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff81169560a09190911c945092505050565b60008060006106f3878787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506100e792505050565b60009081526066602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c975095505050505050565b600054610100900460ff161580801561074b5750600054600160ff909116105b806107655750303b158015610765575060005460ff166001145b6107f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161032a565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561084f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610857610d03565b61086082610c8c565b80156108c357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6108cf610ace565b73ffffffffffffffffffffffffffffffffffffffff8116610972576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161032a565b61097b81610c8c565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60006002825101603f8101600a81036040518360581b8260e81b177f6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d7300001781528660601b601e8201527f5af43d3d93803e603357fd5bf300000000000000000000000000000000000000603282015285519150603f8101602087015b60208410610a5257805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09093019260209182019101610a15565b517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602085900360031b1b16815260f085901b9083015282816000f0945084610abf577febfef1880000000000000000000000000000000000000000000000000000000060005260206000fd5b90910160405250909392505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610661576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161032a565b606081600003610b9257505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610bbc5780610ba681611212565b9150610bb59050600a83611279565b9150610b96565b60008167ffffffffffffffff811115610bd757610bd7610e53565b6040519080825280601f01601f191660200182016040528015610c01576020820181803683370190505b5090505b8415610c8457610c1660018361128d565b9150610c23600a866112a4565b610c2e9060306112b8565b60f81b818381518110610c4357610c436111b4565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610c7d600a86611279565b9450610c05565b949350505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610d9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161032a565b610661600054610100900460ff16610e34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161032a565b61066133610c8c565b803560ff81168114610e4e57600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600060608486031215610e9757600080fd5b610ea084610e3d565b925060208401359150604084013567ffffffffffffffff80821115610ec457600080fd5b818601915086601f830112610ed857600080fd5b813581811115610eea57610eea610e53565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610f3057610f30610e53565b81604052828152896020848701011115610f4957600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60008060008060608587031215610f8157600080fd5b610f8a85610e3d565b935060208501359250604085013567ffffffffffffffff80821115610fae57600080fd5b818701915087601f830112610fc257600080fd5b813581811115610fd157600080fd5b886020828501011115610fe357600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461097b57600080fd5b6000806040838503121561102757600080fd5b61103083610e3d565b9150602083013561104081610ff2565b809150509250929050565b60005b8381101561106657818101518382015260200161104e565b83811115611075576000848401525b50505050565b602081526000825180602084015261109a81604085016020870161104b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000602082840312156110de57600080fd5b5035919050565b6000602082840312156110f757600080fd5b813561110281610ff2565b9392505050565b60006020828403121561111b57600080fd5b61110282610e3d565b838152818360208301376000910160200190815292915050565b6000845161115081846020890161104b565b80830190507f2e00000000000000000000000000000000000000000000000000000000000000808252855161118c816001850160208a0161104b565b600192019182015283516111a781600284016020880161104b565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611243576112436111e3565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826112885761128861124a565b500490565b60008282101561129f5761129f6111e3565b500390565b6000826112b3576112b361124a565b500690565b600082198211156112cb576112cb6111e3565b50019056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069",
} }
// DisputeGameFactoryABI is the input ABI used to generate the binding from. // DisputeGameFactoryABI is the input ABI used to generate the binding from.
......
...@@ -37,8 +37,8 @@ type IFaultDisputeGameOutputProposal struct { ...@@ -37,8 +37,8 @@ type IFaultDisputeGameOutputProposal struct {
// FaultDisputeGameMetaData contains all meta data concerning the FaultDisputeGame contract. // FaultDisputeGameMetaData contains all meta data concerning the FaultDisputeGame contract.
var FaultDisputeGameMetaData = &bind.MetaData{ var FaultDisputeGameMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"_gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"_absolutePrestate\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_maxGameDepth\",\"type\":\"uint256\"},{\"internalType\":\"Duration\",\"name\":\"_gameDuration\",\"type\":\"uint64\"},{\"internalType\":\"contractIBigStepper\",\"name\":\"_vm\",\"type\":\"address\"},{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2oo\",\"type\":\"address\"},{\"internalType\":\"contractBlockOracle\",\"name\":\"_blockOracle\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotDefendRootClaim\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ClaimAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ClockNotExpired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ClockTimeExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GameDepthExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GameNotInProgress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidParent\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPrestate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"L1HeadTooOld\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValidStep\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"parentIndex\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"Claim\",\"name\":\"claim\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"claimant\",\"type\":\"address\"}],\"name\":\"Move\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"enumGameStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"name\":\"Resolved\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ABSOLUTE_PRESTATE\",\"outputs\":[{\"internalType\":\"Claim\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"BLOCK_ORACLE\",\"outputs\":[{\"internalType\":\"contractBlockOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GAME_DURATION\",\"outputs\":[{\"internalType\":\"Duration\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_OUTPUT_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_GAME_DEPTH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VM\",\"outputs\":[{\"internalType\":\"contractIBigStepper\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ident\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_partOffset\",\"type\":\"uint256\"}],\"name\":\"addLocalData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_parentIndex\",\"type\":\"uint256\"},{\"internalType\":\"Claim\",\"name\":\"_claim\",\"type\":\"bytes32\"}],\"name\":\"attack\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bondManager\",\"outputs\":[{\"internalType\":\"contractIBondManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"claimData\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"parentIndex\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"countered\",\"type\":\"bool\"},{\"internalType\":\"Claim\",\"name\":\"claim\",\"type\":\"bytes32\"},{\"internalType\":\"Position\",\"name\":\"position\",\"type\":\"uint128\"},{\"internalType\":\"Clock\",\"name\":\"clock\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimDataLen\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"len_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"createdAt\",\"outputs\":[{\"internalType\":\"Timestamp\",\"name\":\"createdAt_\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_parentIndex\",\"type\":\"uint256\"},{\"internalType\":\"Claim\",\"name\":\"_claim\",\"type\":\"bytes32\"}],\"name\":\"defend\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"extraData\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"extraData_\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameData\",\"outputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType_\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"rootClaim_\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"extraData_\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameStart\",\"outputs\":[{\"internalType\":\"Timestamp\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameType\",\"outputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType_\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"l1BlockNumber_\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1Head\",\"outputs\":[{\"internalType\":\"Hash\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"l2BlockNumber_\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_challengeIndex\",\"type\":\"uint256\"},{\"internalType\":\"Claim\",\"name\":\"_claim\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"_isAttack\",\"type\":\"bool\"}],\"name\":\"move\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposals\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"index\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2BlockNumber\",\"type\":\"uint128\"},{\"internalType\":\"Hash\",\"name\":\"outputRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structIFaultDisputeGame.OutputProposal\",\"name\":\"starting\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint128\",\"name\":\"index\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2BlockNumber\",\"type\":\"uint128\"},{\"internalType\":\"Hash\",\"name\":\"outputRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structIFaultDisputeGame.OutputProposal\",\"name\":\"disputed\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"enumGameStatus\",\"name\":\"status_\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rootClaim\",\"outputs\":[{\"internalType\":\"Claim\",\"name\":\"rootClaim_\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"status\",\"outputs\":[{\"internalType\":\"enumGameStatus\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_claimIndex\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_isAttack\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_stateData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_proof\",\"type\":\"bytes\"}],\"name\":\"step\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", ABI: "[{\"inputs\":[{\"internalType\":\"GameType\",\"name\":\"_gameType\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"_absolutePrestate\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_maxGameDepth\",\"type\":\"uint256\"},{\"internalType\":\"Duration\",\"name\":\"_gameDuration\",\"type\":\"uint64\"},{\"internalType\":\"contractIBigStepper\",\"name\":\"_vm\",\"type\":\"address\"},{\"internalType\":\"contractL2OutputOracle\",\"name\":\"_l2oo\",\"type\":\"address\"},{\"internalType\":\"contractBlockOracle\",\"name\":\"_blockOracle\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotDefendRootClaim\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ClaimAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ClockNotExpired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ClockTimeExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GameDepthExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GameNotInProgress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidParent\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPrestate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"L1HeadTooOld\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValidStep\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"parentIndex\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"Claim\",\"name\":\"claim\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"claimant\",\"type\":\"address\"}],\"name\":\"Move\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"enumGameStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"name\":\"Resolved\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ABSOLUTE_PRESTATE\",\"outputs\":[{\"internalType\":\"Claim\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"BLOCK_ORACLE\",\"outputs\":[{\"internalType\":\"contractBlockOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GAME_DURATION\",\"outputs\":[{\"internalType\":\"Duration\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_OUTPUT_ORACLE\",\"outputs\":[{\"internalType\":\"contractL2OutputOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_GAME_DEPTH\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VM\",\"outputs\":[{\"internalType\":\"contractIBigStepper\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ident\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_partOffset\",\"type\":\"uint256\"}],\"name\":\"addLocalData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_parentIndex\",\"type\":\"uint256\"},{\"internalType\":\"Claim\",\"name\":\"_claim\",\"type\":\"bytes32\"}],\"name\":\"attack\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bondManager\",\"outputs\":[{\"internalType\":\"contractIBondManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"claimData\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"parentIndex\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"countered\",\"type\":\"bool\"},{\"internalType\":\"Claim\",\"name\":\"claim\",\"type\":\"bytes32\"},{\"internalType\":\"Position\",\"name\":\"position\",\"type\":\"uint128\"},{\"internalType\":\"Clock\",\"name\":\"clock\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimDataLen\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"len_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"createdAt\",\"outputs\":[{\"internalType\":\"Timestamp\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_parentIndex\",\"type\":\"uint256\"},{\"internalType\":\"Claim\",\"name\":\"_claim\",\"type\":\"bytes32\"}],\"name\":\"defend\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"extraData\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"extraData_\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameData\",\"outputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType_\",\"type\":\"uint8\"},{\"internalType\":\"Claim\",\"name\":\"rootClaim_\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"extraData_\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameType\",\"outputs\":[{\"internalType\":\"GameType\",\"name\":\"gameType_\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"l1BlockNumber_\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1Head\",\"outputs\":[{\"internalType\":\"Hash\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"l2BlockNumber_\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_challengeIndex\",\"type\":\"uint256\"},{\"internalType\":\"Claim\",\"name\":\"_claim\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"_isAttack\",\"type\":\"bool\"}],\"name\":\"move\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proposals\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"index\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2BlockNumber\",\"type\":\"uint128\"},{\"internalType\":\"Hash\",\"name\":\"outputRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structIFaultDisputeGame.OutputProposal\",\"name\":\"starting\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint128\",\"name\":\"index\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"l2BlockNumber\",\"type\":\"uint128\"},{\"internalType\":\"Hash\",\"name\":\"outputRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structIFaultDisputeGame.OutputProposal\",\"name\":\"disputed\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"enumGameStatus\",\"name\":\"status_\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rootClaim\",\"outputs\":[{\"internalType\":\"Claim\",\"name\":\"rootClaim_\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"status\",\"outputs\":[{\"internalType\":\"enumGameStatus\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_claimIndex\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_isAttack\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"_stateData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_proof\",\"type\":\"bytes\"}],\"name\":\"step\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
Bin: "0x6101c06040523480156200001257600080fd5b5060405162002ef238038062002ef28339810160408190526200003591620000a1565b6000608081905260a052600660c05260ff9096166101a05260e094909452610100929092526001600160401b0316610120526001600160a01b039081166101405290811661016052166101805262000145565b6001600160a01b03811681146200009e57600080fd5b50565b600080600080600080600060e0888a031215620000bd57600080fd5b875160ff81168114620000cf57600080fd5b602089015160408a015160608b015192995090975095506001600160401b0381168114620000fc57600080fd5b60808901519094506200010f8162000088565b60a0890151909350620001228162000088565b60c0890151909250620001358162000088565b8091505092959891949750929550565b60805160a05160c05160e05161010051610120516101405161016051610180516101a051612cd66200021c6000396000818161056701526120a40152600081816103a3015261192b0152600081816105e0015281816116f8015281816117cc01526118a50152600081816105310152818161076f0152611e2301526000818161061401528181610cea015261133c01526000818161036f01528181610bf20152818161117b0152611c2701526000818161022c0152611d6101526000610f6701526000610f3e01526000610f150152612cd66000f3fe6080604052600436106101b75760003560e01c80636361506d116100ec578063c0c3a0921161008a578063c6f0308c11610064578063c6f0308c14610649578063cf09e0d0146106ad578063d8cc1a3c146106cc578063fa24f743146106ec57600080fd5b8063c0c3a092146105ce578063c31b29ce14610602578063c55cd0c71461063657600080fd5b80638b85902b116100c65780638b85902b146104df578063929312981461051f578063bbdc02db14610553578063bcef3b551461059157600080fd5b80636361506d1461049f5780638129fc1c146104b55780638980e0cc146104ca57600080fd5b8063363cc4271161015957806354fd4d501161013357806354fd4d50146103c557806355ef20e6146103e7578063609d333414610477578063632247ea1461048c57600080fd5b8063363cc427146102fe5780634778efe81461035d578063529184c91461039157600080fd5b80632810e1d6116101955780632810e1d61461025c578063298c9005146102715780633218b99d146102b157806335fef567146102eb57600080fd5b80631e27052a146101bc578063200d2ed2146101de578063266198f91461021a575b600080fd5b3480156101c857600080fd5b506101dc6101d7366004612577565b610710565b005b3480156101ea57600080fd5b506000546102049068010000000000000000900460ff1681565b60405161021191906125c8565b60405180910390f35b34801561022657600080fd5b5061024e7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610211565b34801561026857600080fd5b50610204610ad8565b34801561027d57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036040013561024e565b3480156102bd57600080fd5b506000546102d29067ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610211565b6101dc6102f9366004612577565b610efe565b34801561030a57600080fd5b50600054610338906901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610211565b34801561036957600080fd5b5061024e7f000000000000000000000000000000000000000000000000000000000000000081565b34801561039d57600080fd5b506103387f000000000000000000000000000000000000000000000000000000000000000081565b3480156103d157600080fd5b506103da610f0e565b604051610211919061267f565b3480156103f357600080fd5b5060408051606080820183526003546fffffffffffffffffffffffffffffffff808216845270010000000000000000000000000000000091829004811660208086019190915260045485870152855193840186526005548083168552929092041690820152600654928101929092526104699182565b604051610211929190612699565b34801561048357600080fd5b506103da610fb1565b6101dc61049a366004612702565b610fbf565b3480156104ab57600080fd5b5061024e60015481565b3480156104c157600080fd5b506101dc6115a4565b3480156104d657600080fd5b5060025461024e565b3480156104eb57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036020013561024e565b34801561052b57600080fd5b506103387f000000000000000000000000000000000000000000000000000000000000000081565b34801561055f57600080fd5b5060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610211565b34801561059d57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033561024e565b3480156105da57600080fd5b506103387f000000000000000000000000000000000000000000000000000000000000000081565b34801561060e57600080fd5b506102d27f000000000000000000000000000000000000000000000000000000000000000081565b6101dc610644366004612577565b611b01565b34801561065557600080fd5b50610669610664366004612737565b611b0d565b6040805163ffffffff90961686529315156020860152928401919091526fffffffffffffffffffffffffffffffff908116606084015216608082015260a001610211565b3480156106b957600080fd5b5060005467ffffffffffffffff166102d2565b3480156106d857600080fd5b506101dc6106e7366004612799565b611b7e565b3480156106f857600080fd5b506107016120a2565b60405161021193929190612823565b6000805468010000000000000000900460ff16600281111561073457610734612599565b1461076b576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fc919061284e565b9050826001036108b7576001546040517f9a1f5e7f000000000000000000000000000000000000000000000000000000008152600481018590526024810191909152602060448201526064810183905273ffffffffffffffffffffffffffffffffffffffff821690639a1f5e7f906084015b6020604051808303816000875af115801561088d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b19190612884565b50505050565b8260020361092857600480546040517f9a1f5e7f0000000000000000000000000000000000000000000000000000000081529182018590526024820152602060448201526064810183905273ffffffffffffffffffffffffffffffffffffffff821690639a1f5e7f9060840161086e565b8260030361099c576006546040517f9a1f5e7f000000000000000000000000000000000000000000000000000000008152600481018590526024810191909152602060448201526064810183905273ffffffffffffffffffffffffffffffffffffffff821690639a1f5e7f9060840161086e565b82600403610a47576003546040517f9a1f5e7f0000000000000000000000000000000000000000000000000000000081526004810185905270010000000000000000000000000000000090910460c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166024820152600860448201526064810183905273ffffffffffffffffffffffffffffffffffffffff821690639a1f5e7f9060840161086e565b82600503610ad3576040517f9a1f5e7f000000000000000000000000000000000000000000000000000000008152600481018490524660c01b6024820152600860448201526064810183905273ffffffffffffffffffffffffffffffffffffffff821690639a1f5e7f906084016020604051808303816000875af115801561088d573d6000803e3d6000fd5b505050565b60008060005468010000000000000000900460ff166002811115610afe57610afe612599565b14610b35576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600254600090610b47906001906128cc565b90506fffffffffffffffffffffffffffffffff815b67ffffffffffffffff811015610c3157600060028281548110610b8157610b816128e3565b6000918252602090912060039091020180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9093019290915060ff6401000000009091041615610bd25750610b5c565b6002810154600090610c16906fffffffffffffffffffffffffffffffff167f00000000000000000000000000000000000000000000000000000000000000006120ff565b905083811015610c2a578093508260010194505b5050610b5c565b50600060028381548110610c4757610c476128e3565b600091825260208220600390910201805490925063ffffffff90811691908214610cb15760028281548110610c7e57610c7e6128e3565b906000526020600020906003020160020160109054906101000a90046fffffffffffffffffffffffffffffffff16610cdd565b600283015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff165b9050677fffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000060011c16610d2167ffffffffffffffff8316426128cc565b610d3d836fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16610d519190612912565b11610d88576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600283810154610e2a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b610e349190612959565b67ffffffffffffffff16158015610e5b57506fffffffffffffffffffffffffffffffff8414155b15610e695760029550610e6e565b600195505b600080548791907fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1668010000000000000000836002811115610eb357610eb3612599565b021790556002811115610ec857610ec8612599565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a2505050505090565b905090565b610f0a82826000610fbf565b5050565b6060610f397f00000000000000000000000000000000000000000000000000000000000000006121b4565b610f627f00000000000000000000000000000000000000000000000000000000000000006121b4565b610f8b7f00000000000000000000000000000000000000000000000000000000000000006121b4565b604051602001610f9d93929190612980565b604051602081830303815290604052905090565b6060610ef9602060406122f1565b6000805468010000000000000000900460ff166002811115610fe357610fe3612599565b1461101a576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82158015611026575080155b1561105d576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110611072576110726128e3565b60009182526020918290206040805160a0810182526003909302909101805463ffffffff8116845260ff64010000000090910416151593830193909352600180840154918301919091526002928301546fffffffffffffffffffffffffffffffff8082166060850152700100000000000000000000000000000000909104166080830152825491935091908690811061110d5761110d6128e3565b6000918252602082206003909102018054921515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff909316929092179091556060820151611177906fffffffffffffffffffffffffffffffff1684151760011b90565b90507f0000000000000000000000000000000000000000000000000000000000000000611236826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff161115611278576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160009063ffffffff908116146112d8576002836000015163ffffffff16815481106112a7576112a76128e3565b906000526020600020906003020160020160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b608083015160009067ffffffffffffffff1667ffffffffffffffff1642611311846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff166113259190612912565b61132f91906128cc565b9050677fffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000060011c1667ffffffffffffffff821611156113a2576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000604082901b4217905060006113c3888660009182526020526040902090565b60008181526007602052604090205490915060ff161561140f576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260076020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155815160a08101835263ffffffff808f1682529381018581528184018e81526fffffffffffffffffffffffffffffffff808d16606085019081528a8216608086019081526002805497880181558a52945160039096027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace8101805495511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000909616979099169690961793909317909655517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf8401555190518416700100000000000000000000000000000000029316929092177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0909201919091555133918a918c917f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be91a4505050505050505050565b600080547fffffffffffffffffffffffffffffffffffffffffffffff000000000000000000164267ffffffffffffffff161781556040805160a08101825263ffffffff815260208101929092526002919081016116297ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90033590565b815260016020820152604001426fffffffffffffffffffffffffffffffff9081169091528254600181810185556000948552602080862085516003909402018054918601511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000090921663ffffffff909416939093171782556040840151908201556060830151608090930151821670010000000000000000000000000000000002929091169190911760029091015573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016637f00642061175260207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c9003013590565b6040518263ffffffff1660e01b815260040161177091815260200190565b602060405180830381865afa15801561178d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b19190612884565b9050600073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663a25ae5576117fc6001856128cc565b6040518263ffffffff1660e01b815260040161181a91815260200190565b606060405180830381865afa158015611837573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185b9190612a45565b6040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810184905290915060009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa1580156118ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119109190612a45565b9050600073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166399d548aa367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003604001356040518263ffffffff1660e01b815260040161199c91815260200190565b6040805180830381865afa1580156119b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119dc9190612ad1565b905081602001516fffffffffffffffffffffffffffffffff16816020015167ffffffffffffffff1611611a3b576040517f13809ba500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160a081018252908190810180611a566001896128cc565b6fffffffffffffffffffffffffffffffff9081168252604088810151821660208085019190915298519281019290925291835280516060810182529782168852858101518216888801529451878601529085019590955280518051818601519087167001000000000000000000000000000000009188168202176003559084015160045590840151805194810151948616949095160292909217600555919091015160065551600155565b610f0a82826001610fbf565b60028181548110611b1d57600080fd5b600091825260209091206003909102018054600182015460029092015463ffffffff8216935064010000000090910460ff1691906fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041685565b6000805468010000000000000000900460ff166002811115611ba257611ba2612599565b14611bd9576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110611bee57611bee6128e3565b6000918252602082206003919091020160028101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050611c4d7f00000000000000000000000000000000000000000000000000000000000000006001612912565b611ce9826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1614611d2a576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808915611db057611d4e836fffffffffffffffffffffffffffffffff16612388565b67ffffffffffffffff16600003611d87577f00000000000000000000000000000000000000000000000000000000000000009150611da9565b611da2611d95600186612b58565b865463ffffffff1661242e565b6001015491505b5083611dca565b84600101549150611dc7846001611d959190612b89565b90505b818989604051611ddb929190612bbd565b604051809103902014611e1a576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081600101547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f8e0cb968c8c8c8c6040518563ffffffff1660e01b8152600401611e809493929190612c16565b6020604051808303816000875af1158015611e9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec39190612884565b600284810154929091149250600091611f6e906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b61200a886fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6120149190612c48565b61201e9190612959565b67ffffffffffffffff161590508115158103612066576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505084547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000001790945550505050505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560606120f8610fb1565b9050909192565b60008061218c847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1690508083036001841b600180831b0386831b17039250505092915050565b6060816000036121f757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115612221578061220b81612c69565b915061221a9050600a83612ca1565b91506121fb565b60008167ffffffffffffffff81111561223c5761223c6129f6565b6040519080825280601f01601f191660200182016040528015612266576020820181803683370190505b5090505b84156122e95761227b6001836128cc565b9150612288600a86612cb5565b612293906030612912565b60f81b8183815181106122a8576122a86128e3565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506122e2600a86612ca1565b945061226a565b949350505050565b6060600061232884367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003612912565b90508267ffffffffffffffff1667ffffffffffffffff81111561234d5761234d6129f6565b6040519080825280601f01601f191660200182016040528015612377576020820181803683370190505b509150828160208401375092915050565b600080612415837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600167ffffffffffffffff919091161b90920392915050565b60008061244c846fffffffffffffffffffffffffffffffff166124cb565b905060028381548110612461576124616128e3565b906000526020600020906003020191505b60028201546fffffffffffffffffffffffffffffffff8281169116146124c457815460028054909163ffffffff169081106124af576124af6128e3565b90600052602060002090600302019150612472565b5092915050565b6000811960018301168161255f827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169390931c8015179392505050565b6000806040838503121561258a57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310612603577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60005b8381101561262457818101518382015260200161260c565b838111156108b15750506000910152565b6000815180845261264d816020860160208601612609565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006126926020830184612635565b9392505050565b82516fffffffffffffffffffffffffffffffff90811682526020808501518216818401526040808601518185015284518316606085015290840151909116608083015282015160a082015260c08101612692565b803580151581146126fd57600080fd5b919050565b60008060006060848603121561271757600080fd5b833592506020840135915061272e604085016126ed565b90509250925092565b60006020828403121561274957600080fd5b5035919050565b60008083601f84011261276257600080fd5b50813567ffffffffffffffff81111561277a57600080fd5b60208301915083602082850101111561279257600080fd5b9250929050565b600080600080600080608087890312156127b257600080fd5b863595506127c2602088016126ed565b9450604087013567ffffffffffffffff808211156127df57600080fd5b6127eb8a838b01612750565b9096509450606089013591508082111561280457600080fd5b5061281189828a01612750565b979a9699509497509295939492505050565b60ff841681528260208201526060604082015260006128456060830184612635565b95945050505050565b60006020828403121561286057600080fd5b815173ffffffffffffffffffffffffffffffffffffffff8116811461269257600080fd5b60006020828403121561289657600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156128de576128de61289d565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082198211156129255761292561289d565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff808416806129745761297461292a565b92169190910692915050565b60008451612992818460208901612609565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516129ce816001850160208a01612609565b600192019182015283516129e9816002840160208801612609565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b80516fffffffffffffffffffffffffffffffff811681146126fd57600080fd5b600060608284031215612a5757600080fd5b6040516060810181811067ffffffffffffffff82111715612aa1577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405282518152612ab460208401612a25565b6020820152612ac560408401612a25565b60408201529392505050565b600060408284031215612ae357600080fd5b6040516040810167ffffffffffffffff8282108183111715612b2e577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8160405284518352602085015191508082168214612b4b57600080fd5b5060208201529392505050565b60006fffffffffffffffffffffffffffffffff83811690831681811015612b8157612b8161289d565b039392505050565b60006fffffffffffffffffffffffffffffffff808316818516808303821115612bb457612bb461289d565b01949350505050565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b604081526000612c2a604083018688612bcd565b8281036020840152612c3d818587612bcd565b979650505050505050565b600067ffffffffffffffff83811690831681811015612b8157612b8161289d565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612c9a57612c9a61289d565b5060010190565b600082612cb057612cb061292a565b500490565b600082612cc457612cc461292a565b50069056fea164736f6c634300080f000a", Bin: "0x6101c06040523480156200001257600080fd5b5060405162002cb338038062002cb38339810160408190526200003591620000a1565b6000608081905260a052600760c05260ff9096166101a05260e094909452610100929092526001600160401b0316610120526001600160a01b039081166101405290811661016052166101805262000145565b6001600160a01b03811681146200009e57600080fd5b50565b600080600080600080600060e0888a031215620000bd57600080fd5b875160ff81168114620000cf57600080fd5b602089015160408a015160608b015192995090975095506001600160401b0381168114620000fc57600080fd5b60808901519094506200010f8162000088565b60a0890151909350620001228162000088565b60c0890151909250620001358162000088565b8091505092959891949750929550565b60805160a05160c05160e05161010051610120516101405161016051610180516101a051612a976200021c600039600081816105220152611e5d01526000818161035e01526116e701526000818161059b015281816114b40152818161158801526116610152600081816104ec015281816107450152611bdc0152600081816105cf01528181610ab7015261109801526000818161032a015281816109bf01528181610ed701526119e30152600081816102210152611b3f01526000610d3401526000610d0b01526000610ce20152612a976000f3fe6080604052600436106101ac5760003560e01c80636361506d116100ec578063c0c3a0921161008a578063c6f0308c11610064578063c6f0308c1461061d578063cf09e0d014610681578063d8cc1a3c146106a2578063fa24f743146106c257600080fd5b8063c0c3a09214610589578063c31b29ce146105bd578063c55cd0c71461060a57600080fd5b80638b85902b116100c65780638b85902b1461049a57806392931298146104da578063bbdc02db1461050e578063bcef3b551461054c57600080fd5b80636361506d1461045a5780638129fc1c146104705780638980e0cc1461048557600080fd5b8063363cc4271161015957806354fd4d501161013357806354fd4d501461038057806355ef20e6146103a2578063609d333414610432578063632247ea1461044757600080fd5b8063363cc427146102b95780634778efe814610318578063529184c91461034c57600080fd5b80632810e1d61161018a5780632810e1d614610251578063298c90051461026657806335fef567146102a657600080fd5b80631e27052a146101b1578063200d2ed2146101d3578063266198f91461020f575b600080fd5b3480156101bd57600080fd5b506101d16101cc366004612338565b6106e6565b005b3480156101df57600080fd5b506000546101f99068010000000000000000900460ff1681565b6040516102069190612389565b60405180910390f35b34801561021b57600080fd5b506102437f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610206565b34801561025d57600080fd5b506101f96108a5565b34801561027257600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360400135610243565b6101d16102b4366004612338565b610ccb565b3480156102c557600080fd5b506000546102f3906901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610206565b34801561032457600080fd5b506102437f000000000000000000000000000000000000000000000000000000000000000081565b34801561035857600080fd5b506102f37f000000000000000000000000000000000000000000000000000000000000000081565b34801561038c57600080fd5b50610395610cdb565b6040516102069190612440565b3480156103ae57600080fd5b5060408051606080820183526003546fffffffffffffffffffffffffffffffff808216845270010000000000000000000000000000000091829004811660208086019190915260045485870152855193840186526005548083168552929092041690820152600654928101929092526104249182565b60405161020692919061245a565b34801561043e57600080fd5b50610395610d7e565b6101d16104553660046124c3565b610d8c565b34801561046657600080fd5b5061024360015481565b34801561047c57600080fd5b506101d1611360565b34801561049157600080fd5b50600254610243565b3480156104a657600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360200135610243565b3480156104e657600080fd5b506102f37f000000000000000000000000000000000000000000000000000000000000000081565b34801561051a57600080fd5b5060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610206565b34801561055857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335610243565b34801561059557600080fd5b506102f37f000000000000000000000000000000000000000000000000000000000000000081565b3480156105c957600080fd5b506105f17f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff9091168152602001610206565b6101d1610618366004612338565b6118bd565b34801561062957600080fd5b5061063d6106383660046124f8565b6118c9565b6040805163ffffffff90961686529315156020860152928401919091526fffffffffffffffffffffffffffffffff908116606084015216608082015260a001610206565b34801561068d57600080fd5b506000546105f19067ffffffffffffffff1681565b3480156106ae57600080fd5b506101d16106bd36600461255a565b61193a565b3480156106ce57600080fd5b506106d7611e5b565b604051610206939291906125e4565b6000805468010000000000000000900460ff16600281111561070a5761070a61235a565b14610741576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d2919061260f565b7f9a1f5e7f00000000000000000000000000000000000000000000000000000000601c8190526020859052909150600084600181146108395760028114610843576003811461084d576004811461085757600581146108675763ff137e656000526004601cfd5b600154915061086e565b600454915061086e565b600654915061086e565b60035460801c60c01b915061086e565b4660c01b91505b50604052600160038511811b6005031b60605260808390526000806084601c82865af161089f573d6000803e3d6000fd5b50505050565b60008060005468010000000000000000900460ff1660028111156108cb576108cb61235a565b14610902576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460009061091490600190612674565b90506fffffffffffffffffffffffffffffffff815b67ffffffffffffffff8110156109fe5760006002828154811061094e5761094e61268b565b6000918252602090912060039091020180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9093019290915060ff640100000000909104161561099f5750610929565b60028101546000906109e3906fffffffffffffffffffffffffffffffff167f0000000000000000000000000000000000000000000000000000000000000000611eb8565b9050838110156109f7578093508260010194505b5050610929565b50600060028381548110610a1457610a1461268b565b600091825260208220600390910201805490925063ffffffff90811691908214610a7e5760028281548110610a4b57610a4b61268b565b906000526020600020906003020160020160109054906101000a90046fffffffffffffffffffffffffffffffff16610aaa565b600283015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff165b9050677fffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000060011c16610aee67ffffffffffffffff831642612674565b610b0a836fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16610b1e91906126ba565b11610b55576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600283810154610bf7906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b610c019190612701565b67ffffffffffffffff16158015610c2857506fffffffffffffffffffffffffffffffff8414155b15610c365760029550610c3b565b600195505b600080548791907fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1668010000000000000000836002811115610c8057610c8061235a565b021790556002811115610c9557610c9561235a565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a2505050505090565b905090565b610cd782826000610d8c565b5050565b6060610d067f0000000000000000000000000000000000000000000000000000000000000000611f6d565b610d2f7f0000000000000000000000000000000000000000000000000000000000000000611f6d565b610d587f0000000000000000000000000000000000000000000000000000000000000000611f6d565b604051602001610d6a93929190612728565b604051602081830303815290604052905090565b6060610cc6602060406120aa565b6000805468010000000000000000900460ff166002811115610db057610db061235a565b14610de7576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82158015610df3575080155b15610e2a576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110610e3f57610e3f61268b565b600091825260208083206040805160a081018252600394909402909101805463ffffffff808216865264010000000090910460ff16151593850193909352600181015491840191909152600201546fffffffffffffffffffffffffffffffff80821660608501819052700100000000000000000000000000000000909204166080840152919350610ed39190859061214116565b90507f0000000000000000000000000000000000000000000000000000000000000000610f92826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff161115610fd4576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160009063ffffffff90811614611034576002836000015163ffffffff16815481106110035761100361268b565b906000526020600020906003020160020160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b608083015160009067ffffffffffffffff1667ffffffffffffffff164261106d846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff1661108191906126ba565b61108b9190612674565b9050677fffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000060011c1667ffffffffffffffff821611156110fe576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000604082901b42179050600061111f888660009182526020526040902090565b60008181526007602052604090205490915060ff161561116b576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260076020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155815160a08101835263ffffffff808f1682529381018581529281018d81526fffffffffffffffffffffffffffffffff808c16606084019081528982166080850190815260028054808801825599819052945160039099027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace8101805498511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009099169a909916999099179690961790965590517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf8701559351925184167001000000000000000000000000000000000292909316919091177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad09093019290925580548b9081106112e3576112e361268b565b6000918252602082206003909102018054921515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff9093169290921790915560405133918a918c917f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be91a4505050505050505050565b600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161781556040805160a08101825263ffffffff815260208101929092526002919081016113e57ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90033590565b815260016020820152604001426fffffffffffffffffffffffffffffffff9081169091528254600181810185556000948552602080862085516003909402018054918601511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000090921663ffffffff909416939093171782556040840151908201556060830151608090930151821670010000000000000000000000000000000002929091169190911760029091015573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016637f00642061150e60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c9003013590565b6040518263ffffffff1660e01b815260040161152c91815260200190565b602060405180830381865afa158015611549573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156d919061279e565b9050600073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663a25ae5576115b8600185612674565b6040518263ffffffff1660e01b81526004016115d691815260200190565b606060405180830381865afa1580156115f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116179190612806565b6040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810184905290915060009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa1580156116a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116cc9190612806565b9050600073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166399d548aa367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003604001356040518263ffffffff1660e01b815260040161175891815260200190565b6040805180830381865afa158015611774573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117989190612892565b905081602001516fffffffffffffffffffffffffffffffff16816020015167ffffffffffffffff16116117f7576040517f13809ba500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160a081018252908190810180611812600189612674565b6fffffffffffffffffffffffffffffffff9081168252604088810151821660208085019190915298519281019290925291835280516060810182529782168852858101518216888801529451878601529085019590955280518051818601519087167001000000000000000000000000000000009188168202176003559084015160045590840151805194810151948616949095160292909217600555919091015160065551600155565b610cd782826001610d8c565b600281815481106118d957600080fd5b600091825260209091206003909102018054600182015460029092015463ffffffff8216935064010000000090910460ff1691906fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041685565b6000805468010000000000000000900460ff16600281111561195e5761195e61235a565b14611995576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600287815481106119aa576119aa61268b565b6000918252602082206003919091020160028101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050611a097f000000000000000000000000000000000000000000000000000000000000000060016126ba565b611aa5826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1614611ae6576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808915611b6957611b0a836fffffffffffffffffffffffffffffffff16612149565b67ffffffffffffffff1615611b3d57611b34611b27600186612919565b865463ffffffff166121ef565b60010154611b5f565b7f00000000000000000000000000000000000000000000000000000000000000005b9150849050611b83565b84600101549150611b80846001611b27919061294a565b90505b818989604051611b9492919061297e565b604051809103902014611bd3576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081600101547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f8e0cb968c8c8c8c6040518563ffffffff1660e01b8152600401611c3994939291906129d7565b6020604051808303816000875af1158015611c58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c7c919061279e565b600284810154929091149250600091611d27906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b611dc3886fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b611dcd9190612a09565b611dd79190612701565b67ffffffffffffffff161590508115158103611e1f576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505084547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000001790945550505050505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003356060611eb1610d7e565b9050909192565b600080611f45847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1690508083036001841b600180831b0386831b17039250505092915050565b606081600003611fb057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611fda5780611fc481612a2a565b9150611fd39050600a83612a62565b9150611fb4565b60008167ffffffffffffffff811115611ff557611ff56127b7565b6040519080825280601f01601f19166020018201604052801561201f576020820181803683370190505b5090505b84156120a257612034600183612674565b9150612041600a86612a76565b61204c9060306126ba565b60f81b8183815181106120615761206161268b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061209b600a86612a62565b9450612023565b949350505050565b606060006120e184367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036126ba565b90508267ffffffffffffffff1667ffffffffffffffff811115612106576121066127b7565b6040519080825280601f01601f191660200182016040528015612130576020820181803683370190505b509150828160208401375092915050565b151760011b90565b6000806121d6837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600167ffffffffffffffff919091161b90920392915050565b60008061220d846fffffffffffffffffffffffffffffffff1661228c565b9050600283815481106122225761222261268b565b906000526020600020906003020191505b60028201546fffffffffffffffffffffffffffffffff82811691161461228557815460028054909163ffffffff169081106122705761227061268b565b90600052602060002090600302019150612233565b5092915050565b60008119600183011681612320827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169390931c8015179392505050565b6000806040838503121561234b57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600383106123c4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60005b838110156123e55781810151838201526020016123cd565b8381111561089f5750506000910152565b6000815180845261240e8160208601602086016123ca565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061245360208301846123f6565b9392505050565b82516fffffffffffffffffffffffffffffffff90811682526020808501518216818401526040808601518185015284518316606085015290840151909116608083015282015160a082015260c08101612453565b803580151581146124be57600080fd5b919050565b6000806000606084860312156124d857600080fd5b83359250602084013591506124ef604085016124ae565b90509250925092565b60006020828403121561250a57600080fd5b5035919050565b60008083601f84011261252357600080fd5b50813567ffffffffffffffff81111561253b57600080fd5b60208301915083602082850101111561255357600080fd5b9250929050565b6000806000806000806080878903121561257357600080fd5b86359550612583602088016124ae565b9450604087013567ffffffffffffffff808211156125a057600080fd5b6125ac8a838b01612511565b909650945060608901359150808211156125c557600080fd5b506125d289828a01612511565b979a9699509497509295939492505050565b60ff8416815282602082015260606040820152600061260660608301846123f6565b95945050505050565b60006020828403121561262157600080fd5b815173ffffffffffffffffffffffffffffffffffffffff8116811461245357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561268657612686612645565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082198211156126cd576126cd612645565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff8084168061271c5761271c6126d2565b92169190910692915050565b6000845161273a8184602089016123ca565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612776816001850160208a016123ca565b600192019182015283516127918160028401602088016123ca565b0160020195945050505050565b6000602082840312156127b057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b80516fffffffffffffffffffffffffffffffff811681146124be57600080fd5b60006060828403121561281857600080fd5b6040516060810181811067ffffffffffffffff82111715612862577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405282518152612875602084016127e6565b6020820152612886604084016127e6565b60408201529392505050565b6000604082840312156128a457600080fd5b6040516040810167ffffffffffffffff82821081831117156128ef577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b816040528451835260208501519150808216821461290c57600080fd5b5060208201529392505050565b60006fffffffffffffffffffffffffffffffff8381169083168181101561294257612942612645565b039392505050565b60006fffffffffffffffffffffffffffffffff80831681851680830382111561297557612975612645565b01949350505050565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6040815260006129eb60408301868861298e565b82810360208401526129fe81858761298e565b979650505050505050565b600067ffffffffffffffff8381169083168181101561294257612942612645565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612a5b57612a5b612645565b5060010190565b600082612a7157612a716126d2565b500490565b600082612a8557612a856126d2565b50069056fea164736f6c634300080f000a",
} }
// FaultDisputeGameABI is the input ABI used to generate the binding from. // FaultDisputeGameABI is the input ABI used to generate the binding from.
...@@ -518,7 +518,7 @@ func (_FaultDisputeGame *FaultDisputeGameCallerSession) ClaimDataLen() (*big.Int ...@@ -518,7 +518,7 @@ func (_FaultDisputeGame *FaultDisputeGameCallerSession) ClaimDataLen() (*big.Int
// CreatedAt is a free data retrieval call binding the contract method 0xcf09e0d0. // CreatedAt is a free data retrieval call binding the contract method 0xcf09e0d0.
// //
// Solidity: function createdAt() view returns(uint64 createdAt_) // Solidity: function createdAt() view returns(uint64)
func (_FaultDisputeGame *FaultDisputeGameCaller) CreatedAt(opts *bind.CallOpts) (uint64, error) { func (_FaultDisputeGame *FaultDisputeGameCaller) CreatedAt(opts *bind.CallOpts) (uint64, error) {
var out []interface{} var out []interface{}
err := _FaultDisputeGame.contract.Call(opts, &out, "createdAt") err := _FaultDisputeGame.contract.Call(opts, &out, "createdAt")
...@@ -535,14 +535,14 @@ func (_FaultDisputeGame *FaultDisputeGameCaller) CreatedAt(opts *bind.CallOpts) ...@@ -535,14 +535,14 @@ func (_FaultDisputeGame *FaultDisputeGameCaller) CreatedAt(opts *bind.CallOpts)
// CreatedAt is a free data retrieval call binding the contract method 0xcf09e0d0. // CreatedAt is a free data retrieval call binding the contract method 0xcf09e0d0.
// //
// Solidity: function createdAt() view returns(uint64 createdAt_) // Solidity: function createdAt() view returns(uint64)
func (_FaultDisputeGame *FaultDisputeGameSession) CreatedAt() (uint64, error) { func (_FaultDisputeGame *FaultDisputeGameSession) CreatedAt() (uint64, error) {
return _FaultDisputeGame.Contract.CreatedAt(&_FaultDisputeGame.CallOpts) return _FaultDisputeGame.Contract.CreatedAt(&_FaultDisputeGame.CallOpts)
} }
// CreatedAt is a free data retrieval call binding the contract method 0xcf09e0d0. // CreatedAt is a free data retrieval call binding the contract method 0xcf09e0d0.
// //
// Solidity: function createdAt() view returns(uint64 createdAt_) // Solidity: function createdAt() view returns(uint64)
func (_FaultDisputeGame *FaultDisputeGameCallerSession) CreatedAt() (uint64, error) { func (_FaultDisputeGame *FaultDisputeGameCallerSession) CreatedAt() (uint64, error) {
return _FaultDisputeGame.Contract.CreatedAt(&_FaultDisputeGame.CallOpts) return _FaultDisputeGame.Contract.CreatedAt(&_FaultDisputeGame.CallOpts)
} }
...@@ -628,37 +628,6 @@ func (_FaultDisputeGame *FaultDisputeGameCallerSession) GameData() (struct { ...@@ -628,37 +628,6 @@ func (_FaultDisputeGame *FaultDisputeGameCallerSession) GameData() (struct {
return _FaultDisputeGame.Contract.GameData(&_FaultDisputeGame.CallOpts) return _FaultDisputeGame.Contract.GameData(&_FaultDisputeGame.CallOpts)
} }
// GameStart is a free data retrieval call binding the contract method 0x3218b99d.
//
// Solidity: function gameStart() view returns(uint64)
func (_FaultDisputeGame *FaultDisputeGameCaller) GameStart(opts *bind.CallOpts) (uint64, error) {
var out []interface{}
err := _FaultDisputeGame.contract.Call(opts, &out, "gameStart")
if err != nil {
return *new(uint64), err
}
out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64)
return out0, err
}
// GameStart is a free data retrieval call binding the contract method 0x3218b99d.
//
// Solidity: function gameStart() view returns(uint64)
func (_FaultDisputeGame *FaultDisputeGameSession) GameStart() (uint64, error) {
return _FaultDisputeGame.Contract.GameStart(&_FaultDisputeGame.CallOpts)
}
// GameStart is a free data retrieval call binding the contract method 0x3218b99d.
//
// Solidity: function gameStart() view returns(uint64)
func (_FaultDisputeGame *FaultDisputeGameCallerSession) GameStart() (uint64, error) {
return _FaultDisputeGame.Contract.GameStart(&_FaultDisputeGame.CallOpts)
}
// GameType is a free data retrieval call binding the contract method 0xbbdc02db. // GameType is a free data retrieval call binding the contract method 0xbbdc02db.
// //
// Solidity: function gameType() view returns(uint8 gameType_) // Solidity: function gameType() view returns(uint8 gameType_)
......
...@@ -9,11 +9,11 @@ import ( ...@@ -9,11 +9,11 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "github.com/ethereum-optimism/optimism/op-bindings/solc"
) )
const FaultDisputeGameStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"gameStart\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_userDefinedValueType(Timestamp)1017\"},{\"astId\":1001,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"status\",\"offset\":8,\"slot\":\"0\",\"type\":\"t_enum(GameStatus)1008\"},{\"astId\":1002,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"bondManager\",\"offset\":9,\"slot\":\"0\",\"type\":\"t_contract(IBondManager)1007\"},{\"astId\":1003,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"l1Head\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_userDefinedValueType(Hash)1015\"},{\"astId\":1004,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"claimData\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_array(t_struct(ClaimData)1009_storage)dyn_storage\"},{\"astId\":1005,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"proposals\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_struct(OutputProposals)1011_storage\"},{\"astId\":1006,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"claims\",\"offset\":0,\"slot\":\"7\",\"type\":\"t_mapping(t_userDefinedValueType(ClaimHash)1013,t_bool)\"}],\"types\":{\"t_array(t_struct(ClaimData)1009_storage)dyn_storage\":{\"encoding\":\"dynamic_array\",\"label\":\"struct IFaultDisputeGame.ClaimData[]\",\"numberOfBytes\":\"32\",\"base\":\"t_struct(ClaimData)1009_storage\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_contract(IBondManager)1007\":{\"encoding\":\"inplace\",\"label\":\"contract IBondManager\",\"numberOfBytes\":\"20\"},\"t_enum(GameStatus)1008\":{\"encoding\":\"inplace\",\"label\":\"enum GameStatus\",\"numberOfBytes\":\"1\"},\"t_mapping(t_userDefinedValueType(ClaimHash)1013,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(ClaimHash =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_userDefinedValueType(ClaimHash)1013\",\"value\":\"t_bool\"},\"t_struct(ClaimData)1009_storage\":{\"encoding\":\"inplace\",\"label\":\"struct IFaultDisputeGame.ClaimData\",\"numberOfBytes\":\"96\"},\"t_struct(OutputProposal)1010_storage\":{\"encoding\":\"inplace\",\"label\":\"struct IFaultDisputeGame.OutputProposal\",\"numberOfBytes\":\"64\"},\"t_struct(OutputProposals)1011_storage\":{\"encoding\":\"inplace\",\"label\":\"struct IFaultDisputeGame.OutputProposals\",\"numberOfBytes\":\"128\"},\"t_uint128\":{\"encoding\":\"inplace\",\"label\":\"uint128\",\"numberOfBytes\":\"16\"},\"t_uint32\":{\"encoding\":\"inplace\",\"label\":\"uint32\",\"numberOfBytes\":\"4\"},\"t_userDefinedValueType(Claim)1012\":{\"encoding\":\"inplace\",\"label\":\"Claim\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(ClaimHash)1013\":{\"encoding\":\"inplace\",\"label\":\"ClaimHash\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(Clock)1014\":{\"encoding\":\"inplace\",\"label\":\"Clock\",\"numberOfBytes\":\"16\"},\"t_userDefinedValueType(Hash)1015\":{\"encoding\":\"inplace\",\"label\":\"Hash\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(Position)1016\":{\"encoding\":\"inplace\",\"label\":\"Position\",\"numberOfBytes\":\"16\"},\"t_userDefinedValueType(Timestamp)1017\":{\"encoding\":\"inplace\",\"label\":\"Timestamp\",\"numberOfBytes\":\"8\"}}}" const FaultDisputeGameStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"createdAt\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_userDefinedValueType(Timestamp)1017\"},{\"astId\":1001,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"status\",\"offset\":8,\"slot\":\"0\",\"type\":\"t_enum(GameStatus)1008\"},{\"astId\":1002,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"bondManager\",\"offset\":9,\"slot\":\"0\",\"type\":\"t_contract(IBondManager)1007\"},{\"astId\":1003,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"l1Head\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_userDefinedValueType(Hash)1015\"},{\"astId\":1004,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"claimData\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_array(t_struct(ClaimData)1009_storage)dyn_storage\"},{\"astId\":1005,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"proposals\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_struct(OutputProposals)1011_storage\"},{\"astId\":1006,\"contract\":\"src/dispute/FaultDisputeGame.sol:FaultDisputeGame\",\"label\":\"claims\",\"offset\":0,\"slot\":\"7\",\"type\":\"t_mapping(t_userDefinedValueType(ClaimHash)1013,t_bool)\"}],\"types\":{\"t_array(t_struct(ClaimData)1009_storage)dyn_storage\":{\"encoding\":\"dynamic_array\",\"label\":\"struct IFaultDisputeGame.ClaimData[]\",\"numberOfBytes\":\"32\",\"base\":\"t_struct(ClaimData)1009_storage\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_contract(IBondManager)1007\":{\"encoding\":\"inplace\",\"label\":\"contract IBondManager\",\"numberOfBytes\":\"20\"},\"t_enum(GameStatus)1008\":{\"encoding\":\"inplace\",\"label\":\"enum GameStatus\",\"numberOfBytes\":\"1\"},\"t_mapping(t_userDefinedValueType(ClaimHash)1013,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(ClaimHash =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_userDefinedValueType(ClaimHash)1013\",\"value\":\"t_bool\"},\"t_struct(ClaimData)1009_storage\":{\"encoding\":\"inplace\",\"label\":\"struct IFaultDisputeGame.ClaimData\",\"numberOfBytes\":\"96\"},\"t_struct(OutputProposal)1010_storage\":{\"encoding\":\"inplace\",\"label\":\"struct IFaultDisputeGame.OutputProposal\",\"numberOfBytes\":\"64\"},\"t_struct(OutputProposals)1011_storage\":{\"encoding\":\"inplace\",\"label\":\"struct IFaultDisputeGame.OutputProposals\",\"numberOfBytes\":\"128\"},\"t_uint128\":{\"encoding\":\"inplace\",\"label\":\"uint128\",\"numberOfBytes\":\"16\"},\"t_uint32\":{\"encoding\":\"inplace\",\"label\":\"uint32\",\"numberOfBytes\":\"4\"},\"t_userDefinedValueType(Claim)1012\":{\"encoding\":\"inplace\",\"label\":\"Claim\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(ClaimHash)1013\":{\"encoding\":\"inplace\",\"label\":\"ClaimHash\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(Clock)1014\":{\"encoding\":\"inplace\",\"label\":\"Clock\",\"numberOfBytes\":\"16\"},\"t_userDefinedValueType(Hash)1015\":{\"encoding\":\"inplace\",\"label\":\"Hash\",\"numberOfBytes\":\"32\"},\"t_userDefinedValueType(Position)1016\":{\"encoding\":\"inplace\",\"label\":\"Position\",\"numberOfBytes\":\"16\"},\"t_userDefinedValueType(Timestamp)1017\":{\"encoding\":\"inplace\",\"label\":\"Timestamp\",\"numberOfBytes\":\"8\"}}}"
var FaultDisputeGameStorageLayout = new(solc.StorageLayout) var FaultDisputeGameStorageLayout = new(solc.StorageLayout)
var FaultDisputeGameDeployedBin = "0x6080604052600436106101b75760003560e01c80636361506d116100ec578063c0c3a0921161008a578063c6f0308c11610064578063c6f0308c14610649578063cf09e0d0146106ad578063d8cc1a3c146106cc578063fa24f743146106ec57600080fd5b8063c0c3a092146105ce578063c31b29ce14610602578063c55cd0c71461063657600080fd5b80638b85902b116100c65780638b85902b146104df578063929312981461051f578063bbdc02db14610553578063bcef3b551461059157600080fd5b80636361506d1461049f5780638129fc1c146104b55780638980e0cc146104ca57600080fd5b8063363cc4271161015957806354fd4d501161013357806354fd4d50146103c557806355ef20e6146103e7578063609d333414610477578063632247ea1461048c57600080fd5b8063363cc427146102fe5780634778efe81461035d578063529184c91461039157600080fd5b80632810e1d6116101955780632810e1d61461025c578063298c9005146102715780633218b99d146102b157806335fef567146102eb57600080fd5b80631e27052a146101bc578063200d2ed2146101de578063266198f91461021a575b600080fd5b3480156101c857600080fd5b506101dc6101d7366004612577565b610710565b005b3480156101ea57600080fd5b506000546102049068010000000000000000900460ff1681565b60405161021191906125c8565b60405180910390f35b34801561022657600080fd5b5061024e7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610211565b34801561026857600080fd5b50610204610ad8565b34801561027d57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036040013561024e565b3480156102bd57600080fd5b506000546102d29067ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610211565b6101dc6102f9366004612577565b610efe565b34801561030a57600080fd5b50600054610338906901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610211565b34801561036957600080fd5b5061024e7f000000000000000000000000000000000000000000000000000000000000000081565b34801561039d57600080fd5b506103387f000000000000000000000000000000000000000000000000000000000000000081565b3480156103d157600080fd5b506103da610f0e565b604051610211919061267f565b3480156103f357600080fd5b5060408051606080820183526003546fffffffffffffffffffffffffffffffff808216845270010000000000000000000000000000000091829004811660208086019190915260045485870152855193840186526005548083168552929092041690820152600654928101929092526104699182565b604051610211929190612699565b34801561048357600080fd5b506103da610fb1565b6101dc61049a366004612702565b610fbf565b3480156104ab57600080fd5b5061024e60015481565b3480156104c157600080fd5b506101dc6115a4565b3480156104d657600080fd5b5060025461024e565b3480156104eb57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036020013561024e565b34801561052b57600080fd5b506103387f000000000000000000000000000000000000000000000000000000000000000081565b34801561055f57600080fd5b5060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610211565b34801561059d57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033561024e565b3480156105da57600080fd5b506103387f000000000000000000000000000000000000000000000000000000000000000081565b34801561060e57600080fd5b506102d27f000000000000000000000000000000000000000000000000000000000000000081565b6101dc610644366004612577565b611b01565b34801561065557600080fd5b50610669610664366004612737565b611b0d565b6040805163ffffffff90961686529315156020860152928401919091526fffffffffffffffffffffffffffffffff908116606084015216608082015260a001610211565b3480156106b957600080fd5b5060005467ffffffffffffffff166102d2565b3480156106d857600080fd5b506101dc6106e7366004612799565b611b7e565b3480156106f857600080fd5b506107016120a2565b60405161021193929190612823565b6000805468010000000000000000900460ff16600281111561073457610734612599565b1461076b576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fc919061284e565b9050826001036108b7576001546040517f9a1f5e7f000000000000000000000000000000000000000000000000000000008152600481018590526024810191909152602060448201526064810183905273ffffffffffffffffffffffffffffffffffffffff821690639a1f5e7f906084015b6020604051808303816000875af115801561088d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b19190612884565b50505050565b8260020361092857600480546040517f9a1f5e7f0000000000000000000000000000000000000000000000000000000081529182018590526024820152602060448201526064810183905273ffffffffffffffffffffffffffffffffffffffff821690639a1f5e7f9060840161086e565b8260030361099c576006546040517f9a1f5e7f000000000000000000000000000000000000000000000000000000008152600481018590526024810191909152602060448201526064810183905273ffffffffffffffffffffffffffffffffffffffff821690639a1f5e7f9060840161086e565b82600403610a47576003546040517f9a1f5e7f0000000000000000000000000000000000000000000000000000000081526004810185905270010000000000000000000000000000000090910460c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166024820152600860448201526064810183905273ffffffffffffffffffffffffffffffffffffffff821690639a1f5e7f9060840161086e565b82600503610ad3576040517f9a1f5e7f000000000000000000000000000000000000000000000000000000008152600481018490524660c01b6024820152600860448201526064810183905273ffffffffffffffffffffffffffffffffffffffff821690639a1f5e7f906084016020604051808303816000875af115801561088d573d6000803e3d6000fd5b505050565b60008060005468010000000000000000900460ff166002811115610afe57610afe612599565b14610b35576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600254600090610b47906001906128cc565b90506fffffffffffffffffffffffffffffffff815b67ffffffffffffffff811015610c3157600060028281548110610b8157610b816128e3565b6000918252602090912060039091020180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9093019290915060ff6401000000009091041615610bd25750610b5c565b6002810154600090610c16906fffffffffffffffffffffffffffffffff167f00000000000000000000000000000000000000000000000000000000000000006120ff565b905083811015610c2a578093508260010194505b5050610b5c565b50600060028381548110610c4757610c476128e3565b600091825260208220600390910201805490925063ffffffff90811691908214610cb15760028281548110610c7e57610c7e6128e3565b906000526020600020906003020160020160109054906101000a90046fffffffffffffffffffffffffffffffff16610cdd565b600283015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff165b9050677fffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000060011c16610d2167ffffffffffffffff8316426128cc565b610d3d836fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16610d519190612912565b11610d88576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600283810154610e2a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b610e349190612959565b67ffffffffffffffff16158015610e5b57506fffffffffffffffffffffffffffffffff8414155b15610e695760029550610e6e565b600195505b600080548791907fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1668010000000000000000836002811115610eb357610eb3612599565b021790556002811115610ec857610ec8612599565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a2505050505090565b905090565b610f0a82826000610fbf565b5050565b6060610f397f00000000000000000000000000000000000000000000000000000000000000006121b4565b610f627f00000000000000000000000000000000000000000000000000000000000000006121b4565b610f8b7f00000000000000000000000000000000000000000000000000000000000000006121b4565b604051602001610f9d93929190612980565b604051602081830303815290604052905090565b6060610ef9602060406122f1565b6000805468010000000000000000900460ff166002811115610fe357610fe3612599565b1461101a576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82158015611026575080155b1561105d576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110611072576110726128e3565b60009182526020918290206040805160a0810182526003909302909101805463ffffffff8116845260ff64010000000090910416151593830193909352600180840154918301919091526002928301546fffffffffffffffffffffffffffffffff8082166060850152700100000000000000000000000000000000909104166080830152825491935091908690811061110d5761110d6128e3565b6000918252602082206003909102018054921515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff909316929092179091556060820151611177906fffffffffffffffffffffffffffffffff1684151760011b90565b90507f0000000000000000000000000000000000000000000000000000000000000000611236826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff161115611278576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160009063ffffffff908116146112d8576002836000015163ffffffff16815481106112a7576112a76128e3565b906000526020600020906003020160020160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b608083015160009067ffffffffffffffff1667ffffffffffffffff1642611311846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff166113259190612912565b61132f91906128cc565b9050677fffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000060011c1667ffffffffffffffff821611156113a2576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000604082901b4217905060006113c3888660009182526020526040902090565b60008181526007602052604090205490915060ff161561140f576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260076020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155815160a08101835263ffffffff808f1682529381018581528184018e81526fffffffffffffffffffffffffffffffff808d16606085019081528a8216608086019081526002805497880181558a52945160039096027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace8101805495511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000909616979099169690961793909317909655517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf8401555190518416700100000000000000000000000000000000029316929092177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0909201919091555133918a918c917f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be91a4505050505050505050565b600080547fffffffffffffffffffffffffffffffffffffffffffffff000000000000000000164267ffffffffffffffff161781556040805160a08101825263ffffffff815260208101929092526002919081016116297ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90033590565b815260016020820152604001426fffffffffffffffffffffffffffffffff9081169091528254600181810185556000948552602080862085516003909402018054918601511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000090921663ffffffff909416939093171782556040840151908201556060830151608090930151821670010000000000000000000000000000000002929091169190911760029091015573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016637f00642061175260207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c9003013590565b6040518263ffffffff1660e01b815260040161177091815260200190565b602060405180830381865afa15801561178d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b19190612884565b9050600073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663a25ae5576117fc6001856128cc565b6040518263ffffffff1660e01b815260040161181a91815260200190565b606060405180830381865afa158015611837573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185b9190612a45565b6040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810184905290915060009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa1580156118ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119109190612a45565b9050600073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166399d548aa367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003604001356040518263ffffffff1660e01b815260040161199c91815260200190565b6040805180830381865afa1580156119b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119dc9190612ad1565b905081602001516fffffffffffffffffffffffffffffffff16816020015167ffffffffffffffff1611611a3b576040517f13809ba500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160a081018252908190810180611a566001896128cc565b6fffffffffffffffffffffffffffffffff9081168252604088810151821660208085019190915298519281019290925291835280516060810182529782168852858101518216888801529451878601529085019590955280518051818601519087167001000000000000000000000000000000009188168202176003559084015160045590840151805194810151948616949095160292909217600555919091015160065551600155565b610f0a82826001610fbf565b60028181548110611b1d57600080fd5b600091825260209091206003909102018054600182015460029092015463ffffffff8216935064010000000090910460ff1691906fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041685565b6000805468010000000000000000900460ff166002811115611ba257611ba2612599565b14611bd9576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110611bee57611bee6128e3565b6000918252602082206003919091020160028101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050611c4d7f00000000000000000000000000000000000000000000000000000000000000006001612912565b611ce9826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1614611d2a576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808915611db057611d4e836fffffffffffffffffffffffffffffffff16612388565b67ffffffffffffffff16600003611d87577f00000000000000000000000000000000000000000000000000000000000000009150611da9565b611da2611d95600186612b58565b865463ffffffff1661242e565b6001015491505b5083611dca565b84600101549150611dc7846001611d959190612b89565b90505b818989604051611ddb929190612bbd565b604051809103902014611e1a576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081600101547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f8e0cb968c8c8c8c6040518563ffffffff1660e01b8152600401611e809493929190612c16565b6020604051808303816000875af1158015611e9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec39190612884565b600284810154929091149250600091611f6e906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b61200a886fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6120149190612c48565b61201e9190612959565b67ffffffffffffffff161590508115158103612066576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505084547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000001790945550505050505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560606120f8610fb1565b9050909192565b60008061218c847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1690508083036001841b600180831b0386831b17039250505092915050565b6060816000036121f757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115612221578061220b81612c69565b915061221a9050600a83612ca1565b91506121fb565b60008167ffffffffffffffff81111561223c5761223c6129f6565b6040519080825280601f01601f191660200182016040528015612266576020820181803683370190505b5090505b84156122e95761227b6001836128cc565b9150612288600a86612cb5565b612293906030612912565b60f81b8183815181106122a8576122a86128e3565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506122e2600a86612ca1565b945061226a565b949350505050565b6060600061232884367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003612912565b90508267ffffffffffffffff1667ffffffffffffffff81111561234d5761234d6129f6565b6040519080825280601f01601f191660200182016040528015612377576020820181803683370190505b509150828160208401375092915050565b600080612415837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600167ffffffffffffffff919091161b90920392915050565b60008061244c846fffffffffffffffffffffffffffffffff166124cb565b905060028381548110612461576124616128e3565b906000526020600020906003020191505b60028201546fffffffffffffffffffffffffffffffff8281169116146124c457815460028054909163ffffffff169081106124af576124af6128e3565b90600052602060002090600302019150612472565b5092915050565b6000811960018301168161255f827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169390931c8015179392505050565b6000806040838503121561258a57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310612603577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60005b8381101561262457818101518382015260200161260c565b838111156108b15750506000910152565b6000815180845261264d816020860160208601612609565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006126926020830184612635565b9392505050565b82516fffffffffffffffffffffffffffffffff90811682526020808501518216818401526040808601518185015284518316606085015290840151909116608083015282015160a082015260c08101612692565b803580151581146126fd57600080fd5b919050565b60008060006060848603121561271757600080fd5b833592506020840135915061272e604085016126ed565b90509250925092565b60006020828403121561274957600080fd5b5035919050565b60008083601f84011261276257600080fd5b50813567ffffffffffffffff81111561277a57600080fd5b60208301915083602082850101111561279257600080fd5b9250929050565b600080600080600080608087890312156127b257600080fd5b863595506127c2602088016126ed565b9450604087013567ffffffffffffffff808211156127df57600080fd5b6127eb8a838b01612750565b9096509450606089013591508082111561280457600080fd5b5061281189828a01612750565b979a9699509497509295939492505050565b60ff841681528260208201526060604082015260006128456060830184612635565b95945050505050565b60006020828403121561286057600080fd5b815173ffffffffffffffffffffffffffffffffffffffff8116811461269257600080fd5b60006020828403121561289657600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156128de576128de61289d565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082198211156129255761292561289d565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff808416806129745761297461292a565b92169190910692915050565b60008451612992818460208901612609565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516129ce816001850160208a01612609565b600192019182015283516129e9816002840160208801612609565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b80516fffffffffffffffffffffffffffffffff811681146126fd57600080fd5b600060608284031215612a5757600080fd5b6040516060810181811067ffffffffffffffff82111715612aa1577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405282518152612ab460208401612a25565b6020820152612ac560408401612a25565b60408201529392505050565b600060408284031215612ae357600080fd5b6040516040810167ffffffffffffffff8282108183111715612b2e577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8160405284518352602085015191508082168214612b4b57600080fd5b5060208201529392505050565b60006fffffffffffffffffffffffffffffffff83811690831681811015612b8157612b8161289d565b039392505050565b60006fffffffffffffffffffffffffffffffff808316818516808303821115612bb457612bb461289d565b01949350505050565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b604081526000612c2a604083018688612bcd565b8281036020840152612c3d818587612bcd565b979650505050505050565b600067ffffffffffffffff83811690831681811015612b8157612b8161289d565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612c9a57612c9a61289d565b5060010190565b600082612cb057612cb061292a565b500490565b600082612cc457612cc461292a565b50069056fea164736f6c634300080f000a" var FaultDisputeGameDeployedBin = "0x6080604052600436106101ac5760003560e01c80636361506d116100ec578063c0c3a0921161008a578063c6f0308c11610064578063c6f0308c1461061d578063cf09e0d014610681578063d8cc1a3c146106a2578063fa24f743146106c257600080fd5b8063c0c3a09214610589578063c31b29ce146105bd578063c55cd0c71461060a57600080fd5b80638b85902b116100c65780638b85902b1461049a57806392931298146104da578063bbdc02db1461050e578063bcef3b551461054c57600080fd5b80636361506d1461045a5780638129fc1c146104705780638980e0cc1461048557600080fd5b8063363cc4271161015957806354fd4d501161013357806354fd4d501461038057806355ef20e6146103a2578063609d333414610432578063632247ea1461044757600080fd5b8063363cc427146102b95780634778efe814610318578063529184c91461034c57600080fd5b80632810e1d61161018a5780632810e1d614610251578063298c90051461026657806335fef567146102a657600080fd5b80631e27052a146101b1578063200d2ed2146101d3578063266198f91461020f575b600080fd5b3480156101bd57600080fd5b506101d16101cc366004612338565b6106e6565b005b3480156101df57600080fd5b506000546101f99068010000000000000000900460ff1681565b6040516102069190612389565b60405180910390f35b34801561021b57600080fd5b506102437f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610206565b34801561025d57600080fd5b506101f96108a5565b34801561027257600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360400135610243565b6101d16102b4366004612338565b610ccb565b3480156102c557600080fd5b506000546102f3906901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610206565b34801561032457600080fd5b506102437f000000000000000000000000000000000000000000000000000000000000000081565b34801561035857600080fd5b506102f37f000000000000000000000000000000000000000000000000000000000000000081565b34801561038c57600080fd5b50610395610cdb565b6040516102069190612440565b3480156103ae57600080fd5b5060408051606080820183526003546fffffffffffffffffffffffffffffffff808216845270010000000000000000000000000000000091829004811660208086019190915260045485870152855193840186526005548083168552929092041690820152600654928101929092526104249182565b60405161020692919061245a565b34801561043e57600080fd5b50610395610d7e565b6101d16104553660046124c3565b610d8c565b34801561046657600080fd5b5061024360015481565b34801561047c57600080fd5b506101d1611360565b34801561049157600080fd5b50600254610243565b3480156104a657600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360200135610243565b3480156104e657600080fd5b506102f37f000000000000000000000000000000000000000000000000000000000000000081565b34801561051a57600080fd5b5060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610206565b34801561055857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335610243565b34801561059557600080fd5b506102f37f000000000000000000000000000000000000000000000000000000000000000081565b3480156105c957600080fd5b506105f17f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff9091168152602001610206565b6101d1610618366004612338565b6118bd565b34801561062957600080fd5b5061063d6106383660046124f8565b6118c9565b6040805163ffffffff90961686529315156020860152928401919091526fffffffffffffffffffffffffffffffff908116606084015216608082015260a001610206565b34801561068d57600080fd5b506000546105f19067ffffffffffffffff1681565b3480156106ae57600080fd5b506101d16106bd36600461255a565b61193a565b3480156106ce57600080fd5b506106d7611e5b565b604051610206939291906125e4565b6000805468010000000000000000900460ff16600281111561070a5761070a61235a565b14610741576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d2919061260f565b7f9a1f5e7f00000000000000000000000000000000000000000000000000000000601c8190526020859052909150600084600181146108395760028114610843576003811461084d576004811461085757600581146108675763ff137e656000526004601cfd5b600154915061086e565b600454915061086e565b600654915061086e565b60035460801c60c01b915061086e565b4660c01b91505b50604052600160038511811b6005031b60605260808390526000806084601c82865af161089f573d6000803e3d6000fd5b50505050565b60008060005468010000000000000000900460ff1660028111156108cb576108cb61235a565b14610902576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460009061091490600190612674565b90506fffffffffffffffffffffffffffffffff815b67ffffffffffffffff8110156109fe5760006002828154811061094e5761094e61268b565b6000918252602090912060039091020180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9093019290915060ff640100000000909104161561099f5750610929565b60028101546000906109e3906fffffffffffffffffffffffffffffffff167f0000000000000000000000000000000000000000000000000000000000000000611eb8565b9050838110156109f7578093508260010194505b5050610929565b50600060028381548110610a1457610a1461268b565b600091825260208220600390910201805490925063ffffffff90811691908214610a7e5760028281548110610a4b57610a4b61268b565b906000526020600020906003020160020160109054906101000a90046fffffffffffffffffffffffffffffffff16610aaa565b600283015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff165b9050677fffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000060011c16610aee67ffffffffffffffff831642612674565b610b0a836fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16610b1e91906126ba565b11610b55576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600283810154610bf7906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b610c019190612701565b67ffffffffffffffff16158015610c2857506fffffffffffffffffffffffffffffffff8414155b15610c365760029550610c3b565b600195505b600080548791907fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1668010000000000000000836002811115610c8057610c8061235a565b021790556002811115610c9557610c9561235a565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a2505050505090565b905090565b610cd782826000610d8c565b5050565b6060610d067f0000000000000000000000000000000000000000000000000000000000000000611f6d565b610d2f7f0000000000000000000000000000000000000000000000000000000000000000611f6d565b610d587f0000000000000000000000000000000000000000000000000000000000000000611f6d565b604051602001610d6a93929190612728565b604051602081830303815290604052905090565b6060610cc6602060406120aa565b6000805468010000000000000000900460ff166002811115610db057610db061235a565b14610de7576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82158015610df3575080155b15610e2a576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110610e3f57610e3f61268b565b600091825260208083206040805160a081018252600394909402909101805463ffffffff808216865264010000000090910460ff16151593850193909352600181015491840191909152600201546fffffffffffffffffffffffffffffffff80821660608501819052700100000000000000000000000000000000909204166080840152919350610ed39190859061214116565b90507f0000000000000000000000000000000000000000000000000000000000000000610f92826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff161115610fd4576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160009063ffffffff90811614611034576002836000015163ffffffff16815481106110035761100361268b565b906000526020600020906003020160020160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b608083015160009067ffffffffffffffff1667ffffffffffffffff164261106d846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff1661108191906126ba565b61108b9190612674565b9050677fffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000060011c1667ffffffffffffffff821611156110fe576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000604082901b42179050600061111f888660009182526020526040902090565b60008181526007602052604090205490915060ff161561116b576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260076020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155815160a08101835263ffffffff808f1682529381018581529281018d81526fffffffffffffffffffffffffffffffff808c16606084019081528982166080850190815260028054808801825599819052945160039099027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace8101805498511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009099169a909916999099179690961790965590517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf8701559351925184167001000000000000000000000000000000000292909316919091177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad09093019290925580548b9081106112e3576112e361268b565b6000918252602082206003909102018054921515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff9093169290921790915560405133918a918c917f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be91a4505050505050505050565b600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161781556040805160a08101825263ffffffff815260208101929092526002919081016113e57ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90033590565b815260016020820152604001426fffffffffffffffffffffffffffffffff9081169091528254600181810185556000948552602080862085516003909402018054918601511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000090921663ffffffff909416939093171782556040840151908201556060830151608090930151821670010000000000000000000000000000000002929091169190911760029091015573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016637f00642061150e60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c9003013590565b6040518263ffffffff1660e01b815260040161152c91815260200190565b602060405180830381865afa158015611549573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156d919061279e565b9050600073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001663a25ae5576115b8600185612674565b6040518263ffffffff1660e01b81526004016115d691815260200190565b606060405180830381865afa1580156115f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116179190612806565b6040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810184905290915060009073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a25ae55790602401606060405180830381865afa1580156116a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116cc9190612806565b9050600073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166399d548aa367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003604001356040518263ffffffff1660e01b815260040161175891815260200190565b6040805180830381865afa158015611774573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117989190612892565b905081602001516fffffffffffffffffffffffffffffffff16816020015167ffffffffffffffff16116117f7576040517f13809ba500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160a081018252908190810180611812600189612674565b6fffffffffffffffffffffffffffffffff9081168252604088810151821660208085019190915298519281019290925291835280516060810182529782168852858101518216888801529451878601529085019590955280518051818601519087167001000000000000000000000000000000009188168202176003559084015160045590840151805194810151948616949095160292909217600555919091015160065551600155565b610cd782826001610d8c565b600281815481106118d957600080fd5b600091825260209091206003909102018054600182015460029092015463ffffffff8216935064010000000090910460ff1691906fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041685565b6000805468010000000000000000900460ff16600281111561195e5761195e61235a565b14611995576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600287815481106119aa576119aa61268b565b6000918252602082206003919091020160028101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050611a097f000000000000000000000000000000000000000000000000000000000000000060016126ba565b611aa5826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1614611ae6576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808915611b6957611b0a836fffffffffffffffffffffffffffffffff16612149565b67ffffffffffffffff1615611b3d57611b34611b27600186612919565b865463ffffffff166121ef565b60010154611b5f565b7f00000000000000000000000000000000000000000000000000000000000000005b9150849050611b83565b84600101549150611b80846001611b27919061294a565b90505b818989604051611b9492919061297e565b604051809103902014611bd3576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081600101547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f8e0cb968c8c8c8c6040518563ffffffff1660e01b8152600401611c3994939291906129d7565b6020604051808303816000875af1158015611c58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c7c919061279e565b600284810154929091149250600091611d27906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b611dc3886fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b611dcd9190612a09565b611dd79190612701565b67ffffffffffffffff161590508115158103611e1f576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505084547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff166401000000001790945550505050505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003356060611eb1610d7e565b9050909192565b600080611f45847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff1690508083036001841b600180831b0386831b17039250505092915050565b606081600003611fb057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611fda5780611fc481612a2a565b9150611fd39050600a83612a62565b9150611fb4565b60008167ffffffffffffffff811115611ff557611ff56127b7565b6040519080825280601f01601f19166020018201604052801561201f576020820181803683370190505b5090505b84156120a257612034600183612674565b9150612041600a86612a76565b61204c9060306126ba565b60f81b8183815181106120615761206161268b565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061209b600a86612a62565b9450612023565b949350505050565b606060006120e184367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036126ba565b90508267ffffffffffffffff1667ffffffffffffffff811115612106576121066127b7565b6040519080825280601f01601f191660200182016040528015612130576020820181803683370190505b509150828160208401375092915050565b151760011b90565b6000806121d6837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600167ffffffffffffffff919091161b90920392915050565b60008061220d846fffffffffffffffffffffffffffffffff1661228c565b9050600283815481106122225761222261268b565b906000526020600020906003020191505b60028201546fffffffffffffffffffffffffffffffff82811691161461228557815460028054909163ffffffff169081106122705761227061268b565b90600052602060002090600302019150612233565b5092915050565b60008119600183011681612320827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b67ffffffffffffffff169390931c8015179392505050565b6000806040838503121561234b57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600383106123c4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60005b838110156123e55781810151838201526020016123cd565b8381111561089f5750506000910152565b6000815180845261240e8160208601602086016123ca565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061245360208301846123f6565b9392505050565b82516fffffffffffffffffffffffffffffffff90811682526020808501518216818401526040808601518185015284518316606085015290840151909116608083015282015160a082015260c08101612453565b803580151581146124be57600080fd5b919050565b6000806000606084860312156124d857600080fd5b83359250602084013591506124ef604085016124ae565b90509250925092565b60006020828403121561250a57600080fd5b5035919050565b60008083601f84011261252357600080fd5b50813567ffffffffffffffff81111561253b57600080fd5b60208301915083602082850101111561255357600080fd5b9250929050565b6000806000806000806080878903121561257357600080fd5b86359550612583602088016124ae565b9450604087013567ffffffffffffffff808211156125a057600080fd5b6125ac8a838b01612511565b909650945060608901359150808211156125c557600080fd5b506125d289828a01612511565b979a9699509497509295939492505050565b60ff8416815282602082015260606040820152600061260660608301846123f6565b95945050505050565b60006020828403121561262157600080fd5b815173ffffffffffffffffffffffffffffffffffffffff8116811461245357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561268657612686612645565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082198211156126cd576126cd612645565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff8084168061271c5761271c6126d2565b92169190910692915050565b6000845161273a8184602089016123ca565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551612776816001850160208a016123ca565b600192019182015283516127918160028401602088016123ca565b0160020195945050505050565b6000602082840312156127b057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b80516fffffffffffffffffffffffffffffffff811681146124be57600080fd5b60006060828403121561281857600080fd5b6040516060810181811067ffffffffffffffff82111715612862577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405282518152612875602084016127e6565b6020820152612886604084016127e6565b60408201529392505050565b6000604082840312156128a457600080fd5b6040516040810167ffffffffffffffff82821081831117156128ef577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b816040528451835260208501519150808216821461290c57600080fd5b5060208201529392505050565b60006fffffffffffffffffffffffffffffffff8381169083168181101561294257612942612645565b039392505050565b60006fffffffffffffffffffffffffffffffff80831681851680830382111561297557612975612645565b01949350505050565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6040815260006129eb60408301868861298e565b82810360208401526129fe81858761298e565b979650505050505050565b600067ffffffffffffffff8381169083168181101561294257612942612645565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612a5b57612a5b612645565b5060010190565b600082612a7157612a716126d2565b500490565b600082612a8557612a856126d2565b50069056fea164736f6c634300080f000a"
func init() { func init() {
if err := json.Unmarshal([]byte(FaultDisputeGameStorageLayoutJSON), FaultDisputeGameStorageLayout); err != nil { if err := json.Unmarshal([]byte(FaultDisputeGameStorageLayoutJSON), FaultDisputeGameStorageLayout); err != nil {
......
...@@ -470,6 +470,7 @@ func NewDeployConfigWithNetwork(network, path string) (*DeployConfig, error) { ...@@ -470,6 +470,7 @@ func NewDeployConfigWithNetwork(network, path string) (*DeployConfig, error) {
// L1Deployments represents a set of L1 contracts that are deployed. // L1Deployments represents a set of L1 contracts that are deployed.
type L1Deployments struct { type L1Deployments struct {
AddressManager common.Address `json:"AddressManager"` AddressManager common.Address `json:"AddressManager"`
BlockOracle common.Address `json:"BlockOracle"`
DisputeGameFactory common.Address `json:"DisputeGameFactory"` DisputeGameFactory common.Address `json:"DisputeGameFactory"`
DisputeGameFactoryProxy common.Address `json:"DisputeGameFactoryProxy"` DisputeGameFactoryProxy common.Address `json:"DisputeGameFactoryProxy"`
L1CrossDomainMessenger common.Address `json:"L1CrossDomainMessenger"` L1CrossDomainMessenger common.Address `json:"L1CrossDomainMessenger"`
...@@ -512,7 +513,7 @@ func (d *L1Deployments) Check() error { ...@@ -512,7 +513,7 @@ func (d *L1Deployments) Check() error {
for i := 0; i < val.NumField(); i++ { for i := 0; i < val.NumField(); i++ {
name := val.Type().Field(i).Name name := val.Type().Field(i).Name
// Skip the non production ready contracts // Skip the non production ready contracts
if name == "DisputeGameFactory" || name == "DisputeGameFactoryProxy" { if name == "DisputeGameFactory" || name == "DisputeGameFactoryProxy" || name == "BlockOracle" {
continue continue
} }
if val.Field(i).Interface().(common.Address) == (common.Address{}) { if val.Field(i).Interface().(common.Address) == (common.Address{}) {
......
...@@ -13,17 +13,16 @@ import ( ...@@ -13,17 +13,16 @@ import (
) )
var ( var (
l1EthRpc = "http://example.com:8545" l1EthRpc = "http://example.com:8545"
gameAddressValue = "0xaa00000000000000000000000000000000000000" gameAddressValue = "0xaa00000000000000000000000000000000000000"
preimageOracleAddressValue = "0xbb00000000000000000000000000000000000000" cannonBin = "./bin/cannon"
cannonBin = "./bin/cannon" cannonServer = "./bin/op-program"
cannonServer = "./bin/op-program" cannonPreState = "./pre.json"
cannonPreState = "./pre.json" cannonDatadir = "./test_data"
cannonDatadir = "./test_data" cannonL2 = "http://example.com:9545"
cannonL2 = "http://example.com:9545" alphabetTrace = "abcdefghijz"
alphabetTrace = "abcdefghijz" agreeWithProposedOutput = "true"
agreeWithProposedOutput = "true" gameDepth = "4"
gameDepth = "4"
) )
func TestLogLevel(t *testing.T) { func TestLogLevel(t *testing.T) {
...@@ -43,14 +42,14 @@ func TestLogLevel(t *testing.T) { ...@@ -43,14 +42,14 @@ func TestLogLevel(t *testing.T) {
func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) { func TestDefaultCLIOptionsMatchDefaultConfig(t *testing.T) {
cfg := configForArgs(t, addRequiredArgs(config.TraceTypeAlphabet)) cfg := configForArgs(t, addRequiredArgs(config.TraceTypeAlphabet))
defaultCfg := config.NewConfig(l1EthRpc, common.HexToAddress(gameAddressValue), common.HexToAddress(preimageOracleAddressValue), config.TraceTypeAlphabet, true, 4) defaultCfg := config.NewConfig(l1EthRpc, common.HexToAddress(gameAddressValue), config.TraceTypeAlphabet, true, 4)
// Add in the extra CLI options required when using alphabet trace type // Add in the extra CLI options required when using alphabet trace type
defaultCfg.AlphabetTrace = alphabetTrace defaultCfg.AlphabetTrace = alphabetTrace
require.Equal(t, defaultCfg, cfg) require.Equal(t, defaultCfg, cfg)
} }
func TestDefaultConfigIsValid(t *testing.T) { func TestDefaultConfigIsValid(t *testing.T) {
cfg := config.NewConfig(l1EthRpc, common.HexToAddress(gameAddressValue), common.HexToAddress(preimageOracleAddressValue), config.TraceTypeAlphabet, true, 4) cfg := config.NewConfig(l1EthRpc, common.HexToAddress(gameAddressValue), config.TraceTypeAlphabet, true, 4)
// Add in options that are required based on the specific trace type // Add in options that are required based on the specific trace type
// To avoid needing to specify unused options, these aren't included in the params for NewConfig // To avoid needing to specify unused options, these aren't included in the params for NewConfig
cfg.AlphabetTrace = alphabetTrace cfg.AlphabetTrace = alphabetTrace
...@@ -140,26 +139,6 @@ func TestGameDepth(t *testing.T) { ...@@ -140,26 +139,6 @@ func TestGameDepth(t *testing.T) {
}) })
} }
func TestPreimageOracleAddress(t *testing.T) {
t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) {
configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--preimage-oracle-address"))
})
t.Run("Required", func(t *testing.T) {
verifyArgsInvalid(t, "flag preimage-oracle-address is required", addRequiredArgsExcept(config.TraceTypeCannon, "--preimage-oracle-address"))
})
t.Run("Valid", func(t *testing.T) {
addr := common.Address{0xbb, 0xcc, 0xdd}
cfg := configForArgs(t, addRequiredArgsExcept(config.TraceTypeCannon, "--preimage-oracle-address", "--preimage-oracle-address="+addr.Hex()))
require.Equal(t, addr, cfg.PreimageOracleAddress)
})
t.Run("Invalid", func(t *testing.T) {
verifyArgsInvalid(t, "invalid address: foo", addRequiredArgsExcept(config.TraceTypeCannon, "--preimage-oracle-address", "--preimage-oracle-address=foo"))
})
}
func TestCannonBin(t *testing.T) { func TestCannonBin(t *testing.T) {
t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) {
configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-bin")) configForArgs(t, addRequiredArgsExcept(config.TraceTypeAlphabet, "--cannon-bin"))
...@@ -288,7 +267,6 @@ func requiredArgs(traceType config.TraceType) map[string]string { ...@@ -288,7 +267,6 @@ func requiredArgs(traceType config.TraceType) map[string]string {
"--agree-with-proposed-output": agreeWithProposedOutput, "--agree-with-proposed-output": agreeWithProposedOutput,
"--l1-eth-rpc": l1EthRpc, "--l1-eth-rpc": l1EthRpc,
"--game-address": gameAddressValue, "--game-address": gameAddressValue,
"--preimage-oracle-address": preimageOracleAddressValue,
"--trace-type": traceType.String(), "--trace-type": traceType.String(),
} }
switch traceType { switch traceType {
......
...@@ -61,7 +61,6 @@ const DefaultCannonSnapshotFreq = uint(10_000) ...@@ -61,7 +61,6 @@ const DefaultCannonSnapshotFreq = uint(10_000)
type Config struct { type Config struct {
L1EthRpc string // L1 RPC Url L1EthRpc string // L1 RPC Url
GameAddress common.Address // Address of the fault game GameAddress common.Address // Address of the fault game
PreimageOracleAddress common.Address // Address of the pre-image oracle
AgreeWithProposedOutput bool // Temporary config if we agree or disagree with the posted output AgreeWithProposedOutput bool // Temporary config if we agree or disagree with the posted output
GameDepth int // Depth of the game tree GameDepth int // Depth of the game tree
...@@ -84,15 +83,13 @@ type Config struct { ...@@ -84,15 +83,13 @@ type Config struct {
func NewConfig( func NewConfig(
l1EthRpc string, l1EthRpc string,
gameAddress common.Address, gameAddress common.Address,
preimageOracleAddress common.Address,
traceType TraceType, traceType TraceType,
agreeWithProposedOutput bool, agreeWithProposedOutput bool,
gameDepth int, gameDepth int,
) Config { ) Config {
return Config{ return Config{
L1EthRpc: l1EthRpc, L1EthRpc: l1EthRpc,
GameAddress: gameAddress, GameAddress: gameAddress,
PreimageOracleAddress: preimageOracleAddress,
AgreeWithProposedOutput: agreeWithProposedOutput, AgreeWithProposedOutput: agreeWithProposedOutput,
GameDepth: gameDepth, GameDepth: gameDepth,
...@@ -116,9 +113,6 @@ func (c Config) Check() error { ...@@ -116,9 +113,6 @@ func (c Config) Check() error {
return ErrMissingTraceType return ErrMissingTraceType
} }
if c.TraceType == TraceTypeCannon { if c.TraceType == TraceTypeCannon {
if c.PreimageOracleAddress == (common.Address{}) {
return ErrMissingPreimageOracleAddress
}
if c.CannonBin == "" { if c.CannonBin == "" {
return ErrMissingCannonBin return ErrMissingCannonBin
} }
......
...@@ -11,7 +11,6 @@ import ( ...@@ -11,7 +11,6 @@ import (
var ( var (
validL1EthRpc = "http://localhost:8545" validL1EthRpc = "http://localhost:8545"
validGameAddress = common.HexToAddress("0x7bdd3b028C4796eF0EAf07d11394d0d9d8c24139") validGameAddress = common.HexToAddress("0x7bdd3b028C4796eF0EAf07d11394d0d9d8c24139")
validPreimageOracleAddress = common.HexToAddress("0x7bdd3b028C4796eF0EAf07d11394d0d9d8c24139")
validAlphabetTrace = "abcdefgh" validAlphabetTrace = "abcdefgh"
validCannonBin = "./bin/cannon" validCannonBin = "./bin/cannon"
validCannonOpProgramBin = "./bin/op-program" validCannonOpProgramBin = "./bin/op-program"
...@@ -23,7 +22,7 @@ var ( ...@@ -23,7 +22,7 @@ var (
) )
func validConfig(traceType TraceType) Config { func validConfig(traceType TraceType) Config {
cfg := NewConfig(validL1EthRpc, validGameAddress, validPreimageOracleAddress, traceType, agreeWithProposedOutput, gameDepth) cfg := NewConfig(validL1EthRpc, validGameAddress, traceType, agreeWithProposedOutput, gameDepth)
switch traceType { switch traceType {
case TraceTypeAlphabet: case TraceTypeAlphabet:
cfg.AlphabetTrace = validAlphabetTrace cfg.AlphabetTrace = validAlphabetTrace
...@@ -74,12 +73,6 @@ func TestAlphabetTraceRequired(t *testing.T) { ...@@ -74,12 +73,6 @@ func TestAlphabetTraceRequired(t *testing.T) {
require.ErrorIs(t, config.Check(), ErrMissingAlphabetTrace) require.ErrorIs(t, config.Check(), ErrMissingAlphabetTrace)
} }
func TestCannonPreimageOracleAddressRequired(t *testing.T) {
config := validConfig(TraceTypeCannon)
config.PreimageOracleAddress = common.Address{}
require.ErrorIs(t, config.Check(), ErrMissingPreimageOracleAddress)
}
func TestCannonBinRequired(t *testing.T) { func TestCannonBinRequired(t *testing.T) {
config := validConfig(TraceTypeCannon) config := validConfig(TraceTypeCannon)
config.CannonBin = "" config.CannonBin = ""
......
...@@ -23,16 +23,18 @@ type Agent struct { ...@@ -23,16 +23,18 @@ type Agent struct {
solver *solver.Solver solver *solver.Solver
loader Loader loader Loader
responder Responder responder Responder
updater types.OracleUpdater
maxDepth int maxDepth int
agreeWithProposedOutput bool agreeWithProposedOutput bool
log log.Logger log log.Logger
} }
func NewAgent(loader Loader, maxDepth int, trace types.TraceProvider, responder Responder, agreeWithProposedOutput bool, log log.Logger) *Agent { func NewAgent(loader Loader, maxDepth int, trace types.TraceProvider, responder Responder, updater types.OracleUpdater, agreeWithProposedOutput bool, log log.Logger) *Agent {
return &Agent{ return &Agent{
solver: solver.NewSolver(maxDepth, trace), solver: solver.NewSolver(maxDepth, trace),
loader: loader, loader: loader,
responder: responder, responder: responder,
updater: updater,
maxDepth: maxDepth, maxDepth: maxDepth,
agreeWithProposedOutput: agreeWithProposedOutput, agreeWithProposedOutput: agreeWithProposedOutput,
log: log, log: log,
...@@ -132,6 +134,17 @@ func (a *Agent) step(ctx context.Context, claim types.Claim, game types.Game) er ...@@ -132,6 +134,17 @@ func (a *Agent) step(ctx context.Context, claim types.Claim, game types.Game) er
return nil return nil
} }
oracleData, err := a.solver.GetOracleData(ctx, claim)
if err != nil {
a.log.Debug("Failed to get oracle data", "err", err)
return nil
}
a.log.Info("Updating oracle data", "oracleKey", oracleData.OracleKey, "oracleData", oracleData.OracleData)
if err := a.updater.UpdateOracle(ctx, *oracleData); err != nil {
return fmt.Errorf("failed to load oracle data: %w", err)
}
a.log.Info("Attempting step", "claim_depth", claim.Depth(), "maxDepth", a.maxDepth) a.log.Info("Attempting step", "claim_depth", claim.Depth(), "maxDepth", a.maxDepth)
step, err := a.solver.AttemptStep(ctx, claim, agreeWithClaimLevel) step, err := a.solver.AttemptStep(ctx, claim, agreeWithClaimLevel)
if err != nil { if err != nil {
......
...@@ -56,31 +56,44 @@ func NewExecutor(logger log.Logger, cfg *config.Config, inputs localGameInputs) ...@@ -56,31 +56,44 @@ func NewExecutor(logger log.Logger, cfg *config.Config, inputs localGameInputs)
} }
func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) error { func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) error {
start, err := e.selectSnapshot(e.logger, filepath.Join(e.dataDir, snapsDir), e.absolutePreState, i) snapshotDir := filepath.Join(dir, snapsDir)
start, err := e.selectSnapshot(e.logger, snapshotDir, e.absolutePreState, i)
if err != nil { if err != nil {
return fmt.Errorf("find starting snapshot: %w", err) return fmt.Errorf("find starting snapshot: %w", err)
} }
proofDir := filepath.Join(dir, proofsDir)
dataDir := filepath.Join(e.dataDir, preimagesDir)
args := []string{ args := []string{
"run", "run",
"--input", start, "--input", start,
"--output", filepath.Join(dir, "out.json"),
"--meta", "",
"--proof-at", "=" + strconv.FormatUint(i, 10), "--proof-at", "=" + strconv.FormatUint(i, 10),
"--stop-at", "=" + strconv.FormatUint(i+1, 10), "--stop-at", "=" + strconv.FormatUint(i+1, 10),
"--proof-fmt", filepath.Join(dir, proofsDir, "%d.json"), "--proof-fmt", filepath.Join(proofDir, "%d.json"),
"--snapshot-at", "%" + strconv.FormatUint(uint64(e.snapshotFreq), 10), "--snapshot-at", "%" + strconv.FormatUint(uint64(e.snapshotFreq), 10),
"--snapshot-fmt", filepath.Join(e.dataDir, snapsDir, "%d.json"), "--snapshot-fmt", filepath.Join(snapshotDir, "%d.json"),
"--", "--",
e.server, e.server,
"--l1", e.l1, "--l1", e.l1,
"--l2", e.l2, "--l2", e.l2,
"--datadir", filepath.Join(e.dataDir, preimagesDir), "--datadir", dataDir,
"--l1.head", e.inputs.l1Head.Hex(), "--l1.head", e.inputs.l1Head.Hex(),
"--l2.head", e.inputs.l2Head.Hex(), "--l2.head", e.inputs.l2Head.Hex(),
"--l2.outputroot", e.inputs.l2OutputRoot.Hex(), "--l2.outputroot", e.inputs.l2OutputRoot.Hex(),
"--l2.claim", e.inputs.l2Claim.Hex(), "--l2.claim", e.inputs.l2Claim.Hex(),
"--l2.blocknumber", e.inputs.l2BlockNumber.Text(10), "--l2.blocknumber", e.inputs.l2BlockNumber.Text(10),
"--l2.chainid", e.inputs.l2ChainId.Text(10),
} }
if err := os.MkdirAll(snapshotDir, 0755); err != nil {
return fmt.Errorf("could not create snapshot directory %v: %w", snapshotDir, err)
}
if err := os.MkdirAll(dataDir, 0755); err != nil {
return fmt.Errorf("could not create preimage cache directory %v: %w", dataDir, err)
}
if err := os.MkdirAll(proofDir, 0755); err != nil {
return fmt.Errorf("could not create proofs directory %v: %w", proofDir, err)
}
e.logger.Info("Generating trace", "proof", i, "cmd", e.cannon, "args", args) e.logger.Info("Generating trace", "proof", i, "cmd", e.cannon, "args", args)
return e.cmdExecutor(ctx, e.logger.New("proof", i), e.cannon, args...) return e.cmdExecutor(ctx, e.logger.New("proof", i), e.cannon, args...)
} }
......
...@@ -20,7 +20,7 @@ const execTestCannonPrestate = "/foo/pre.json" ...@@ -20,7 +20,7 @@ const execTestCannonPrestate = "/foo/pre.json"
func TestGenerateProof(t *testing.T) { func TestGenerateProof(t *testing.T) {
input := "starting.json" input := "starting.json"
cfg := config.NewConfig("http://localhost:8888", common.Address{0xaa}, common.Address{0xbb}, config.TraceTypeCannon, true, 5) cfg := config.NewConfig("http://localhost:8888", common.Address{0xaa}, config.TraceTypeCannon, true, 5)
cfg.CannonDatadir = t.TempDir() cfg.CannonDatadir = t.TempDir()
cfg.CannonAbsolutePreState = "pre.json" cfg.CannonAbsolutePreState = "pre.json"
cfg.CannonBin = "./bin/cannon" cfg.CannonBin = "./bin/cannon"
...@@ -30,7 +30,6 @@ func TestGenerateProof(t *testing.T) { ...@@ -30,7 +30,6 @@ func TestGenerateProof(t *testing.T) {
inputs := localGameInputs{ inputs := localGameInputs{
l1Head: common.Hash{0x11}, l1Head: common.Hash{0x11},
l2ChainId: big.NewInt(2342),
l2Head: common.Hash{0x22}, l2Head: common.Hash{0x22},
l2OutputRoot: common.Hash{0x33}, l2OutputRoot: common.Hash{0x33},
l2Claim: common.Hash{0x44}, l2Claim: common.Hash{0x44},
...@@ -54,9 +53,15 @@ func TestGenerateProof(t *testing.T) { ...@@ -54,9 +53,15 @@ func TestGenerateProof(t *testing.T) {
} }
err := executor.GenerateProof(context.Background(), cfg.CannonDatadir, 150_000_000) err := executor.GenerateProof(context.Background(), cfg.CannonDatadir, 150_000_000)
require.NoError(t, err) require.NoError(t, err)
require.DirExists(t, filepath.Join(cfg.CannonDatadir, preimagesDir))
require.DirExists(t, filepath.Join(cfg.CannonDatadir, proofsDir))
require.DirExists(t, filepath.Join(cfg.CannonDatadir, snapsDir))
require.Equal(t, cfg.CannonBin, binary) require.Equal(t, cfg.CannonBin, binary)
require.Equal(t, "run", subcommand) require.Equal(t, "run", subcommand)
require.Equal(t, input, args["--input"]) require.Equal(t, input, args["--input"])
require.Contains(t, args, "--meta")
require.Equal(t, "", args["--meta"])
require.Equal(t, filepath.Join(cfg.CannonDatadir, "out.json"), args["--output"])
require.Equal(t, "=150000000", args["--proof-at"]) require.Equal(t, "=150000000", args["--proof-at"])
require.Equal(t, "=150000001", args["--stop-at"]) require.Equal(t, "=150000001", args["--stop-at"])
require.Equal(t, "%500", args["--snapshot-at"]) require.Equal(t, "%500", args["--snapshot-at"])
...@@ -73,7 +78,6 @@ func TestGenerateProof(t *testing.T) { ...@@ -73,7 +78,6 @@ func TestGenerateProof(t *testing.T) {
require.Equal(t, inputs.l2OutputRoot.Hex(), args["--l2.outputroot"]) require.Equal(t, inputs.l2OutputRoot.Hex(), args["--l2.outputroot"])
require.Equal(t, inputs.l2Claim.Hex(), args["--l2.claim"]) require.Equal(t, inputs.l2Claim.Hex(), args["--l2.claim"])
require.Equal(t, "3333", args["--l2.blocknumber"]) require.Equal(t, "3333", args["--l2.blocknumber"])
require.Equal(t, "2342", args["--l2.chainid"])
} }
func TestRunCmdLogsOutput(t *testing.T) { func TestRunCmdLogsOutput(t *testing.T) {
......
...@@ -13,7 +13,6 @@ import ( ...@@ -13,7 +13,6 @@ import (
type localGameInputs struct { type localGameInputs struct {
l1Head common.Hash l1Head common.Hash
l2ChainId *big.Int
l2Head common.Hash l2Head common.Hash
l2OutputRoot common.Hash l2OutputRoot common.Hash
l2Claim common.Hash l2Claim common.Hash
...@@ -39,10 +38,6 @@ func fetchLocalInputs(ctx context.Context, gameAddr common.Address, caller GameI ...@@ -39,10 +38,6 @@ func fetchLocalInputs(ctx context.Context, gameAddr common.Address, caller GameI
if err != nil { if err != nil {
return localGameInputs{}, fmt.Errorf("fetch L1 head for game %v: %w", gameAddr, err) return localGameInputs{}, fmt.Errorf("fetch L1 head for game %v: %w", gameAddr, err)
} }
l2ChainId, err := l2Client.ChainID(ctx)
if err != nil {
return localGameInputs{}, fmt.Errorf("fetch L2 chain ID: %w", err)
}
proposals, err := caller.Proposals(opts) proposals, err := caller.Proposals(opts)
if err != nil { if err != nil {
...@@ -58,7 +53,6 @@ func fetchLocalInputs(ctx context.Context, gameAddr common.Address, caller GameI ...@@ -58,7 +53,6 @@ func fetchLocalInputs(ctx context.Context, gameAddr common.Address, caller GameI
return localGameInputs{ return localGameInputs{
l1Head: l1Head, l1Head: l1Head,
l2ChainId: l2ChainId,
l2Head: l2Head, l2Head: l2Head,
l2OutputRoot: agreedOutput.OutputRoot, l2OutputRoot: agreedOutput.OutputRoot,
l2Claim: claimedOutput.OutputRoot, l2Claim: claimedOutput.OutputRoot,
......
...@@ -40,7 +40,6 @@ func TestFetchLocalInputs(t *testing.T) { ...@@ -40,7 +40,6 @@ func TestFetchLocalInputs(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, l1Client.l1Head, inputs.l1Head) require.Equal(t, l1Client.l1Head, inputs.l1Head)
require.Equal(t, l2Client.chainID, inputs.l2ChainId)
require.Equal(t, l2Client.header.Hash(), inputs.l2Head) require.Equal(t, l2Client.header.Hash(), inputs.l2Head)
require.EqualValues(t, l1Client.starting.OutputRoot, inputs.l2OutputRoot) require.EqualValues(t, l1Client.starting.OutputRoot, inputs.l2OutputRoot)
require.EqualValues(t, l1Client.disputed.OutputRoot, inputs.l2Claim) require.EqualValues(t, l1Client.disputed.OutputRoot, inputs.l2Claim)
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -28,8 +29,36 @@ type cannonUpdater struct { ...@@ -28,8 +29,36 @@ type cannonUpdater struct {
preimageOracleAddr common.Address preimageOracleAddr common.Address
} }
// NewOracleUpdater returns a new updater. // NewOracleUpdater returns a new updater. The pre-image oracle address is loaded from the fault dispute game.
func NewOracleUpdater( func NewOracleUpdater(
ctx context.Context,
logger log.Logger,
txMgr txmgr.TxManager,
fdgAddr common.Address,
client bind.ContractCaller,
) (*cannonUpdater, error) {
gameCaller, err := bindings.NewFaultDisputeGameCaller(fdgAddr, client)
if err != nil {
return nil, fmt.Errorf("create caller for game %v: %w", fdgAddr, err)
}
opts := &bind.CallOpts{Context: ctx}
vm, err := gameCaller.VM(opts)
if err != nil {
return nil, fmt.Errorf("failed to load VM address from game %v: %w", fdgAddr, err)
}
mipsCaller, err := bindings.NewMIPSCaller(vm, client)
if err != nil {
return nil, fmt.Errorf("failed to create MIPS caller for address %v: %w", vm, err)
}
oracleAddr, err := mipsCaller.Oracle(opts)
if err != nil {
return nil, fmt.Errorf("failed to load pre-image oracle address from game %v: %w", fdgAddr, err)
}
return NewOracleUpdaterWithOracle(logger, txMgr, fdgAddr, oracleAddr)
}
// NewOracleUpdaterWithOracle returns a new updater using a specified pre-image oracle address.
func NewOracleUpdaterWithOracle(
logger log.Logger, logger log.Logger,
txMgr txmgr.TxManager, txMgr txmgr.TxManager,
fdgAddr common.Address, fdgAddr common.Address,
......
...@@ -64,7 +64,7 @@ func newTestCannonUpdater(t *testing.T, sendFails bool) (*cannonUpdater, *mockTx ...@@ -64,7 +64,7 @@ func newTestCannonUpdater(t *testing.T, sendFails bool) (*cannonUpdater, *mockTx
from: mockFdgAddress, from: mockFdgAddress,
sendFails: sendFails, sendFails: sendFails,
} }
updater, err := NewOracleUpdater(logger, txMgr, mockFdgAddress, mockPreimageOracleAddress) updater, err := NewOracleUpdaterWithOracle(logger, txMgr, mockFdgAddress, mockPreimageOracleAddress)
require.NoError(t, err) require.NoError(t, err)
return updater, txMgr return updater, txMgr
} }
......
...@@ -49,7 +49,7 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*se ...@@ -49,7 +49,7 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*se
if err != nil { if err != nil {
return nil, fmt.Errorf("create cannon trace provider: %w", err) return nil, fmt.Errorf("create cannon trace provider: %w", err)
} }
updater, err = cannon.NewOracleUpdater(logger, txMgr, cfg.GameAddress, cfg.PreimageOracleAddress) updater, err = cannon.NewOracleUpdater(ctx, logger, txMgr, cfg.GameAddress, client)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create the cannon updater: %w", err) return nil, fmt.Errorf("failed to create the cannon updater: %w", err)
} }
...@@ -64,8 +64,7 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*se ...@@ -64,8 +64,7 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*se
} }
// newTypedService creates a new Service from a provided trace provider. // newTypedService creates a new Service from a provided trace provider.
func newTypedService(ctx context.Context, logger log.Logger, cfg *config.Config, client *ethclient.Client, provider types.TraceProvider, uploader types.OracleUpdater, txMgr txmgr.TxManager) (*service, error) { func newTypedService(ctx context.Context, logger log.Logger, cfg *config.Config, client *ethclient.Client, provider types.TraceProvider, updater types.OracleUpdater, txMgr txmgr.TxManager) (*service, error) {
contract, err := bindings.NewFaultDisputeGameCaller(cfg.GameAddress, client) contract, err := bindings.NewFaultDisputeGameCaller(cfg.GameAddress, client)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to bind the fault dispute game contract: %w", err) return nil, fmt.Errorf("failed to bind the fault dispute game contract: %w", err)
...@@ -83,7 +82,7 @@ func newTypedService(ctx context.Context, logger log.Logger, cfg *config.Config, ...@@ -83,7 +82,7 @@ func newTypedService(ctx context.Context, logger log.Logger, cfg *config.Config,
return nil, fmt.Errorf("failed to bind the fault contract: %w", err) return nil, fmt.Errorf("failed to bind the fault contract: %w", err)
} }
agent := NewAgent(loader, cfg.GameDepth, provider, responder, cfg.AgreeWithProposedOutput, gameLogger) agent := NewAgent(loader, cfg.GameDepth, provider, responder, updater, cfg.AgreeWithProposedOutput, gameLogger)
return &service{ return &service{
agent: agent, agent: agent,
......
...@@ -28,6 +28,12 @@ func NewSolver(gameDepth int, traceProvider types.TraceProvider) *Solver { ...@@ -28,6 +28,12 @@ func NewSolver(gameDepth int, traceProvider types.TraceProvider) *Solver {
} }
} }
// GetOracleData returns the oracle data for the provided claim.
// It passes through to the [TraceProvider] by finding the trace index for the claim.
func (s *Solver) GetOracleData(ctx context.Context, claim types.Claim) (*types.PreimageOracleData, error) {
return s.trace.GetOracleData(ctx, claim.TraceIndex(s.gameDepth))
}
// NextMove returns the next move to make given the current state of the game. // NextMove returns the next move to make given the current state of the game.
func (s *Solver) NextMove(ctx context.Context, claim types.Claim, agreeWithClaimLevel bool) (*types.Claim, error) { func (s *Solver) NextMove(ctx context.Context, claim types.Claim, agreeWithClaimLevel bool) (*types.Claim, error) {
if agreeWithClaimLevel { if agreeWithClaimLevel {
......
...@@ -10,7 +10,6 @@ import ( ...@@ -10,7 +10,6 @@ import (
oplog "github.com/ethereum-optimism/optimism/op-service/log" oplog "github.com/ethereum-optimism/optimism/op-service/log"
"github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
...@@ -59,11 +58,6 @@ var ( ...@@ -59,11 +58,6 @@ var (
Usage: "Correct Alphabet Trace (alphabet trace type only)", Usage: "Correct Alphabet Trace (alphabet trace type only)",
EnvVars: prefixEnvVars("ALPHABET"), EnvVars: prefixEnvVars("ALPHABET"),
} }
PreimageOracleAddressFlag = &cli.StringFlag{
Name: "preimage-oracle-address",
Usage: "Address of the Preimage Oracle contract (only required for cannon).",
EnvVars: prefixEnvVars("PREIMAGE_ORACLE_ADDRESS"),
}
CannonBinFlag = &cli.StringFlag{ CannonBinFlag = &cli.StringFlag{
Name: "cannon-bin", Name: "cannon-bin",
Usage: "Path to cannon executable to use when generating trace data (cannon trace type only)", Usage: "Path to cannon executable to use when generating trace data (cannon trace type only)",
...@@ -109,7 +103,6 @@ var requiredFlags = []cli.Flag{ ...@@ -109,7 +103,6 @@ var requiredFlags = []cli.Flag{
// optionalFlags is a list of unchecked cli flags // optionalFlags is a list of unchecked cli flags
var optionalFlags = []cli.Flag{ var optionalFlags = []cli.Flag{
AlphabetFlag, AlphabetFlag,
PreimageOracleAddressFlag,
CannonBinFlag, CannonBinFlag,
CannonServerFlag, CannonServerFlag,
CannonPreStateFlag, CannonPreStateFlag,
...@@ -137,9 +130,6 @@ func CheckRequired(ctx *cli.Context) error { ...@@ -137,9 +130,6 @@ func CheckRequired(ctx *cli.Context) error {
gameType := config.TraceType(strings.ToLower(ctx.String(TraceTypeFlag.Name))) gameType := config.TraceType(strings.ToLower(ctx.String(TraceTypeFlag.Name)))
switch gameType { switch gameType {
case config.TraceTypeCannon: case config.TraceTypeCannon:
if !ctx.IsSet(PreimageOracleAddressFlag.Name) {
return fmt.Errorf("flag %s is required", PreimageOracleAddressFlag.Name)
}
if !ctx.IsSet(CannonBinFlag.Name) { if !ctx.IsSet(CannonBinFlag.Name) {
return fmt.Errorf("flag %s is required", CannonBinFlag.Name) return fmt.Errorf("flag %s is required", CannonBinFlag.Name)
} }
...@@ -179,21 +169,11 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) { ...@@ -179,21 +169,11 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
traceTypeFlag := config.TraceType(strings.ToLower(ctx.String(TraceTypeFlag.Name))) traceTypeFlag := config.TraceType(strings.ToLower(ctx.String(TraceTypeFlag.Name)))
preimageOracleAddress := common.Address{}
preimageOracleValue := ctx.String(PreimageOracleAddressFlag.Name)
if traceTypeFlag == config.TraceTypeCannon || preimageOracleValue != "" {
preimageOracleAddress, err = opservice.ParseAddress(preimageOracleValue)
if err != nil {
return nil, err
}
}
return &config.Config{ return &config.Config{
// Required Flags // Required Flags
L1EthRpc: ctx.String(L1EthRpcFlag.Name), L1EthRpc: ctx.String(L1EthRpcFlag.Name),
TraceType: traceTypeFlag, TraceType: traceTypeFlag,
GameAddress: dgfAddress, GameAddress: dgfAddress,
PreimageOracleAddress: preimageOracleAddress,
AlphabetTrace: ctx.String(AlphabetFlag.Name), AlphabetTrace: ctx.String(AlphabetFlag.Name),
CannonBin: ctx.String(CannonBinFlag.Name), CannonBin: ctx.String(CannonBinFlag.Name),
CannonServer: ctx.String(CannonServerFlag.Name), CannonServer: ctx.String(CannonServerFlag.Name),
......
package disputegame
import (
"context"
"math/big"
"time"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer"
"github.com/ethereum-optimism/optimism/op-e2e/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/require"
)
// deployDisputeGameContracts deploys the DisputeGameFactory, AlphabetVM and FaultDisputeGame contracts
// It configures the alphabet fault game as game type 0 (faultGameType)
// If/when the dispute game factory becomes a predeployed contract this can be removed and just use the
// predeployed version
func deployDisputeGameContracts(require *require.Assertions, ctx context.Context, clock *clock.AdvancingClock, client *ethclient.Client, opts *bind.TransactOpts, gameDuration uint64) (*bindings.DisputeGameFactory, *big.Int) {
ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
defer cancel()
// Deploy the proxy
_, tx, proxy, err := bindings.DeployProxy(opts, client, deployer.TestAddress)
require.NoError(err)
proxyAddr, err := bind.WaitDeployed(ctx, client, tx)
require.NoError(err)
// Deploy the dispute game factory implementation
_, tx, _, err = bindings.DeployDisputeGameFactory(opts, client)
require.NoError(err)
factoryAddr, err := bind.WaitDeployed(ctx, client, tx)
require.NoError(err)
// Point the proxy at the implementation and create bindings going via the proxy
disputeGameFactoryAbi, err := bindings.DisputeGameFactoryMetaData.GetAbi()
require.NoError(err)
data, err := disputeGameFactoryAbi.Pack("initialize", deployer.TestAddress)
require.NoError(err)
tx, err = proxy.UpgradeToAndCall(opts, factoryAddr, data)
require.NoError(err)
_, err = utils.WaitReceiptOK(ctx, client, tx.Hash())
require.NoError(err)
factory, err := bindings.NewDisputeGameFactory(proxyAddr, client)
require.NoError(err)
// Now setup the fault dispute game type
// Start by deploying the AlphabetVM
_, tx, _, err = bindings.DeployAlphabetVM(opts, client, alphabetVMAbsolutePrestateClaim)
require.NoError(err)
alphaVMAddr, err := bind.WaitDeployed(ctx, client, tx)
require.NoError(err)
l2OutputOracle, err := bindings.NewL2OutputOracle(config.L1Deployments.L2OutputOracleProxy, client)
require.NoError(err)
// Deploy the block hash oracle
_, tx, _, err = bindings.DeployBlockOracle(opts, client)
require.NoError(err)
blockHashOracleAddr, err := bind.WaitDeployed(ctx, client, tx)
require.NoError(err)
blockHashOracle, err := bindings.NewBlockOracle(blockHashOracleAddr, client)
require.NoError(err)
// Deploy the fault dispute game implementation
_, tx, _, err = bindings.DeployFaultDisputeGame(
opts,
client,
uint8(0),
alphabetVMAbsolutePrestateClaim,
big.NewInt(alphabetGameDepth),
gameDuration,
alphaVMAddr,
config.L1Deployments.L2OutputOracleProxy,
blockHashOracleAddr,
)
require.NoError(err)
faultDisputeGameAddr, err := bind.WaitDeployed(ctx, client, tx)
require.NoError(err)
// Create a proposer transactor
secrets, err := e2eutils.DefaultMnemonicConfig.Secrets()
require.NoError(err)
chainId, err := client.ChainID(ctx)
require.NoError(err)
proposerOpts, err := bind.NewKeyedTransactorWithChainID(secrets.Proposer, chainId)
require.NoError(err)
// Propose 2 outputs
for i := uint8(0); i < 2; i++ {
nextBlockNumber, err := l2OutputOracle.NextBlockNumber(&bind.CallOpts{Pending: true, Context: ctx})
require.NoError(err)
block, err := client.BlockByNumber(ctx, big.NewInt(int64(i)))
require.NoError(err)
tx, err = l2OutputOracle.ProposeL2Output(proposerOpts, [32]byte{i + 1}, nextBlockNumber, block.Hash(), block.Number())
require.NoError(err)
_, err = utils.WaitReceiptOK(ctx, client, tx.Hash())
require.NoError(err)
}
// Set the fault game type implementation
tx, err = factory.SetImplementation(opts, faultGameType, faultDisputeGameAddr)
require.NoError(err)
_, err = utils.WaitReceiptOK(ctx, client, tx.Hash())
require.NoError(err, "wait for final transaction to be included and OK")
// Warp 15 seconds ahead for a diff in the timestamp.
clock.AdvanceTime(15 * time.Second)
// Store the current block in the oracle
tx, err = blockHashOracle.Checkpoint(opts)
require.NoError(err)
r, err := utils.WaitReceiptOK(ctx, client, tx.Hash())
require.NoError(err, "failed to store block in blockoracle")
return factory, new(big.Int).Sub(r.BlockNumber, big.NewInt(1))
}
...@@ -10,15 +10,14 @@ import ( ...@@ -10,15 +10,14 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer" "github.com/ethereum-optimism/optimism/op-chain-ops/deployer"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/fault/alphabet" "github.com/ethereum-optimism/optimism/op-challenger/fault/alphabet"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
"github.com/ethereum-optimism/optimism/op-service/client/utils" "github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
...@@ -35,48 +34,90 @@ const ( ...@@ -35,48 +34,90 @@ const (
StatusDefenderWins StatusDefenderWins
) )
var alphabetVMAbsolutePrestate = common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000060") func (s Status) String() string {
var alphabetVMAbsolutePrestateClaim = crypto.Keccak256Hash(alphabetVMAbsolutePrestate) switch s {
case StatusInProgress:
return "In Progress"
case StatusChallengerWins:
return "Challenger Wins"
case StatusDefenderWins:
return "Defender Wins"
default:
return fmt.Sprintf("Unknown status: %v", int(s))
}
}
var CorrectAlphabet = "abcdefghijklmnop" var CorrectAlphabet = "abcdefghijklmnop"
type FactoryHelper struct { type FactoryHelper struct {
t *testing.T t *testing.T
require *require.Assertions require *require.Assertions
client *ethclient.Client client *ethclient.Client
opts *bind.TransactOpts opts *bind.TransactOpts
factory *bindings.DisputeGameFactory factory *bindings.DisputeGameFactory
l1Head *big.Int blockOracle *bindings.BlockOracle
l2oo *bindings.L2OutputOracleCaller
} }
func NewFactoryHelper(t *testing.T, ctx context.Context, clock *clock.AdvancingClock, client *ethclient.Client, gameDuration uint64) *FactoryHelper { func NewFactoryHelper(t *testing.T, ctx context.Context, deployments *genesis.L1Deployments, client *ethclient.Client) *FactoryHelper {
require := require.New(t) require := require.New(t)
chainID, err := client.ChainID(ctx) chainID, err := client.ChainID(ctx)
require.NoError(err) require.NoError(err)
opts, err := bind.NewKeyedTransactorWithChainID(deployer.TestKey, chainID) opts, err := bind.NewKeyedTransactorWithChainID(deployer.TestKey, chainID)
require.NoError(err) require.NoError(err)
factory, l1Head := deployDisputeGameContracts(require, ctx, clock, client, opts, gameDuration) require.NotNil(deployments, "No deployments")
factory, err := bindings.NewDisputeGameFactory(deployments.DisputeGameFactoryProxy, client)
require.NoError(err)
blockOracle, err := bindings.NewBlockOracle(deployments.BlockOracle, client)
require.NoError(err)
l2oo, err := bindings.NewL2OutputOracleCaller(deployments.L2OutputOracleProxy, client)
require.NoError(err, "Error creating l2oo caller")
//factory, l1Head := deployDisputeGameContracts(require, ctx, clock, client, opts, gameDuration)
return &FactoryHelper{ return &FactoryHelper{
t: t, t: t,
require: require, require: require,
client: client, client: client,
opts: opts, opts: opts,
factory: factory, factory: factory,
l1Head: l1Head, blockOracle: blockOracle,
l2oo: l2oo,
} }
} }
func (h *FactoryHelper) StartAlphabetGame(ctx context.Context, claimedAlphabet string) *FaultGameHelper { func (h *FactoryHelper) StartAlphabetGame(ctx context.Context, claimedAlphabet string) *FaultGameHelper {
ctx, cancel := context.WithTimeout(ctx, 1*time.Minute) // Wait for two output proposals to be published
ctx, cancel := context.WithTimeout(ctx, 2*time.Minute)
defer cancel() defer cancel()
trace := alphabet.NewTraceProvider(claimedAlphabet, 4) err := utils.WaitFor(ctx, time.Second, func() (bool, error) {
index, err := h.l2oo.LatestOutputIndex(&bind.CallOpts{Context: ctx})
if err != nil {
h.t.Logf("Could not get latest output index: %v", err.Error())
return false, nil
}
h.t.Logf("Latest output index: %v", index)
return index.Cmp(big.NewInt(1)) >= 0, nil
})
h.require.NoError(err, "Did not get two output roots")
ctx, cancel = context.WithTimeout(ctx, 1*time.Minute)
defer cancel()
// Store the current block in the oracle
tx, err := h.blockOracle.Checkpoint(h.opts)
h.require.NoError(err)
r, err := utils.WaitReceiptOK(ctx, h.client, tx.Hash())
h.require.NoError(err, "failed to store block in blockoracle")
l1Head := new(big.Int).Sub(r.BlockNumber, big.NewInt(1))
trace := alphabet.NewTraceProvider(claimedAlphabet, alphabetGameDepth)
rootClaim, err := trace.Get(ctx, lastAlphabetTraceIndex) rootClaim, err := trace.Get(ctx, lastAlphabetTraceIndex)
h.require.NoError(err, "get root claim") h.require.NoError(err, "get root claim")
extraData := make([]byte, 64) extraData := make([]byte, 64)
binary.BigEndian.PutUint64(extraData[24:], uint64(8)) binary.BigEndian.PutUint64(extraData[24:], uint64(8))
binary.BigEndian.PutUint64(extraData[56:], h.l1Head.Uint64()) binary.BigEndian.PutUint64(extraData[56:], l1Head.Uint64())
tx, err := h.factory.Create(h.opts, faultGameType, rootClaim, extraData) tx, err = h.factory.Create(h.opts, faultGameType, rootClaim, extraData)
h.require.NoError(err, "create fault dispute game") h.require.NoError(err, "create fault dispute game")
rcpt, err := utils.WaitReceiptOK(ctx, h.client, tx.Hash()) rcpt, err := utils.WaitReceiptOK(ctx, h.client, tx.Hash())
h.require.NoError(err, "wait for create fault dispute game receipt to be OK") h.require.NoError(err, "wait for create fault dispute game receipt to be OK")
...@@ -128,6 +169,12 @@ func (g *FaultGameHelper) StartChallenger(ctx context.Context, l1Endpoint string ...@@ -128,6 +169,12 @@ func (g *FaultGameHelper) StartChallenger(ctx context.Context, l1Endpoint string
return c return c
} }
func (g *FaultGameHelper) GameDuration(ctx context.Context) time.Duration {
duration, err := g.game.GAMEDURATION(&bind.CallOpts{Context: ctx})
g.require.NoError(err, "failed to get game duration")
return time.Duration(duration) * time.Second
}
func (g *FaultGameHelper) WaitForClaimCount(ctx context.Context, count int64) { func (g *FaultGameHelper) WaitForClaimCount(ctx context.Context, count int64) {
ctx, cancel := context.WithTimeout(ctx, 1*time.Minute) ctx, cancel := context.WithTimeout(ctx, 1*time.Minute)
defer cancel() defer cancel()
...@@ -190,6 +237,7 @@ func (g *FaultGameHelper) Resolve(ctx context.Context) { ...@@ -190,6 +237,7 @@ func (g *FaultGameHelper) Resolve(ctx context.Context) {
} }
func (g *FaultGameHelper) WaitForGameStatus(ctx context.Context, expected Status) { func (g *FaultGameHelper) WaitForGameStatus(ctx context.Context, expected Status) {
g.t.Logf("Waiting for game %v to have status %v", g.addr, expected)
ctx, cancel := context.WithTimeout(ctx, 1*time.Minute) ctx, cancel := context.WithTimeout(ctx, 1*time.Minute)
defer cancel() defer cancel()
err := utils.WaitFor(ctx, 1*time.Second, func() (bool, error) { err := utils.WaitFor(ctx, 1*time.Second, func() (bool, error) {
...@@ -199,7 +247,7 @@ func (g *FaultGameHelper) WaitForGameStatus(ctx context.Context, expected Status ...@@ -199,7 +247,7 @@ func (g *FaultGameHelper) WaitForGameStatus(ctx context.Context, expected Status
if err != nil { if err != nil {
return false, fmt.Errorf("game status unavailable: %w", err) return false, fmt.Errorf("game status unavailable: %w", err)
} }
g.t.Logf("Game %v has state %v, waiting for state %v", g.addr, Status(status), expected)
return expected == Status(status), nil return expected == Status(status), nil
}) })
g.require.NoError(err, "wait for game status") g.require.NoError(err, "wait for game status")
......
...@@ -3,7 +3,6 @@ package op_e2e ...@@ -3,7 +3,6 @@ package op_e2e
import ( import (
"context" "context"
"testing" "testing"
"time"
"github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
...@@ -17,13 +16,13 @@ func TestResolveDisputeGame(t *testing.T) { ...@@ -17,13 +16,13 @@ func TestResolveDisputeGame(t *testing.T) {
InitParallel(t) InitParallel(t)
ctx := context.Background() ctx := context.Background()
sys, l1Client := startL1OnlySystem(t) sys, l1Client := startFaultDisputeSystem(t)
t.Cleanup(sys.Close) t.Cleanup(sys.Close)
gameDuration := 24 * time.Hour disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys.cfg.L1Deployments, l1Client)
disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys.TimeTravelClock, l1Client, uint64(gameDuration.Seconds()))
game := disputeGameFactory.StartAlphabetGame(ctx, "zyxwvut") game := disputeGameFactory.StartAlphabetGame(ctx, "zyxwvut")
require.NotNil(t, game) require.NotNil(t, game)
gameDuration := game.GameDuration(ctx)
game.WaitForGameStatus(ctx, disputegame.StatusInProgress) game.WaitForGameStatus(ctx, disputegame.StatusInProgress)
...@@ -115,13 +114,13 @@ func TestChallengerCompleteDisputeGame(t *testing.T) { ...@@ -115,13 +114,13 @@ func TestChallengerCompleteDisputeGame(t *testing.T) {
InitParallel(t) InitParallel(t)
ctx := context.Background() ctx := context.Background()
sys, l1Client := startL1OnlySystem(t) sys, l1Client := startFaultDisputeSystem(t)
t.Cleanup(sys.Close) t.Cleanup(sys.Close)
gameDuration := 24 * time.Hour disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys.cfg.L1Deployments, l1Client)
disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys.TimeTravelClock, l1Client, uint64(gameDuration.Seconds()))
game := disputeGameFactory.StartAlphabetGame(ctx, test.rootClaimAlphabet) game := disputeGameFactory.StartAlphabetGame(ctx, test.rootClaimAlphabet)
require.NotNil(t, game) require.NotNil(t, game)
gameDuration := game.GameDuration(ctx)
game.StartChallenger(ctx, sys.NodeEndpoint("l1"), "Defender", func(c *config.Config) { game.StartChallenger(ctx, sys.NodeEndpoint("l1"), "Defender", func(c *config.Config) {
c.TxMgrConfig.PrivateKey = e2eutils.EncodePrivKeyToString(sys.cfg.Secrets.Mallory) c.TxMgrConfig.PrivateKey = e2eutils.EncodePrivKeyToString(sys.cfg.Secrets.Mallory)
...@@ -144,13 +143,13 @@ func TestChallengerCompleteDisputeGame(t *testing.T) { ...@@ -144,13 +143,13 @@ func TestChallengerCompleteDisputeGame(t *testing.T) {
} }
} }
func startL1OnlySystem(t *testing.T) (*System, *ethclient.Client) { func startFaultDisputeSystem(t *testing.T) (*System, *ethclient.Client) {
cfg := DefaultSystemConfig(t) cfg := DefaultSystemConfig(t)
cfg.DeployConfig.L1BlockTime = 1
delete(cfg.Nodes, "verifier") delete(cfg.Nodes, "verifier")
delete(cfg.Nodes, "sequencer")
cfg.SupportL1TimeTravel = true cfg.SupportL1TimeTravel = true
cfg.DeployConfig.L2OutputOracleSubmissionInterval = 2
cfg.NonFinalizedProposals = true // Submit output proposals asap
sys, err := cfg.Start() sys, err := cfg.Start()
require.Nil(t, err, "Error starting up system") require.NoError(t, err, "Error starting up system")
return sys, sys.Clients["l1"] return sys, sys.Clients["l1"]
} }
...@@ -87,38 +87,39 @@ FaucetTest:test_nonAdmin_drip_fails() (gas: 262520) ...@@ -87,38 +87,39 @@ FaucetTest:test_nonAdmin_drip_fails() (gas: 262520)
FaucetTest:test_receive_succeeds() (gas: 17401) FaucetTest:test_receive_succeeds() (gas: 17401)
FaucetTest:test_withdraw_nonAdmin_reverts() (gas: 13145) FaucetTest:test_withdraw_nonAdmin_reverts() (gas: 13145)
FaucetTest:test_withdraw_succeeds() (gas: 78359) FaucetTest:test_withdraw_succeeds() (gas: 78359)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot1:test_resolvesCorrectly_succeeds() (gas: 498844) FaultDisputeGame_ResolvesCorrectly_CorrectRoot1:test_resolvesCorrectly_succeeds() (gas: 498906)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 505718) FaultDisputeGame_ResolvesCorrectly_CorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 505746)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 502387) FaultDisputeGame_ResolvesCorrectly_CorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 502447)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 505594) FaultDisputeGame_ResolvesCorrectly_CorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 505644)
FaultDisputeGame_ResolvesCorrectly_CorrectRoot5:test_resolvesCorrectly_succeeds() (gas: 504883) FaultDisputeGame_ResolvesCorrectly_CorrectRoot5:test_resolvesCorrectly_succeeds() (gas: 504933)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot1:test_resolvesCorrectly_succeeds() (gas: 497609) FaultDisputeGame_ResolvesCorrectly_IncorrectRoot1:test_resolvesCorrectly_succeeds() (gas: 497671)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 504483) FaultDisputeGame_ResolvesCorrectly_IncorrectRoot2:test_resolvesCorrectly_succeeds() (gas: 504511)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 501152) FaultDisputeGame_ResolvesCorrectly_IncorrectRoot3:test_resolvesCorrectly_succeeds() (gas: 501212)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 502359) FaultDisputeGame_ResolvesCorrectly_IncorrectRoot4:test_resolvesCorrectly_succeeds() (gas: 502409)
FaultDisputeGame_ResolvesCorrectly_IncorrectRoot5:test_resolvesCorrectly_succeeds() (gas: 501648) FaultDisputeGame_ResolvesCorrectly_IncorrectRoot5:test_resolvesCorrectly_succeeds() (gas: 501698)
FaultDisputeGame_Test:test_extraData_succeeds() (gas: 32354) FaultDisputeGame_Test:test_addLocalData_static_succeeds() (gas: 640503)
FaultDisputeGame_Test:test_gameData_succeeds() (gas: 32806) FaultDisputeGame_Test:test_createdAt_succeeds() (gas: 10342)
FaultDisputeGame_Test:test_gameStart_succeeds() (gas: 10388) FaultDisputeGame_Test:test_extraData_succeeds() (gas: 32377)
FaultDisputeGame_Test:test_gameType_succeeds() (gas: 8272) FaultDisputeGame_Test:test_gameData_succeeds() (gas: 32829)
FaultDisputeGame_Test:test_initialize_correctData_succeeds() (gas: 57716) FaultDisputeGame_Test:test_gameType_succeeds() (gas: 8250)
FaultDisputeGame_Test:test_initialize_firstOutput_reverts() (gas: 210532) FaultDisputeGame_Test:test_initialize_correctData_succeeds() (gas: 57694)
FaultDisputeGame_Test:test_initialize_l1HeadTooOld_reverts() (gas: 228402) FaultDisputeGame_Test:test_initialize_firstOutput_reverts() (gas: 210576)
FaultDisputeGame_Test:test_move_clockCorrectness_succeeds() (gas: 415921) FaultDisputeGame_Test:test_initialize_l1HeadTooOld_reverts() (gas: 228425)
FaultDisputeGame_Test:test_move_clockTimeExceeded_reverts() (gas: 26428) FaultDisputeGame_Test:test_move_clockCorrectness_succeeds() (gas: 415993)
FaultDisputeGame_Test:test_move_defendRoot_reverts() (gas: 13388) FaultDisputeGame_Test:test_move_clockTimeExceeded_reverts() (gas: 23219)
FaultDisputeGame_Test:test_move_duplicateClaim_reverts() (gas: 103377) FaultDisputeGame_Test:test_move_defendRoot_reverts() (gas: 13366)
FaultDisputeGame_Test:test_move_gameDepthExceeded_reverts() (gas: 408294) FaultDisputeGame_Test:test_move_duplicateClaim_reverts() (gas: 102920)
FaultDisputeGame_Test:test_move_gameDepthExceeded_reverts() (gas: 407913)
FaultDisputeGame_Test:test_move_gameNotInProgress_reverts() (gas: 11024) FaultDisputeGame_Test:test_move_gameNotInProgress_reverts() (gas: 11024)
FaultDisputeGame_Test:test_move_nonExistentParent_reverts() (gas: 24689) FaultDisputeGame_Test:test_move_nonExistentParent_reverts() (gas: 24732)
FaultDisputeGame_Test:test_move_simpleAttack_succeeds() (gas: 107300) FaultDisputeGame_Test:test_move_simpleAttack_succeeds() (gas: 107341)
FaultDisputeGame_Test:test_resolve_challengeContested_succeeds() (gas: 224869) FaultDisputeGame_Test:test_resolve_challengeContested_succeeds() (gas: 224906)
FaultDisputeGame_Test:test_resolve_notInProgress_reverts() (gas: 9664) FaultDisputeGame_Test:test_resolve_notInProgress_reverts() (gas: 9664)
FaultDisputeGame_Test:test_resolve_rootContested_succeeds() (gas: 109838) FaultDisputeGame_Test:test_resolve_rootContested_succeeds() (gas: 109856)
FaultDisputeGame_Test:test_resolve_rootUncontestedClockNotExpired_succeeds() (gas: 21443) FaultDisputeGame_Test:test_resolve_rootUncontestedClockNotExpired_succeeds() (gas: 21421)
FaultDisputeGame_Test:test_resolve_rootUncontested_succeeds() (gas: 27278) FaultDisputeGame_Test:test_resolve_rootUncontested_succeeds() (gas: 27256)
FaultDisputeGame_Test:test_resolve_teamDeathmatch_succeeds() (gas: 395607) FaultDisputeGame_Test:test_resolve_teamDeathmatch_succeeds() (gas: 395635)
FaultDisputeGame_Test:test_rootClaim_succeeds() (gas: 8253) FaultDisputeGame_Test:test_rootClaim_succeeds() (gas: 8276)
FeeVault_Test:test_constructor_succeeds() (gas: 18185) FeeVault_Test:test_constructor_succeeds() (gas: 18185)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 352139) GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 352139)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2950346) GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2950346)
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
"eip1559Elasticity": 6, "eip1559Elasticity": 6,
"l1GenesisBlockTimestamp": "0x64c811bf", "l1GenesisBlockTimestamp": "0x64c811bf",
"l2GenesisRegolithTimeOffset": "0x0", "l2GenesisRegolithTimeOffset": "0x0",
"faultGameAbsolutePrestate": 96, "faultGameAbsolutePrestate": "0x41c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98",
"faultGameMaxDepth": 4, "faultGameMaxDepth": 4,
"faultGameMaxDuration": 120 "faultGameMaxDuration": 300
} }
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
"src/L2/L2StandardBridge.sol": "0x73a4fea3dca8ac7d7ba32e38aadeb69bd344042666a40a75e8c28849f01999e5", "src/L2/L2StandardBridge.sol": "0x73a4fea3dca8ac7d7ba32e38aadeb69bd344042666a40a75e8c28849f01999e5",
"src/L2/L2ToL1MessagePasser.sol": "0xed800b600cb3f67e18a1ab10750e3934a8b3e42178f422bcacfde770a6e8e8bd", "src/L2/L2ToL1MessagePasser.sol": "0xed800b600cb3f67e18a1ab10750e3934a8b3e42178f422bcacfde770a6e8e8bd",
"src/L2/SequencerFeeVault.sol": "0xd57c143b1f042400430b991b806bf971628e6980406c751e82d19ae80eeb4e8d", "src/L2/SequencerFeeVault.sol": "0xd57c143b1f042400430b991b806bf971628e6980406c751e82d19ae80eeb4e8d",
"src/dispute/FaultDisputeGame.sol": "0x01b3770e4d056550e71b4b9e9ada5401de98668d0a1e0ff336ed8f73a0127e99", "src/dispute/FaultDisputeGame.sol": "0x2a7f367443752f841d734f339a596c4ad93e16f7df0230f1cdd5e6f0b4b58368",
"src/legacy/DeployerWhitelist.sol": "0x5e80f7b13ef73f06c63bd9b118a49da1ff06a5c0fcf8067b5a3365d731c23765", "src/legacy/DeployerWhitelist.sol": "0x5e80f7b13ef73f06c63bd9b118a49da1ff06a5c0fcf8067b5a3365d731c23765",
"src/legacy/L1BlockNumber.sol": "0x84cc587148de5920dfcd19da44d28e769f0e4d08ca2bcc93f18aa78c6cc2ebe6", "src/legacy/L1BlockNumber.sol": "0x84cc587148de5920dfcd19da44d28e769f0e4d08ca2bcc93f18aa78c6cc2ebe6",
"src/legacy/LegacyMessagePasser.sol": "0x2692b50b227e5f75a53439c0cf303498edfd4fc087555b3fc9bc4bceb518229b", "src/legacy/LegacyMessagePasser.sol": "0x2692b50b227e5f75a53439c0cf303498edfd4fc087555b3fc9bc4bceb518229b",
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity ^0.8.15; pragma solidity ^0.8.15;
import "../libraries/DisputeTypes.sol";
import "../libraries/DisputeErrors.sol";
import { ClonesWithImmutableArgs } from "@cwia/ClonesWithImmutableArgs.sol"; import { ClonesWithImmutableArgs } from "@cwia/ClonesWithImmutableArgs.sol";
import { import {
OwnableUpgradeable OwnableUpgradeable
} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { Semver } from "../universal/Semver.sol"; import { Semver } from "src/universal/Semver.sol";
import { IDisputeGame } from "./interfaces/IDisputeGame.sol"; import { IDisputeGame } from "./interfaces/IDisputeGame.sol";
import { IDisputeGameFactory } from "./interfaces/IDisputeGameFactory.sol"; import { IDisputeGameFactory } from "./interfaces/IDisputeGameFactory.sol";
import "src/libraries/DisputeTypes.sol";
import "src/libraries/DisputeErrors.sol";
/// @title DisputeGameFactory /// @title DisputeGameFactory
/// @notice A factory contract for creating `IDisputeGame` contracts. All created dispute games /// @notice A factory contract for creating `IDisputeGame` contracts. All created dispute games
/// are stored in both a mapping and an append only array. The timestamp of the creation /// are stored in both a mapping and an append only array. The timestamp of the creation
...@@ -37,7 +37,7 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, Semver { ...@@ -37,7 +37,7 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, Semver {
GameId[] internal _disputeGameList; GameId[] internal _disputeGameList;
/// @notice constructs a new DisputeGameFactory contract. /// @notice constructs a new DisputeGameFactory contract.
constructor() OwnableUpgradeable() Semver(0, 0, 2) { constructor() OwnableUpgradeable() Semver(0, 0, 3) {
initialize(address(0)); initialize(address(0));
} }
...@@ -88,9 +88,7 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, Semver { ...@@ -88,9 +88,7 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, Semver {
IDisputeGame impl = gameImpls[gameType]; IDisputeGame impl = gameImpls[gameType];
// If there is no implementation to clone for the given `GameType`, revert. // If there is no implementation to clone for the given `GameType`, revert.
if (address(impl) == address(0)) { if (address(impl) == address(0)) revert NoImplementation(gameType);
revert NoImplementation(gameType);
}
// Clone the implementation contract and initialize it with the given parameters. // Clone the implementation contract and initialize it with the given parameters.
proxy = IDisputeGame(address(impl).clone(abi.encodePacked(rootClaim, extraData))); proxy = IDisputeGame(address(impl).clone(abi.encodePacked(rootClaim, extraData)));
...@@ -100,9 +98,7 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, Semver { ...@@ -100,9 +98,7 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, Semver {
Hash uuid = getGameUUID(gameType, rootClaim, extraData); Hash uuid = getGameUUID(gameType, rootClaim, extraData);
// If a dispute game with the same UUID already exists, revert. // If a dispute game with the same UUID already exists, revert.
if (GameId.unwrap(_disputeGames[uuid]) != bytes32(0)) { if (GameId.unwrap(_disputeGames[uuid]) != bytes32(0)) revert GameAlreadyExists(uuid);
revert GameAlreadyExists(uuid);
}
GameId slot = _packSlot(address(proxy), block.timestamp); GameId slot = _packSlot(address(proxy), block.timestamp);
......
...@@ -6,18 +6,18 @@ import { IFaultDisputeGame } from "./interfaces/IFaultDisputeGame.sol"; ...@@ -6,18 +6,18 @@ import { IFaultDisputeGame } from "./interfaces/IFaultDisputeGame.sol";
import { IInitializable } from "./interfaces/IInitializable.sol"; import { IInitializable } from "./interfaces/IInitializable.sol";
import { IBondManager } from "./interfaces/IBondManager.sol"; import { IBondManager } from "./interfaces/IBondManager.sol";
import { IBigStepper, IPreimageOracle } from "./interfaces/IBigStepper.sol"; import { IBigStepper, IPreimageOracle } from "./interfaces/IBigStepper.sol";
import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; import { L2OutputOracle } from "src/L1/L2OutputOracle.sol";
import { BlockOracle } from "./BlockOracle.sol"; import { BlockOracle } from "./BlockOracle.sol";
import { Clone } from "../libraries/Clone.sol"; import { Clone } from "src/libraries/Clone.sol";
import { Types } from "../libraries/Types.sol"; import { Types } from "src/libraries/Types.sol";
import { Semver } from "../universal/Semver.sol"; import { Semver } from "src/universal/Semver.sol";
import { LibHashing } from "./lib/LibHashing.sol"; import { LibHashing } from "./lib/LibHashing.sol";
import { LibPosition } from "./lib/LibPosition.sol"; import { LibPosition } from "./lib/LibPosition.sol";
import { LibClock } from "./lib/LibClock.sol"; import { LibClock } from "./lib/LibClock.sol";
import "../libraries/DisputeTypes.sol"; import "src/libraries/DisputeTypes.sol";
import "../libraries/DisputeErrors.sol"; import "src/libraries/DisputeErrors.sol";
/// @title FaultDisputeGame /// @title FaultDisputeGame
/// @notice An implementation of the `IFaultDisputeGame` interface. /// @notice An implementation of the `IFaultDisputeGame` interface.
...@@ -43,7 +43,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -43,7 +43,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
L2OutputOracle public immutable L2_OUTPUT_ORACLE; L2OutputOracle public immutable L2_OUTPUT_ORACLE;
/// @notice The block hash oracle, used for loading block hashes further back /// @notice The block hash oracle, used for loading block hashes further back
/// than the `BLOCKHASH` opcode allows as well as their estimated timestamps. /// than the `BLOCKHASH` opcode allows as well as their child's timestamp.
BlockOracle public immutable BLOCK_ORACLE; BlockOracle public immutable BLOCK_ORACLE;
/// @notice The game type ID /// @notice The game type ID
...@@ -53,7 +53,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -53,7 +53,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
Position internal constant ROOT_POSITION = Position.wrap(1); Position internal constant ROOT_POSITION = Position.wrap(1);
/// @notice The starting timestamp of the game /// @notice The starting timestamp of the game
Timestamp public gameStart; Timestamp public createdAt;
/// @inheritdoc IDisputeGame /// @inheritdoc IDisputeGame
GameStatus public status; GameStatus public status;
...@@ -85,7 +85,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -85,7 +85,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
/// @param _blockOracle The block oracle, used for loading block hashes further back /// @param _blockOracle The block oracle, used for loading block hashes further back
/// than the `BLOCKHASH` opcode allows as well as their estimated /// than the `BLOCKHASH` opcode allows as well as their estimated
/// timestamps. /// timestamps.
/// @custom:semver 0.0.6 /// @custom:semver 0.0.7
constructor( constructor(
GameType _gameType, GameType _gameType,
Claim _absolutePrestate, Claim _absolutePrestate,
...@@ -94,7 +94,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -94,7 +94,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
IBigStepper _vm, IBigStepper _vm,
L2OutputOracle _l2oo, L2OutputOracle _l2oo,
BlockOracle _blockOracle BlockOracle _blockOracle
) Semver(0, 0, 6) { ) Semver(0, 0, 7) {
GAME_TYPE = _gameType; GAME_TYPE = _gameType;
ABSOLUTE_PRESTATE = _absolutePrestate; ABSOLUTE_PRESTATE = _absolutePrestate;
MAX_GAME_DEPTH = _maxGameDepth; MAX_GAME_DEPTH = _maxGameDepth;
...@@ -133,18 +133,16 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -133,18 +133,16 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
Claim preStateClaim; Claim preStateClaim;
ClaimData storage postState; ClaimData storage postState;
if (_isAttack) { if (_isAttack) {
if (stepPos.indexAtDepth() == 0) { // If the step position's index at depth is 0, the prestate is the absolute
// If the step position's index at depth is 0, the prestate is the absolute // prestate.
// prestate. // If the step is an attack at a trace index > 0, the prestate exists elsewhere in
preStateClaim = ABSOLUTE_PRESTATE; // the game state.
} else { preStateClaim = stepPos.indexAtDepth() == 0
// If the step is an attack at a trace index > 0, the prestate exists elsewhere in ? ABSOLUTE_PRESTATE
// the game state. : findTraceAncestor(
preStateClaim = findTraceAncestor(
Position.wrap(Position.unwrap(parentPos) - 1), Position.wrap(Position.unwrap(parentPos) - 1),
parent.parentIndex parent.parentIndex
).claim; ).claim;
}
// For all attacks, the poststate is the parent claim. // For all attacks, the poststate is the parent claim.
postState = parent; postState = parent;
...@@ -203,9 +201,6 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -203,9 +201,6 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
// Get the parent. If it does not exist, the call will revert with OOB. // Get the parent. If it does not exist, the call will revert with OOB.
ClaimData memory parent = claimData[_challengeIndex]; ClaimData memory parent = claimData[_challengeIndex];
// Set the parent claim as countered.
claimData[_challengeIndex].countered = true;
// Compute the position that the claim commits to. Because the parent's position is already // Compute the position that the claim commits to. Because the parent's position is already
// known, we can compute the next position by moving left or right depending on whether // known, we can compute the next position by moving left or right depending on whether
// or not the move is an attack or defense. // or not the move is an attack or defense.
...@@ -264,6 +259,9 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -264,6 +259,9 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
}) })
); );
// Set the parent claim as countered.
claimData[_challengeIndex].countered = true;
// Emit the appropriate event for the attack or defense. // Emit the appropriate event for the attack or defense.
emit Move(_challengeIndex, _claim, msg.sender); emit Move(_challengeIndex, _claim, msg.sender);
} }
...@@ -284,42 +282,55 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -284,42 +282,55 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress(); if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress();
IPreimageOracle oracle = VM.oracle(); IPreimageOracle oracle = VM.oracle();
if (_ident == 1) { bytes4 loadLocalDataSelector = IPreimageOracle.loadLocalData.selector;
// Load the L1 head hash into the game's local context in the preimage oracle. assembly {
oracle.loadLocalData(_ident, Hash.unwrap(l1Head), 32, _partOffset); // Store the `loadLocalData(uint256,bytes32,uint256,uint256)` selector
} else if (_ident == 2) { mstore(0x1C, loadLocalDataSelector)
// Load the starting or disputed output root into the game's local context in the // Store the `_ident` argument
// preimage oracle. mstore(0x20, _ident)
oracle.loadLocalData( // Store the data to load
_ident, let data
Hash.unwrap(proposals.starting.outputRoot), switch _ident
32, case 1 {
_partOffset // Load the L1 head hash
); data := sload(l1Head.slot)
} else if (_ident == 3) { }
// Load the starting or disputed output root into the game's local context in the case 2 {
// preimage oracle. // Load the starting proposal's output root.
oracle.loadLocalData( data := sload(add(proposals.slot, 0x01))
_ident, }
Hash.unwrap(proposals.disputed.outputRoot), case 3 {
32, // Load the disputed proposal's output root
_partOffset data := sload(add(proposals.slot, 0x03))
); }
} else if (_ident == 4) { case 4 {
// Load the starting l2 block number into the game's local context in the preimage // Load the starting proposal's L2 block number as a big-endian uint64 in the
// oracle. The L2 block number is stored as a big-endian uint64 in the upper 8 bytes // high order 8 bytes of the word.
// of the passed word. data := shl(0xC0, shr(0x80, sload(proposals.slot)))
oracle.loadLocalData( }
_ident, case 5 {
bytes32(uint256(proposals.starting.l2BlockNumber) << 192), // Load the chain ID as a big-endian uint64 in the high order 8 bytes of the word.
8, data := shl(0xC0, chainid())
_partOffset }
); default {
} else if (_ident == 5) { // Store the `InvalidLocalIdent()` selector.
// Load the chain ID into the game's local context in the preimage oracle. mstore(0x00, 0xff137e65)
// The chain ID is stored as a big-endian uint64 in the upper 8 bytes of the // Revert with `InvalidLocalIdent()`
// passed word. revert(0x1C, 0x04)
oracle.loadLocalData(_ident, bytes32(block.chainid << 192), 8, _partOffset); }
mstore(0x40, data)
// Store the size of the data to load
// _ident > 3 ? 8 : 32
mstore(0x60, shl(sub(0x05, shl(0x01, gt(_ident, 0x03))), 0x01))
// Store the part offset of the data
mstore(0x80, _partOffset)
// Attempt to add the local data to the preimage oracle and bubble up the revert
// if it fails.
if iszero(call(gas(), oracle, 0x00, 0x1C, 0x84, 0x00, 0x00)) {
returndatacopy(0x00, 0x00, returndatasize())
revert(0x00, returndatasize())
}
} }
} }
...@@ -342,11 +353,6 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -342,11 +353,6 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
gameType_ = GAME_TYPE; gameType_ = GAME_TYPE;
} }
/// @inheritdoc IDisputeGame
function createdAt() external view returns (Timestamp createdAt_) {
createdAt_ = gameStart;
}
/// @inheritdoc IDisputeGame /// @inheritdoc IDisputeGame
function resolve() external returns (GameStatus status_) { function resolve() external returns (GameStatus status_) {
// INVARIANT: Resolution cannot occur unless the game is currently in progress. // INVARIANT: Resolution cannot occur unless the game is currently in progress.
...@@ -451,11 +457,11 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -451,11 +457,11 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
function initialize() external { function initialize() external {
// SAFETY: Any revert in this function will bubble up to the DisputeGameFactory and // SAFETY: Any revert in this function will bubble up to the DisputeGameFactory and
// prevent the game from being created. // prevent the game from being created.
// Implicit assumptions:
// - The `gameStatus` state variable defaults to 0, which is `GameStatus.IN_PROGRESS`
// Set the game start // Set the game's starting timestamp
gameStart = Timestamp.wrap(uint64(block.timestamp)); createdAt = Timestamp.wrap(uint64(block.timestamp));
// Set the game status
status = GameStatus.IN_PROGRESS;
// Set the root claim // Set the root claim
claimData.push( claimData.push(
...@@ -535,7 +541,8 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver { ...@@ -535,7 +541,8 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
/// @param _pos The position to find the trace ancestor claim of. /// @param _pos The position to find the trace ancestor claim of.
/// @param _start The index to start searching from. /// @param _start The index to start searching from.
/// @return ancestor_ The ancestor claim that commits to the same trace index as `_pos`. /// @return ancestor_ The ancestor claim that commits to the same trace index as `_pos`.
// TODO: Can we form a relationship between the trace path and the position to avoid looping? // TODO(clabby): Can we form a relationship between the trace path and the position to avoid
// looping?
function findTraceAncestor(Position _pos, uint256 _start) function findTraceAncestor(Position _pos, uint256 _start)
internal internal
view view
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity ^0.8.15; pragma solidity ^0.8.15;
import { IPreimageOracle } from "../../cannon/interfaces/IPreimageOracle.sol"; import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol";
/// @title IBigStepper /// @title IBigStepper
/// @notice An interface for a contract with a state transition function that /// @notice An interface for a contract with a state transition function that
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity ^0.8.15; pragma solidity ^0.8.15;
import "../../libraries/DisputeTypes.sol";
import { IBondManager } from "./IBondManager.sol"; import { IBondManager } from "./IBondManager.sol";
import { IInitializable } from "./IInitializable.sol"; import { IInitializable } from "./IInitializable.sol";
import "src/libraries/DisputeTypes.sol";
/// @title IDisputeGame /// @title IDisputeGame
/// @notice The generic interface for a DisputeGame contract. /// @notice The generic interface for a DisputeGame contract.
interface IDisputeGame is IInitializable { interface IDisputeGame is IInitializable {
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity ^0.8.15; pragma solidity ^0.8.15;
import "../../libraries/DisputeTypes.sol";
import { IDisputeGame } from "./IDisputeGame.sol"; import { IDisputeGame } from "./IDisputeGame.sol";
import "src/libraries/DisputeTypes.sol";
/// @title IDisputeGameFactory /// @title IDisputeGameFactory
/// @notice The interface for a DisputeGameFactory contract. /// @notice The interface for a DisputeGameFactory contract.
interface IDisputeGameFactory { interface IDisputeGameFactory {
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity ^0.8.15; pragma solidity ^0.8.15;
import "../../libraries/DisputeTypes.sol";
import { IDisputeGame } from "./IDisputeGame.sol"; import { IDisputeGame } from "./IDisputeGame.sol";
import "src/libraries/DisputeTypes.sol";
/// @title IFaultDisputeGame /// @title IFaultDisputeGame
/// @notice The interface for a fault proof backed dispute game. /// @notice The interface for a fault proof backed dispute game.
interface IFaultDisputeGame is IDisputeGame { interface IFaultDisputeGame is IDisputeGame {
/// @notice The `ClaimData` struct represents the data associated with a Claim. /// @notice The `ClaimData` struct represents the data associated with a Claim.
/// @dev TODO: Add bond ID information. /// @dev TODO(clabby): Add bond ID information.
struct ClaimData { struct ClaimData {
uint32 parentIndex; uint32 parentIndex;
bool countered; bool countered;
...@@ -26,7 +26,14 @@ interface IFaultDisputeGame is IDisputeGame { ...@@ -26,7 +26,14 @@ interface IFaultDisputeGame is IDisputeGame {
Hash outputRoot; Hash outputRoot;
} }
/// @notice A container for two consecutive `OutputProposal`s. /// @notice A container for two consecutive `OutputProposal`s, used to store the starting
/// and disputed output proposals for a given dispute game. The starting output
/// proposal will be used to determine where the off chain agents should begin
/// running their fault proof program, and the disputed output proposal will be
/// fed into the program and treated as disputed state. The program's exit code
/// expresses its opinion on the validity of the state transition from the starting,
/// trusted output proposal to the disputed output proposal, and ultimately resolves
/// the dispute.
struct OutputProposals { struct OutputProposals {
OutputProposal starting; OutputProposal starting;
OutputProposal disputed; OutputProposal disputed;
...@@ -39,27 +46,26 @@ interface IFaultDisputeGame is IDisputeGame { ...@@ -39,27 +46,26 @@ interface IFaultDisputeGame is IDisputeGame {
event Move(uint256 indexed parentIndex, Claim indexed claim, address indexed claimant); event Move(uint256 indexed parentIndex, Claim indexed claim, address indexed claimant);
/// @notice Attack a disagreed upon `Claim`. /// @notice Attack a disagreed upon `Claim`.
/// @param _parentIndex Index of the `Claim` to attack in `claimData`. /// @param _parentIndex Index of the `Claim` to attack in the `claimData` array.
/// @param _claim The `Claim` at the relative attack position. /// @param _claim The `Claim` at the relative attack position.
function attack(uint256 _parentIndex, Claim _claim) external payable; function attack(uint256 _parentIndex, Claim _claim) external payable;
/// @notice Defend an agreed upon `Claim`. /// @notice Defend an agreed upon `Claim`.
/// @param _parentIndex Index of the claim to defend in `claimData`. /// @param _parentIndex Index of the claim to defend in the `claimData` array.
/// @param _claim The `Claim` at the relative defense position. /// @param _claim The `Claim` at the relative defense position.
function defend(uint256 _parentIndex, Claim _claim) external payable; function defend(uint256 _parentIndex, Claim _claim) external payable;
/// @notice Perform the final step via an on-chain fault proof processor /// @notice Perform an instruction step via an on-chain fault proof processor.
/// @dev This function should point to a fault proof processor in order to execute /// @dev This function should point to a fault proof processor in order to execute
/// a step in the fault proof program on-chain. The interface of the fault proof /// a step in the fault proof program on-chain. The interface of the fault proof
/// processor contract should be generic enough such that we can use different /// processor contract should adhere to the `IBigStepper` interface.
/// fault proof VMs (MIPS, RiscV5, etc.)
/// @param _claimIndex The index of the challenged claim within `claimData`. /// @param _claimIndex The index of the challenged claim within `claimData`.
/// @param _isAttack Whether or not the step is an attack or a defense. /// @param _isAttack Whether or not the step is an attack or a defense.
/// @param _stateData The stateData of the step is the preimage of the claim at the given /// @param _stateData The stateData of the step is the preimage of the claim at the given
/// prestate, which is at `_stateIndex` if the move is an attack and `_claimIndex` if /// prestate, which is at `_stateIndex` if the move is an attack and `_claimIndex` if
/// the move is a defense. If the step is an attack on the first instruction, it is /// the move is a defense. If the step is an attack on the first instruction, it is
/// the absolute prestate of the fault proof VM. /// the absolute prestate of the fault proof VM.
/// @param _proof Proof to access memory leaf nodes in the VM. /// @param _proof Proof to access memory nodes in the VM's merkle state tree.
function step( function step(
uint256 _claimIndex, uint256 _claimIndex,
bool _isAttack, bool _isAttack,
...@@ -72,11 +78,13 @@ interface IFaultDisputeGame is IDisputeGame { ...@@ -72,11 +78,13 @@ interface IFaultDisputeGame is IDisputeGame {
/// @param _partOffset The offset of the data to post. /// @param _partOffset The offset of the data to post.
function addLocalData(uint256 _ident, uint256 _partOffset) external; function addLocalData(uint256 _ident, uint256 _partOffset) external;
/// @notice Returns the L1 block hash at the time of the game's creation. /// @notice An L1 block hash that contains the disputed output root, fetched from the
/// `BlockOracle` and verified by referencing the timestamp associated with the
/// first L2 Output Proposal in the `L2OutputOracle` that contains the disputed
/// L2 block number.
function l1Head() external view returns (Hash l1Head_); function l1Head() external view returns (Hash l1Head_);
/// @notice The l2BlockNumber that the `rootClaim` commits to. The trace being bisected within /// @notice The l2BlockNumber of the disputed output root in the `L2OutputOracle`.
/// the game is from `l2BlockNumber - 1` -> `l2BlockNumber`.
function l2BlockNumber() external view returns (uint256 l2BlockNumber_); function l2BlockNumber() external view returns (uint256 l2BlockNumber_);
/// @notice The l1BlockNumber that Cannon was ran from to generate the root claim. /// @notice The l1BlockNumber that Cannon was ran from to generate the root claim.
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity ^0.8.15; pragma solidity ^0.8.15;
import "../../libraries/DisputeTypes.sol"; import "src/libraries/DisputeTypes.sol";
/// @title LibClock /// @title LibClock
/// @notice This library contains helper functions for working with the `Clock` type. /// @notice This library contains helper functions for working with the `Clock` type.
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity ^0.8.15; pragma solidity ^0.8.15;
import "../../libraries/DisputeTypes.sol"; import "src/libraries/DisputeTypes.sol";
/// @title Hashing /// @title Hashing
/// @notice This library contains all of the hashing utilities used in the Cannon contracts. /// @notice This library contains all of the hashing utilities used in the Cannon contracts.
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity ^0.8.15; pragma solidity ^0.8.15;
import "../../libraries/DisputeTypes.sol"; import "src/libraries/DisputeTypes.sol";
/// @title LibPosition /// @title LibPosition
/// @notice This library contains helper functions for working with the `Position` type. /// @notice This library contains helper functions for working with the `Position` type.
......
...@@ -58,6 +58,9 @@ error ValidStep(); ...@@ -58,6 +58,9 @@ error ValidStep();
/// not contain the disputed output root. /// not contain the disputed output root.
error L1HeadTooOld(); error L1HeadTooOld();
/// @notice Thrown when an invalid local identifier is passed to the `addLocalData` function.
error InvalidLocalIdent();
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// `AttestationDisputeGame` Errors // // `AttestationDisputeGame` Errors //
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
......
...@@ -8,6 +8,8 @@ import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; ...@@ -8,6 +8,8 @@ import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol";
import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol";
import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; import { L2OutputOracle } from "src/L1/L2OutputOracle.sol";
import { BlockOracle } from "src/dispute/BlockOracle.sol"; import { BlockOracle } from "src/dispute/BlockOracle.sol";
import { PreimageOracle } from "src/cannon/PreimageOracle.sol";
import { PreimageKeyLib } from "src/cannon/PreimageKeyLib.sol";
import "src/libraries/DisputeTypes.sol"; import "src/libraries/DisputeTypes.sol";
import "src/libraries/DisputeErrors.sol"; import "src/libraries/DisputeErrors.sol";
...@@ -38,12 +40,7 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init { ...@@ -38,12 +40,7 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init {
// Propose 2 mock outputs // Propose 2 mock outputs
vm.startPrank(oracle.PROPOSER()); vm.startPrank(oracle.PROPOSER());
for (uint256 i; i < 2; i++) { for (uint256 i; i < 2; i++) {
oracle.proposeL2Output( oracle.proposeL2Output(bytes32(i + 1), oracle.nextBlockNumber(), blockhash(i), i);
bytes32(i + 1),
oracle.nextBlockNumber(),
blockhash(i),
i
);
// Advance 1 block // Advance 1 block
vm.roll(block.number + 1); vm.roll(block.number + 1);
...@@ -102,9 +99,9 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -102,9 +99,9 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
assertEq(gameProxy.extraData(), extraData); assertEq(gameProxy.extraData(), extraData);
} }
/// @dev Tests that the game's status is set correctly. /// @dev Tests that the game's starting timestamp is set correctly.
function test_gameStart_succeeds() public { function test_createdAt_succeeds() public {
assertEq(Timestamp.unwrap(gameProxy.gameStart()), block.timestamp); assertEq(Timestamp.unwrap(gameProxy.createdAt()), block.timestamp);
} }
/// @dev Tests that the game's type is set correctly. /// @dev Tests that the game's type is set correctly.
...@@ -129,7 +126,11 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -129,7 +126,11 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// contain the disputed L2 output root. /// contain the disputed L2 output root.
function test_initialize_l1HeadTooOld_reverts() public { function test_initialize_l1HeadTooOld_reverts() public {
// Store a mock block hash for the genesis block. The timestamp will default to 0. // Store a mock block hash for the genesis block. The timestamp will default to 0.
vm.store(address(gameImpl.BLOCK_ORACLE()), keccak256(abi.encode(0, 0)), bytes32(uint256(1))); vm.store(
address(gameImpl.BLOCK_ORACLE()),
keccak256(abi.encode(0, 0)),
bytes32(uint256(1))
);
bytes memory _extraData = abi.encode(oracle.SUBMISSION_INTERVAL() * 2, 0); bytes memory _extraData = abi.encode(oracle.SUBMISSION_INTERVAL() * 2, 0);
vm.expectRevert(L1HeadTooOld.selector); vm.expectRevert(L1HeadTooOld.selector);
...@@ -149,7 +150,10 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -149,7 +150,10 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// @dev Tests that the game is initialized with the correct data. /// @dev Tests that the game is initialized with the correct data.
function test_initialize_correctData_succeeds() public { function test_initialize_correctData_succeeds() public {
// Starting // Starting
(FaultDisputeGame.OutputProposal memory startingProp, FaultDisputeGame.OutputProposal memory disputedProp) = gameProxy.proposals(); (
FaultDisputeGame.OutputProposal memory startingProp,
FaultDisputeGame.OutputProposal memory disputedProp
) = gameProxy.proposals();
Types.OutputProposal memory starting = oracle.getL2Output(startingProp.index); Types.OutputProposal memory starting = oracle.getL2Output(startingProp.index);
assertEq(startingProp.index, 0); assertEq(startingProp.index, 0);
assertEq(startingProp.l2BlockNumber, starting.l2BlockNumber); assertEq(startingProp.l2BlockNumber, starting.l2BlockNumber);
...@@ -421,6 +425,59 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { ...@@ -421,6 +425,59 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
assertEq(uint8(status), uint8(GameStatus.CHALLENGER_WINS)); assertEq(uint8(status), uint8(GameStatus.CHALLENGER_WINS));
assertEq(uint8(gameProxy.status()), uint8(GameStatus.CHALLENGER_WINS)); assertEq(uint8(gameProxy.status()), uint8(GameStatus.CHALLENGER_WINS));
} }
/// @dev Tests that adding local data with an out of bounds identifier reverts.
function testFuzz_addLocalData_oob_reverts(uint256 _ident) public {
// [1, 5] are valid local data identifiers.
if (_ident <= 5) _ident = 0;
vm.expectRevert(InvalidLocalIdent.selector);
gameProxy.addLocalData(_ident, 0);
}
/// @dev Tests that local data is loaded into the preimage oracle correctly.
function test_addLocalData_static_succeeds() public {
IPreimageOracle oracle = IPreimageOracle(address(gameProxy.VM().oracle()));
(
FaultDisputeGame.OutputProposal memory starting,
FaultDisputeGame.OutputProposal memory disputed
) = gameProxy.proposals();
bytes32[5] memory data = [
Hash.unwrap(gameProxy.l1Head()),
Hash.unwrap(starting.outputRoot),
Hash.unwrap(disputed.outputRoot),
bytes32(uint256(starting.l2BlockNumber) << 0xC0),
bytes32(block.chainid << 0xC0)
];
for (uint256 i = 1; i <= 5; i++) {
uint256 expectedLen = i > 3 ? 8 : 32;
gameProxy.addLocalData(i, 0);
bytes32 key = _getKey(i);
(bytes32 dat, uint256 datLen) = oracle.readPreimage(key, 0);
assertEq(dat >> 0xC0, bytes32(expectedLen));
// Account for the length prefix if i > 3 (the data stored
// at identifiers i <= 3 are 32 bytes long, so the expected
// length is already correct. If i > 3, the data is only 8
// bytes long, so the length prefix + the data is 16 bytes
// total.)
assertEq(datLen, expectedLen + (i > 3 ? 8 : 0));
gameProxy.addLocalData(i, 8);
key = _getKey(i);
(dat, datLen) = oracle.readPreimage(key, 8);
assertEq(dat, data[i - 1]);
assertEq(datLen, expectedLen);
}
}
/// @dev Helper to get the localized key for an identifier in the context of the game proxy.
function _getKey(uint256 _ident) internal view returns (bytes32) {
bytes32 h = keccak256(abi.encode(_ident | (1 << 248), address(gameProxy)));
return bytes32((uint256(h) & ~uint256(0xFF << 248)) | (1 << 248));
}
} }
/// @notice A generic game player actor with a configurable trace. /// @notice A generic game player actor with a configurable trace.
...@@ -963,7 +1020,7 @@ contract AlphabetVM is IBigStepper { ...@@ -963,7 +1020,7 @@ contract AlphabetVM is IBigStepper {
constructor(Claim _absolutePrestate) { constructor(Claim _absolutePrestate) {
ABSOLUTE_PRESTATE = _absolutePrestate; ABSOLUTE_PRESTATE = _absolutePrestate;
oracle = IPreimageOracle(deployNoop()); oracle = new PreimageOracle();
} }
/// @inheritdoc IBigStepper /// @inheritdoc IBigStepper
...@@ -987,16 +1044,3 @@ contract AlphabetVM is IBigStepper { ...@@ -987,16 +1044,3 @@ contract AlphabetVM is IBigStepper {
postState_ = keccak256(abi.encode(traceIndex, claim + 1)); postState_ = keccak256(abi.encode(traceIndex, claim + 1));
} }
} }
////////////////////////////////////////////////////////////////
// HELPERS //
////////////////////////////////////////////////////////////////
/// @notice Deploys a noop contract.
function deployNoop() returns (address noop_) {
assembly {
mstore(0x00, 0x60016000F3)
let size := 5
noop_ := create(0, sub(0x20, size), size)
}
}
# @eth-optimism/fee-estimation # @eth-optimism/fee-estimation
## 0.15.2
### Patch Changes
- [#6609](https://github.com/ethereum-optimism/optimism/pull/6609) [`0e83c4452`](https://github.com/ethereum-optimism/optimism/commit/0e83c44522e1a13e4d5c1395fd4dc9dbae8be08d) Thanks [@roninjin10](https://github.com/roninjin10)! - Fixed bug with 'estimateFees' not taking into account the l2 gas price
## 0.15.1 ## 0.15.1
### Patch Changes ### Patch Changes
......
...@@ -37,11 +37,9 @@ yarn add @eth-optimism/fee-estimation ...@@ -37,11 +37,9 @@ yarn add @eth-optimism/fee-estimation
### Basic Usage ### Basic Usage
```ts ```ts
import { import { estimateFees } from '@eth-optimism/fee-estimation'
estimateFees, import { optimistABI } from '@eth-optimism/contracts-ts'
} from '@eth-optimism/fee-estimation' import { viemClient } from './viem-client'
import {optimistABI} from '@eth-optimism/contracts-ts'
import {viemClient} from './viem-client'
const optimistOwnerAddress = const optimistOwnerAddress =
'0x77194aa25a06f932c10c0f25090f3046af2c85a6' as const '0x77194aa25a06f932c10c0f25090f3046af2c85a6' as const
......
{ {
"name": "@eth-optimism/fee-estimation", "name": "@eth-optimism/fee-estimation",
"version": "0.15.1", "version": "0.15.2",
"description": "Lightweight library for doing OP-Chain gas estimation", "description": "Lightweight library for doing OP-Chain gas estimation",
"license": "MIT", "license": "MIT",
"repository": { "repository": {
......
...@@ -24,6 +24,19 @@ import { ...@@ -24,6 +24,19 @@ import {
} from '@eth-optimism/contracts-ts' } from '@eth-optimism/contracts-ts'
import { parseEther, parseGwei } from 'viem' import { parseEther, parseGwei } from 'viem'
vi.mock('viem', async () => {
const _viem = (await vi.importActual('viem')) as any
return {
..._viem,
// no way to get historical gas price
createPublicClient: (...args: [any]) => {
const client = _viem.createPublicClient(...args)
client.getGasPrice = async () => parseGwei('0.00000042')
return client
},
}
})
// using this optimist https://optimistic.etherscan.io/tx/0xaa291efba7ea40b0742e5ff84a1e7831a2eb6c2fc35001fa03ba80fd3b609dc9 // using this optimist https://optimistic.etherscan.io/tx/0xaa291efba7ea40b0742e5ff84a1e7831a2eb6c2fc35001fa03ba80fd3b609dc9
const blockNumber = BigInt(107028270) const blockNumber = BigInt(107028270)
const optimistOwnerAddress = const optimistOwnerAddress =
...@@ -95,44 +108,44 @@ beforeEach(() => { ...@@ -95,44 +108,44 @@ beforeEach(() => {
test('estimateFees should return correct fees', async () => { test('estimateFees should return correct fees', async () => {
// burn // burn
const res = await estimateFees({ ...paramsWithRpcUrl, ...functionDataBurn }) const res = await estimateFees({ ...paramsWithRpcUrl, ...functionDataBurn })
expect(res).toMatchInlineSnapshot('20573185261089n') expect(res).toMatchInlineSnapshot('20573203833264n')
expect(formatEther(res)).toMatchInlineSnapshot('"0.000020573185261089"') expect(formatEther(res)).toMatchInlineSnapshot('"0.000020573203833264"')
expect( expect(
await estimateFees({ ...paramsWithRpcUrl, ...functionDataBurn }) await estimateFees({ ...paramsWithRpcUrl, ...functionDataBurn })
).toMatchInlineSnapshot('20573185261089n') ).toMatchInlineSnapshot('20573203833264n')
expect( expect(
await estimateFees({ ...paramsWithViemClient, ...functionDataBurn }) await estimateFees({ ...paramsWithViemClient, ...functionDataBurn })
).toMatchInlineSnapshot('20573185261089n') ).toMatchInlineSnapshot('20573203833264n')
expect( expect(
await estimateFees({ await estimateFees({
...paramsWithRpcUrl, ...paramsWithRpcUrl,
...functionDataBurnWithPriorityFees, ...functionDataBurnWithPriorityFees,
}) })
).toMatchInlineSnapshot('21536974118090n') ).toMatchInlineSnapshot('21536992690265n')
// what is the l2 and l1 part of the fees for reference? // what is the l2 and l1 part of the fees for reference?
const l1Fee = await getL1Fee({ ...paramsWithRpcUrl, ...functionDataBurn }) const l1Fee = await getL1Fee({ ...paramsWithRpcUrl, ...functionDataBurn })
const l2Fee = res - l1Fee const l2Fee = res - l1Fee
expect(l1Fee).toMatchInlineSnapshot('20573185216764n') expect(l1Fee).toMatchInlineSnapshot('20573185216764n')
expect(formatEther(l1Fee)).toMatchInlineSnapshot('"0.000020573185216764"') expect(formatEther(l1Fee)).toMatchInlineSnapshot('"0.000020573185216764"')
expect(l2Fee).toMatchInlineSnapshot('44325n') expect(l2Fee).toMatchInlineSnapshot('18616500n')
expect(formatEther(l2Fee)).toMatchInlineSnapshot('"0.000000000000044325"') expect(formatEther(l2Fee)).toMatchInlineSnapshot('"0.0000000000186165"')
// withdraw // withdraw
const res2 = await estimateFees({ const res2 = await estimateFees({
...paramsWithRpcUrlWithdraw, ...paramsWithRpcUrlWithdraw,
...functionDataWithdraw, ...functionDataWithdraw,
}) })
expect(res2).toMatchInlineSnapshot('62857039016380n') expect(res2).toMatchInlineSnapshot('62857090247510n')
expect( expect(
await estimateFees({ ...paramsWithRpcUrlWithdraw, ...functionDataWithdraw }) await estimateFees({ ...paramsWithRpcUrlWithdraw, ...functionDataWithdraw })
).toMatchInlineSnapshot('62857039016380n') ).toMatchInlineSnapshot('62857090247510n')
expect( expect(
await estimateFees({ ...paramsWithRpcUrlWithdraw, ...functionDataWithdraw }) await estimateFees({ ...paramsWithRpcUrlWithdraw, ...functionDataWithdraw })
).toMatchInlineSnapshot('62857039016380n') ).toMatchInlineSnapshot('62857090247510n')
expect( expect(
await estimateFees({ ...paramsWithRpcUrlWithdraw, ...functionDataWithdraw }) await estimateFees({ ...paramsWithRpcUrlWithdraw, ...functionDataWithdraw })
).toMatchInlineSnapshot('62857039016380n') ).toMatchInlineSnapshot('62857090247510n')
expect(formatEther(res2)).toMatchInlineSnapshot('"0.00006285703901638"') expect(formatEther(res2)).toMatchInlineSnapshot('"0.00006285709024751"')
// what is the l2 and l1 part of the fees for reference? // what is the l2 and l1 part of the fees for reference?
const l1Fee2 = await getL1Fee({ const l1Fee2 = await getL1Fee({
...paramsWithRpcUrlWithdraw, ...paramsWithRpcUrlWithdraw,
...@@ -141,8 +154,8 @@ test('estimateFees should return correct fees', async () => { ...@@ -141,8 +154,8 @@ test('estimateFees should return correct fees', async () => {
const l2Fee2 = res2 - l1Fee const l2Fee2 = res2 - l1Fee
expect(l1Fee2).toMatchInlineSnapshot('62857038894110n') expect(l1Fee2).toMatchInlineSnapshot('62857038894110n')
expect(formatEther(l1Fee2)).toMatchInlineSnapshot('"0.00006285703889411"') expect(formatEther(l1Fee2)).toMatchInlineSnapshot('"0.00006285703889411"')
expect(l2Fee2).toMatchInlineSnapshot('42283853799616n') expect(l2Fee2).toMatchInlineSnapshot('42283905030746n')
expect(formatEther(l2Fee2)).toMatchInlineSnapshot('"0.000042283853799616"') expect(formatEther(l2Fee2)).toMatchInlineSnapshot('"0.000042283905030746"')
}) })
test('baseFee should return the correct result', async () => { test('baseFee should return the correct result', async () => {
......
...@@ -332,7 +332,7 @@ export const estimateFees: EstimateFees = async (options) => { ...@@ -332,7 +332,7 @@ export const estimateFees: EstimateFees = async (options) => {
args: options.args, args: options.args,
functionName: options.functionName, functionName: options.functionName,
} as EncodeFunctionDataParameters) } as EncodeFunctionDataParameters)
const [l1Fee, l2Fee] = await Promise.all([ const [l1Fee, l2Gas, l2GasPrice] = await Promise.all([
getL1Fee({ getL1Fee({
...options, ...options,
// account must be undefined or else viem will return undefined // account must be undefined or else viem will return undefined
...@@ -347,6 +347,7 @@ export const estimateFees: EstimateFees = async (options) => { ...@@ -347,6 +347,7 @@ export const estimateFees: EstimateFees = async (options) => {
data: encodedFunctionData, data: encodedFunctionData,
value: options.value, value: options.value,
} as EstimateGasParameters<typeof chains.optimism>), } as EstimateGasParameters<typeof chains.optimism>),
client.getGasPrice(),
]) ])
return l1Fee + l2Fee return l1Fee + l2Gas * l2GasPrice
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment