-
Notifications
You must be signed in to change notification settings - Fork 10
test: basic storage proof #336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| [profile.default] | ||
| src = "src" | ||
| out = "artifacts" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.20; | ||
|
|
||
| contract SimpleStorage { | ||
| uint256 public value; | ||
|
|
||
| function setValue(uint256 newValue) external { | ||
| value = newValue; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,147 @@ | ||||||
| package proofs | ||||||
|
|
||||||
| import ( | ||||||
| "context" | ||||||
| "encoding/json" | ||||||
| "fmt" | ||||||
| "math/big" | ||||||
| "os" | ||||||
| "strings" | ||||||
| "testing" | ||||||
|
|
||||||
| "github.com/ethereum-optimism/optimism/op-devstack/devtest" | ||||||
| "github.com/ethereum-optimism/optimism/op-devstack/dsl" | ||||||
| "github.com/ethereum-optimism/optimism/op-devstack/presets" | ||||||
| "github.com/ethereum-optimism/optimism/op-service/eth" | ||||||
| "github.com/ethereum-optimism/optimism/op-service/txplan" | ||||||
| "github.com/ethereum/go-ethereum/accounts/abi" | ||||||
| "github.com/ethereum/go-ethereum/common" | ||||||
| "github.com/ethereum/go-ethereum/common/hexutil" | ||||||
| "github.com/ethereum/go-ethereum/core/types" | ||||||
| "github.com/stretchr/testify/require" | ||||||
| ) | ||||||
|
|
||||||
| // minimal parts of artifact | ||||||
| type artifact struct { | ||||||
| ABI json.RawMessage `json:"abi"` | ||||||
| Bytecode struct { | ||||||
| Object string `json:"object"` | ||||||
| } `json:"bytecode"` | ||||||
| } | ||||||
|
|
||||||
| // loadArtifact reads the forge artifact JSON at artifactPath and returns the parsed ABI | ||||||
| // and the creation bytecode (as bytes). It prefers bytecode.object (creation) and falls | ||||||
| // back to deployedBytecode.object if needed. | ||||||
| func loadArtifact(artifactPath string) (abi.ABI, []byte, error) { | ||||||
| data, err := os.ReadFile(artifactPath) | ||||||
| if err != nil { | ||||||
| return abi.ABI{}, nil, err | ||||||
| } | ||||||
| var art artifact | ||||||
| if err := json.Unmarshal(data, &art); err != nil { | ||||||
| return abi.ABI{}, nil, err | ||||||
| } | ||||||
| parsedABI, err := abi.JSON(strings.NewReader(string(art.ABI))) | ||||||
| if err != nil { | ||||||
| return abi.ABI{}, nil, err | ||||||
| } | ||||||
| binHex := strings.TrimSpace(art.Bytecode.Object) | ||||||
| if binHex == "" { | ||||||
| return parsedABI, nil, fmt.Errorf("artifact missing bytecode") | ||||||
| } | ||||||
| return parsedABI, common.FromHex(binHex), nil | ||||||
| } | ||||||
|
|
||||||
| // deployContract deploys the contract creation bytecode from the given artifact. | ||||||
| // user must provide a Plan() method compatible with txplan.NewPlannedTx (kept generic). | ||||||
| func deployContract(ctx context.Context, user *dsl.EOA, bin []byte) (common.Address, uint64, error) { | ||||||
| tx := txplan.NewPlannedTx(user.Plan(), txplan.WithData(bin)) | ||||||
| res, err := tx.Included.Eval(ctx) | ||||||
| if err != nil { | ||||||
| return common.Address{}, 0, fmt.Errorf("deployment eval: %w", err) | ||||||
| } | ||||||
| return res.ContractAddress, res.BlockNumber.Uint64(), nil | ||||||
| } | ||||||
|
|
||||||
| func TestStorageProofUsingSimpleStorageContract(gt *testing.T) { | ||||||
| t := devtest.SerialT(gt) | ||||||
| ctx := t.Ctx() | ||||||
|
|
||||||
| sys := presets.NewSingleChainMultiNode(t) | ||||||
| artifactPath := "contracts/artifacts/SimpleStorage.sol/SimpleStorage.json" | ||||||
| parsedABI, bin, err := loadArtifact(artifactPath) | ||||||
| if err != nil { | ||||||
| t.Error("failed to load artifact: %v", err) | ||||||
|
||||||
| t.Error("failed to load artifact: %v", err) | |
| t.Errorf("failed to load artifact: %v", err) |
Copilot
AI
Oct 30, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using t.Error with format specifiers doesn't format the error. Should use t.Errorf to properly format the error message with the %v verb.
| t.Error("failed to deploy contract: %v", err) | |
| t.Errorf("failed to deploy contract: %v", err) |
Copilot
AI
Oct 30, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using t.Error with format specifiers doesn't format the error. Should use t.Errorf to properly format the error message with the %v verb.
| t.Error("failed to pack set call data: %v", err) | |
| t.Errorf("failed to pack set call data: %v", err) |
Copilot
AI
Oct 30, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using t.Error with format specifiers doesn't format the error. Should use t.Errorf to properly format the error message with the %v verb.
| t.Error("failed to create set tx: %v", err) | |
| t.Errorf("failed to create set tx: %v", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment states the function 'falls back to deployedBytecode.object if needed', but the actual implementation at line 49 returns an error when bytecode.object is empty instead of falling back to deployedBytecode.object.