• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lmittmann / w3 / 12766073216

14 Jan 2025 10:47AM UTC coverage: 64.189% (-0.07%) from 64.258%
12766073216

Pull #208

github

lmittmann
this is no longer needed
Pull Request #208: module/eth: added number support for storage values in `StorageAt`

3 of 3 new or added lines in 2 files covered. (100.0%)

1 existing line in 1 file now uncovered.

1986 of 3094 relevant lines covered (64.19%)

811.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

30.72
/w3vm/util.go
1
package w3vm
2

3
import (
4
        "crypto/rand"
5
        "math/big"
6
        "path/filepath"
7
        "runtime"
8
        "strings"
9
        "testing"
10

11
        "github.com/ethereum/go-ethereum/common"
12
        "github.com/ethereum/go-ethereum/common/hexutil"
13
        "github.com/ethereum/go-ethereum/core/tracing"
14
        "github.com/ethereum/go-ethereum/core/types"
15
        "github.com/holiman/uint256"
16
        "github.com/lmittmann/w3"
17
        "github.com/lmittmann/w3/internal/crypto"
18
        "github.com/lmittmann/w3/internal/mod"
19
        "github.com/lmittmann/w3/internal/module"
20
        "github.com/lmittmann/w3/w3types"
21
)
22

23
// RandA returns a random address.
24
func RandA() (addr common.Address) {
×
25
        rand.Read(addr[:])
×
26
        return addr
×
27
}
×
28

29
var (
30
        weth9BalancePos   = common.BytesToHash([]byte{3})
31
        weth9AllowancePos = common.BytesToHash([]byte{4})
32
)
33

34
// WETHBalanceSlot returns the storage slot that stores the WETH balance of
35
// the given addr.
36
func WETHBalanceSlot(addr common.Address) common.Hash {
12✔
37
        return Slot(weth9BalancePos, common.BytesToHash(addr[:]))
12✔
38
}
12✔
39

40
// WETHAllowanceSlot returns the storage slot that stores the WETH allowance
41
// of the given owner to the spender.
42
func WETHAllowanceSlot(owner, spender common.Address) common.Hash {
2✔
43
        return Slot2(weth9AllowancePos, common.BytesToHash(owner[:]), common.BytesToHash(spender[:]))
2✔
44
}
2✔
45

46
// Slot returns the storage slot of a mapping with the given position and key.
47
//
48
// Slot follows the Solidity storage layout for:
49
//
50
//        mapping(bytes32 => bytes32)
51
func Slot(pos, key common.Hash) common.Hash {
12✔
52
        return crypto.Keccak256Hash(key[:], pos[:])
12✔
53
}
12✔
54

55
// Slot2 returns the storage slot of a double mapping with the given position
56
// and keys.
57
//
58
// Slot2 follows the Solidity storage layout for:
59
//
60
//        mapping(bytes32 => mapping(bytes32 => bytes32))
61
func Slot2(pos, key, key2 common.Hash) common.Hash {
2✔
62
        return crypto.Keccak256Hash(
2✔
63
                key2[:],
2✔
64
                crypto.Keccak256(key[:], pos[:]),
2✔
65
        )
2✔
66
}
2✔
67

68
// nilToZero converts sets a pointer to the zero value if it is nil.
69
func nilToZero[T any](ptr *T) *T {
23,981✔
70
        if ptr == nil {
24,893✔
71
                return new(T)
912✔
72
        }
912✔
73
        return ptr
23,069✔
74
}
75

76
// zeroHashFunc implements a [vm.GetHashFunc] that always returns the zero hash.
77
func zeroHashFunc(uint64) common.Hash {
×
78
        return w3.Hash0
×
79
}
×
80

81
////////////////////////////////////////////////////////////////////////////////////////////////////
82
// w3types.RPCCaller's /////////////////////////////////////////////////////////////////////////////
83
////////////////////////////////////////////////////////////////////////////////////////////////////
84

85
// ethBalance is like [eth.Balance], but returns the balance as [uint256.Int].
86
func ethBalance(addr common.Address, blockNumber *big.Int) w3types.RPCCallerFactory[uint256.Int] {
16✔
87
        return module.NewFactory(
16✔
88
                "eth_getBalance",
16✔
89
                []any{addr, module.BlockNumberArg(blockNumber)},
16✔
90
                module.WithRetWrapper(func(ret *uint256.Int) any { return (*hexutil.U256)(ret) }),
32✔
91
        )
92
}
93

94
// ethHeaderHash is like [eth.Header], but only parses the header hash.
UNCOV
95
func ethHeaderHash(blockNumber uint64) w3types.RPCCallerFactory[header] {
×
96
        return module.NewFactory[header](
×
97
                "eth_getBlockByNumber",
×
98
                []any{hexutil.Uint64(blockNumber), false},
×
99
        )
×
100
}
×
101

102
type header struct {
103
        Hash common.Hash `json:"hash"`
104
}
105

106
////////////////////////////////////////////////////////////////////////////////////////////////////
107
// tracing.Hook's //////////////////////////////////////////////////////////////////////////////////
108
////////////////////////////////////////////////////////////////////////////////////////////////////
109

110
// joinHooks joins multiple hooks into one.
111
func joinHooks(hooks []*tracing.Hooks) *tracing.Hooks {
5,957✔
112
        // hot path
5,957✔
113
        switch len(hooks) {
5,957✔
114
        case 0:
5,954✔
115
                return nil
5,954✔
116
        case 1:
3✔
117
                return hooks[0]
3✔
118
        }
119

120
        // vm hooks
121
        var onEnters []tracing.EnterHook
×
122
        var onExits []tracing.ExitHook
×
123
        var onOpcodes []tracing.OpcodeHook
×
124
        var onFaults []tracing.FaultHook
×
125
        var onGasChanges []tracing.GasChangeHook
×
126
        // state hooks
×
127
        var onBalanceChanges []tracing.BalanceChangeHook
×
128
        var onNonceChanges []tracing.NonceChangeHook
×
129
        var onCodeChanges []tracing.CodeChangeHook
×
130
        var onStorageChanges []tracing.StorageChangeHook
×
131
        var onLogs []tracing.LogHook
×
132

×
133
        for _, h := range hooks {
×
134
                if h == nil {
×
135
                        continue
×
136
                }
137
                // vm hooks
138
                if h.OnEnter != nil {
×
139
                        onEnters = append(onEnters, h.OnEnter)
×
140
                }
×
141
                if h.OnExit != nil {
×
142
                        onExits = append(onExits, h.OnExit)
×
143
                }
×
144
                if h.OnOpcode != nil {
×
145
                        onOpcodes = append(onOpcodes, h.OnOpcode)
×
146
                }
×
147
                if h.OnFault != nil {
×
148
                        onFaults = append(onFaults, h.OnFault)
×
149
                }
×
150
                if h.OnGasChange != nil {
×
151
                        onGasChanges = append(onGasChanges, h.OnGasChange)
×
152
                }
×
153
                // state hooks
154
                if h.OnBalanceChange != nil {
×
155
                        onBalanceChanges = append(onBalanceChanges, h.OnBalanceChange)
×
156
                }
×
157
                if h.OnNonceChange != nil {
×
158
                        onNonceChanges = append(onNonceChanges, h.OnNonceChange)
×
159
                }
×
160
                if h.OnCodeChange != nil {
×
161
                        onCodeChanges = append(onCodeChanges, h.OnCodeChange)
×
162
                }
×
163
                if h.OnStorageChange != nil {
×
164
                        onStorageChanges = append(onStorageChanges, h.OnStorageChange)
×
165
                }
×
166
                if h.OnLog != nil {
×
167
                        onLogs = append(onLogs, h.OnLog)
×
168
                }
×
169
        }
170

171
        hook := new(tracing.Hooks)
×
172
        // vm hooks
×
173
        if len(onEnters) > 0 {
×
174
                hook.OnEnter = func(depth int, typ byte, from, to common.Address, input []byte, gas uint64, value *big.Int) {
×
175
                        for _, h := range onEnters {
×
176
                                h(depth, typ, from, to, input, gas, value)
×
177
                        }
×
178
                }
179
        }
180
        if len(onExits) > 0 {
×
181
                hook.OnExit = func(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
×
182
                        for _, h := range onExits {
×
183
                                h(depth, output, gasUsed, err, reverted)
×
184
                        }
×
185
                }
186
        }
187
        if len(onOpcodes) > 0 {
×
188
                hook.OnOpcode = func(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
×
189
                        for _, h := range onOpcodes {
×
190
                                h(pc, op, gas, cost, scope, rData, depth, err)
×
191
                        }
×
192
                }
193
        }
194
        if len(onFaults) > 0 {
×
195
                hook.OnFault = func(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, depth int, err error) {
×
196
                        for _, h := range onFaults {
×
197
                                h(pc, op, gas, cost, scope, depth, err)
×
198
                        }
×
199
                }
200
        }
201
        if len(onGasChanges) > 0 {
×
202
                hook.OnGasChange = func(old, new uint64, reason tracing.GasChangeReason) {
×
203
                        for _, h := range onGasChanges {
×
204
                                h(old, new, reason)
×
205
                        }
×
206
                }
207
        }
208
        // state hooks
209
        if len(onBalanceChanges) > 0 {
×
210
                hook.OnBalanceChange = func(addr common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) {
×
211
                        for _, h := range onBalanceChanges {
×
212
                                h(addr, prev, new, reason)
×
213
                        }
×
214
                }
215
        }
216
        if len(onNonceChanges) > 0 {
×
217
                hook.OnNonceChange = func(addr common.Address, prev, new uint64) {
×
218
                        for _, h := range onNonceChanges {
×
219
                                h(addr, prev, new)
×
220
                        }
×
221
                }
222
        }
223
        if len(onCodeChanges) > 0 {
×
224
                hook.OnCodeChange = func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte) {
×
225
                        for _, h := range onCodeChanges {
×
226
                                h(addr, prevCodeHash, prevCode, codeHash, code)
×
227
                        }
×
228
                }
229
        }
230
        if len(onStorageChanges) > 0 {
×
231
                hook.OnStorageChange = func(addr common.Address, slot, prev, new common.Hash) {
×
232
                        for _, h := range onStorageChanges {
×
233
                                h(addr, slot, prev, new)
×
234
                        }
×
235
                }
236
        }
237
        if len(onLogs) > 0 {
×
238
                hook.OnLog = func(log *types.Log) {
×
239
                        for _, h := range onLogs {
×
240
                                h(log)
×
241
                        }
×
242
                }
243
        }
244
        return hook
×
245
}
246

247
////////////////////////////////////////////////////////////////////////////////////////////////////
248
// Testing /////////////////////////////////////////////////////////////////////////////////////////
249
////////////////////////////////////////////////////////////////////////////////////////////////////
250

251
func getTbFilepath(tb testing.TB) string {
90✔
252
        // Find test name of the root test (drop subtests from name).
90✔
253
        if tb == nil || tb.Name() == "" {
90✔
254
                return ""
×
255
        }
×
256
        tn := strings.SplitN(tb.Name(), "/", 2)[0]
90✔
257

90✔
258
        // Find the test function in the call stack. Don't go deeper than 32 frames.
90✔
259
        for i := range 32 {
409✔
260
                pc, file, _, ok := runtime.Caller(i)
319✔
261
                if !ok {
319✔
262
                        break
×
263
                }
264

265
                fn := runtime.FuncForPC(pc).Name()
319✔
266
                _, fn = filepath.Split(fn)
319✔
267
                fn = strings.SplitN(fn, ".", 3)[1]
319✔
268

319✔
269
                if fn == tn {
409✔
270
                        return filepath.Dir(file)
90✔
271
                }
90✔
272
        }
273
        return ""
×
274
}
275

276
func isTbInMod(fp string) bool {
45✔
277
        return mod.Root != "" && strings.HasPrefix(fp, mod.Root)
45✔
278
}
45✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc