Skip to content

Commit b4bc5c8

Browse files
author
Adrien Hamelin
authored
feat: add executable examples for all opcodes (#100)
* Add basic highligths for Mnemonic, and run code as a transaction to have a balance * Change precompile code examples to links * Read the state even when the state returns an error to display cost and return value * Fix search for opcode or address
1 parent eff2854 commit b4bc5c8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

141 files changed

+405
-289
lines changed

components/Editor/index.tsx

+6-24
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ const Editor = ({ readOnly = false }: Props) => {
6666
const router = useRouter()
6767

6868
const {
69-
deployContract,
69+
transactionData,
7070
loadInstructions,
7171
startExecution,
7272
startTransaction,
@@ -137,10 +137,10 @@ const Editor = ({ readOnly = false }: Props) => {
137137

138138
try {
139139
const _callValue = getCallValue()
140-
deployContract(byteCode, _callValue).then((tx) => {
140+
transactionData(byteCode, _callValue).then((tx) => {
141141
loadInstructions(byteCode)
142142
setIsCompiling(false)
143-
startTransaction(byteCode, tx)
143+
startTransaction(tx)
144144
})
145145
} catch (error) {
146146
log((error as Error).message, 'error')
@@ -150,7 +150,7 @@ const Editor = ({ readOnly = false }: Props) => {
150150
[
151151
log,
152152
setIsCompiling,
153-
deployContract,
153+
transactionData,
154154
loadInstructions,
155155
startTransaction,
156156
getCallValue,
@@ -231,17 +231,6 @@ const Editor = ({ readOnly = false }: Props) => {
231231
return value
232232
}
233233

234-
const highlightMnemonic = (value: string) => {
235-
if (!codeType) {
236-
return value
237-
}
238-
239-
return value
240-
.split('\n')
241-
.map((line, i) => `<span class='line-number'>${i + 1}</span>${line}`)
242-
.join('\n')
243-
}
244-
245234
const handleCodeTypeChange = (option: OnChangeValue<any, any>) => {
246235
const { value } = option
247236
setCodeType(value)
@@ -275,7 +264,7 @@ const Editor = ({ readOnly = false }: Props) => {
275264
}
276265

277266
try {
278-
const _callData = Buffer.from(callData.substr(2), 'hex')
267+
const _callData = callData.substr(2)
279268
const _callValue = getCallValue()
280269

281270
if (codeType === CodeType.Mnemonic) {
@@ -339,7 +328,6 @@ const Editor = ({ readOnly = false }: Props) => {
339328
}, [compiling, code])
340329

341330
const isBytecode = useMemo(() => codeType === CodeType.Bytecode, [codeType])
342-
const isMnemonic = useMemo(() => codeType === CodeType.Mnemonic, [codeType])
343331
const isCallDataActive = useMemo(
344332
() => codeType === CodeType.Mnemonic || codeType === CodeType.Bytecode,
345333
[codeType],
@@ -375,13 +363,7 @@ const Editor = ({ readOnly = false }: Props) => {
375363
value={code}
376364
readOnly={readOnly}
377365
onValueChange={handleCodeChange}
378-
highlight={
379-
isBytecode
380-
? highlightBytecode
381-
: isMnemonic
382-
? highlightMnemonic
383-
: highlightCode
384-
}
366+
highlight={isBytecode ? highlightBytecode : highlightCode}
385367
tabSize={4}
386368
className={cn('code-editor', {
387369
'with-numbers': !isBytecode,

components/Reference/Filters.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ const Filters = ({ onSetFilter, isPrecompiled = false }: Props) => {
2121

2222
const filterByOptions = useMemo(
2323
() => [
24-
{ label: !isPrecompiled ? 'Opcode' : 'Address', value: 'code' },
24+
{
25+
label: !isPrecompiled ? 'Opcode' : 'Address',
26+
value: 'opcodeOrAddress',
27+
},
2528
{ label: 'Name', value: 'name' },
2629
{ label: 'Description', value: 'description' },
2730
],

context/ethereumContext.tsx

+35-44
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const privateKey = Buffer.from(
3939
)
4040
const accountBalance = 18 // 1eth
4141
const accountAddress = Address.fromPrivateKey(privateKey)
42+
const contractAddress = Address.generate(accountAddress, new BN(1))
4243
const gasLimit = new BN(0xffffffffffff)
4344

4445
type ContextProps = {
@@ -57,13 +58,14 @@ type ContextProps = {
5758

5859
onChainChange: (chainId: number) => void
5960
onForkChange: (forkName: string) => void
60-
deployContract: (
61+
transactionData: (
6162
byteCode: string,
6263
value: BN,
64+
to?: Address,
6365
) => Promise<TypedTransaction | TxData>
6466
loadInstructions: (byteCode: string) => void
65-
startExecution: (byteCode: string, value: BN, data: Buffer) => void
66-
startTransaction: (byteCode: string, tx: TypedTransaction | TxData) => void
67+
startExecution: (byteCode: string, value: BN, data: string) => void
68+
startTransaction: (tx: TypedTransaction | TxData) => void
6769
continueExecution: () => void
6870
addBreakpoint: (instructionId: number) => void
6971
removeBreakpoint: (instructionId: number) => void
@@ -97,7 +99,7 @@ export const EthereumContext = createContext<ContextProps>({
9799

98100
onChainChange: () => undefined,
99101
onForkChange: () => undefined,
100-
deployContract: () =>
102+
transactionData: () =>
101103
new Promise((resolve) => {
102104
resolve({})
103105
}),
@@ -194,14 +196,15 @@ export const EthereumProvider: React.FC<{}> = ({ children }) => {
194196
* @param byteCode The contract bytecode.
195197
* @returns The deployed contract transaction data.
196198
*/
197-
const deployContract = async (byteCode: string, value: BN) => {
199+
const transactionData = async (data: string, value: BN, to?: Address) => {
198200
const account = await vm.stateManager.getAccount(accountAddress)
199201

200202
const txData = {
203+
to,
201204
value: value,
202205
gasLimit,
203206
gasPrice: 10,
204-
data: '0x' + byteCode,
207+
data: '0x' + data,
205208
nonce: account.nonce,
206209
}
207210

@@ -252,39 +255,20 @@ export const EthereumProvider: React.FC<{}> = ({ children }) => {
252255
* @param value The callvalue.
253256
* @param data The calldata.
254257
*/
255-
const startExecution = (byteCode: string, value: BN, data: Buffer) => {
256-
// always start paused
257-
isExecutionPaused.current = true
258-
setIsExecuting(true)
259-
setVmError(undefined)
260-
261-
vm.runCode({
262-
code: Buffer.from(byteCode, 'hex'),
263-
value,
264-
data,
265-
gasLimit,
266-
block: _getBlock(),
267-
})
268-
.then(({ runState, gasUsed, returnValue, exceptionError }) =>
269-
_loadRunState({
270-
gasUsed,
271-
runState,
272-
returnValue,
273-
exceptionError,
274-
}),
275-
)
276-
.finally(() => setIsExecuting(false))
258+
const startExecution = async (byteCode: string, value: BN, data: string) => {
259+
vm.stateManager.putContractCode(
260+
contractAddress,
261+
Buffer.from(byteCode, 'hex'),
262+
)
263+
startTransaction(await transactionData(data, value, contractAddress))
277264
}
278265

279266
/**
280267
* Starts EVM execution of the instructions.
281268
* @param byteCode The contract bytecode.
282269
* @param tx The transaction data to run from.
283270
*/
284-
const startTransaction = (
285-
byteCode: string,
286-
tx: TypedTransaction | TxData,
287-
) => {
271+
const startTransaction = (tx: TypedTransaction | TxData) => {
288272
// always start paused
289273
isExecutionPaused.current = true
290274
setIsExecuting(true)
@@ -296,7 +280,9 @@ export const EthereumProvider: React.FC<{}> = ({ children }) => {
296280
_loadRunState({
297281
gasUsed,
298282
runState: execResult.runState,
299-
contractAddress: createdAddress,
283+
newContractAddress: createdAddress,
284+
returnValue: execResult.returnValue,
285+
exceptionError: execResult.exceptionError,
300286
}),
301287
)
302288
.finally(() => setIsExecuting(false))
@@ -495,33 +481,36 @@ export const EthereumProvider: React.FC<{}> = ({ children }) => {
495481
const _setupAccount = () => {
496482
// Add a fake account
497483
const accountData = {
498-
nonce: 0,
484+
nonce: 2,
499485
balance: new BN(10).pow(new BN(accountBalance)),
500486
}
487+
const contractData = {
488+
nonce: 0,
489+
balance: 0,
490+
}
501491
vm.stateManager.putAccount(
502492
accountAddress,
503493
Account.fromAccountData(accountData),
504494
)
495+
vm.stateManager.putAccount(
496+
contractAddress,
497+
Account.fromAccountData(contractData),
498+
)
505499
}
506500

507501
const _loadRunState = ({
508502
gasUsed,
509503
runState,
510-
contractAddress,
504+
newContractAddress,
511505
returnValue,
512506
exceptionError,
513507
}: {
514508
gasUsed: BN
515509
runState?: RunState
516-
contractAddress?: Address
510+
newContractAddress?: Address
517511
returnValue?: Buffer
518512
exceptionError?: VmError
519513
}) => {
520-
if (exceptionError) {
521-
setVmError(exceptionError.error)
522-
return
523-
}
524-
525514
if (runState) {
526515
const { programCounter: pc, stack, memory } = runState
527516
_setExecutionState({
@@ -533,8 +522,10 @@ export const EthereumProvider: React.FC<{}> = ({ children }) => {
533522
})
534523
}
535524

536-
if (contractAddress) {
537-
setDeployedContractAddress(contractAddress.toString())
525+
if (exceptionError) {
526+
setVmError(exceptionError.error)
527+
} else if (newContractAddress) {
528+
setDeployedContractAddress(newContractAddress.toString())
538529
}
539530
}
540531

@@ -671,7 +662,7 @@ export const EthereumProvider: React.FC<{}> = ({ children }) => {
671662

672663
onChainChange,
673664
onForkChange,
674-
deployContract,
665+
transactionData,
675666
loadInstructions,
676667
startExecution,
677668
startTransaction,

docs/opcodes/01.mdx

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ group: Stop and Arithmetic Operations
2121
| `1` | `10` | `20` | * | `1` | `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF` | `0` |
2222
| `2` | `10` | | * | `2` | `1` | |
2323

24+
[Reproduce in playground](/playground?unit=Wei&codeType=Mnemonic&code='y1z0z0twwy2v32%200xsssszt'~uuuuzv1%201y%2F%2F%20Example%20w%5CnvwPUSHuFFtwADDs~~%01stuvwyz~_).
25+
2426
## Error cases
2527

2628
The state changes done by the current context are [reverted](#FD) in those cases:

docs/opcodes/02.mdx

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ group: Stop and Arithmetic Operations
2626
| `1` | `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF` | `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE` |
2727
| `2` | `2` | |
2828

29+
[Reproduce in playground](/playground?unit=Wei&codeType=Mnemonic&code='y1z10z10twwy2v32%200xssssz2t'~uuuuzv1%20y%2F%2F%20Example%20w%5CnvwPUSHuFFtwMULs~~%01stuvwyz~_).
30+
2931
## Error cases
3032

3133
The state changes done by the current context are [reverted](#FD) in those cases:

docs/opcodes/03.mdx

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ group: Stop and Arithmetic Operations
2121
| `1` | `10` | `0` | * | `1` | `0` | `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF` |
2222
| `2` | `10` | | * | `2` | `1` | |
2323

24+
[Reproduce in playground](/playground?unit=Wei&codeType=Mnemonic&code='z1~10~1wyyz2~1~w'~yPUSH1%20z%2F%2F%20Example%20y%5Cnw0ySUB%01wyz~_).
25+
2426
## Error cases
2527

2628
The state changes done by the current context are [reverted](#FD) in those cases:

docs/opcodes/04.mdx

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ group: Stop and Arithmetic Operations
2121
| `1` | `10` | `1` | * | `1` | `1` | `0` |
2222
| `2` | `10` | | * | `2` | `2` | |
2323

24+
[Reproduce in playground](/playground?unit=Wei&codeType=Mnemonic&code='z1~10~10wyyz2~2~1w'~yPUSH1%20z%2F%2F%20Example%20y%5CnwyDIV%01wyz~_).
2425

2526
## Error cases
2627

docs/opcodes/05.mdx

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ All values are treated as two’s complement signed 256-bit integers. Note the o
2222

2323
| * | Input | Output | * | * | Input | Output |
2424
|--:|------:|-------:|--:|--:|------:|-------:|
25-
| `1` | `10` | `1` | * | `1` | `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF` | `2` |
26-
| `2` | `10` | | * | `2` | `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE` | |
25+
| `1` | `10` | `1` | * | `1` | `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE` | `2` |
26+
| `2` | `10` | | * | `2` | `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF` | |
27+
28+
[Reproduce in playground](/playground?unit=Wei&codeType=Mnemonic&code='y1vvszzy2wrFwrEs'~uuuz%5Cny%2F%2F%20Example%20wt32%200xr~vt1%2010uFFFtzPUSHszSDIVr~~~%01rstuvwyz~_).
2729

2830
## Error cases
2931

docs/opcodes/06.mdx

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ group: Stop and Arithmetic Operations
2121
| `1` | `10` | `1` | * | `1` | `17` | `2` |
2222
| `2` | `3` | | * | `2` | `5` | |
2323

24+
[Reproduce in playground](/playground?unit=Wei&codeType=Mnemonic&code='z1~3~10wyyz2~5~17w'~yPUSH1%20z%2F%2F%20Example%20y%5CnwyMOD%01wyz~_).
25+
2426
## Error cases
2527

2628
The state changes done by the current context are [reverted](#FD) in those cases:

docs/opcodes/07.mdx

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ All values are treated as two’s complement signed 256-bit integers. Note the o
3030
| `1` | `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8` | `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE` |
3131
| `2` | `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD` | |
3232

33+
[Reproduce in playground](/playground?unit=Wei&codeType=Mnemonic&code='y1s3s10tzzy2wrDwr8t'~uuuz%5Cny%2F%2F%20Example%20wv32%200xr~vzPUSHuFFFtzSMODsv1%20r~~~%01rstuvwyz~_).
34+
3335
## Error cases
3436

3537
The state changes done by the current context are [reverted](#FD) in those cases:

docs/opcodes/08.mdx

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ All intermediate calculations of this operation are not subject to the 2<sup>256
2727
| `2` | `10` | | * | `2` | `2` | |
2828
| `3` | `8` | | * | `2` | `2` | |
2929

30+
[Reproduce in playground](/playground?unit=Wei&codeType=Mnemonic&code='y1z8z10z10vwwy2z2z2u32%200xssssv'~ttttzu1%20y%2F%2F%20Example%20w%5CnvwADDMODuwPUSHtFFs~~%01stuvwyz~_).
31+
3032
## Error cases
3133

3234
The state changes done by the current context are [reverted](#FD) in those cases:

docs/opcodes/09.mdx

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ All intermediate calculations of this operation are not subject to the 2<sup>256
2727
| `2` | `10` | | * | `2` | `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF` | |
2828
| `3` | `8` | | * | `3` | `12` | |
2929

30+
[Reproduce in playground](/playground?unit=Wei&codeType=Mnemonic&code='y1v8v10v10twwy2v12usust'~rrrrzwPUSHy%2F%2F%20Example%20w%5Cnvz1%20uz32%200xstwMULMODs~~~~rFF%01rstuvwyz~_).
31+
3032
## Error cases
3133

3234
The state changes done by the current context are [reverted](#FD) in those cases:

docs/opcodes/0A.mdx

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ group: Stop and Arithmetic Operations
2121
| `1` | `10` | `100` | * | `1` | `2` | `4` |
2222
| `2` | `2` | | * | `2` | `2` | |
2323

24+
[Reproduce in playground](/playground?unit=Wei&codeType=Mnemonic&code='z1~2~10wyyz2~2~2w'~yPUSH1%20z%2F%2F%20Example%20y%5CnwyEXP%01wyz~_).
25+
2426
## Error cases
2527

2628
The state changes done by the current context are [reverted](#FD) in those cases:

docs/opcodes/0B.mdx

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ group: Stop and Arithmetic Operations
2121
| `1` | `0` | `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF` | * | `1` | `0` | `0x7F` |
2222
| `2` | `0xFF` | | * | `2` | `0x7F` | |
2323

24+
[Reproduce in playground](/playground?unit=Wei&codeType=Mnemonic&code='z1~xFywwz2~x7y'~wPUSH1%200z%2F%2F%20Example%20yF~wSIGNEXTENDw%5Cn%01wyz~_).
25+
2426
## Error cases
2527

2628
The state changes done by the current context are [reverted](#FD) in those cases:

docs/opcodes/10.mdx

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ group: Comparison & Bitwise Logic Operations
2121
| `1` | `9` | `1` | * | `1` | `10` | `0` |
2222
| `2` | `10` | | * | `2` | `10` | |
2323

24+
[Reproduce in playground](/playground?unit=Wei&codeType=Mnemonic&code='z1w~9yLTyyz2wwyLT'~yPUSH1%20z%2F%2F%20Example%20y%5Cnw~10%01wyz~_).
25+
2426
## Error cases
2527

2628
The state changes done by the current context are [reverted](#FD) in those cases:

docs/opcodes/11.mdx

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ group: Comparison & Bitwise Logic Operations
2121
| `1` | `10` | `1` | * | `1` | `10` | `0` |
2222
| `2` | `9` | | * | `2` | `10` | |
2323

24+
[Reproduce in playground](/playground?unit=Wei&codeType=Mnemonic&code='z1~9wyyz2~10w'~yPUSH1%20z%2F%2F%20Example%20y%5Cnw~10yGT%01wyz~_).
25+
2426
## Error cases
2527

2628
The state changes done by the current context are [reverted](#FD) in those cases:

docs/opcodes/12.mdx

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ All values are treated as two’s complement signed 256-bit integers.
2525
| `1` | `0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF` | `1` | * | `1` | `10` | `0` |
2626
| `2` | `0` | | * | `2` | `10` | |
2727

28+
[Reproduce in playground](/playground?unit=Wei&codeType=Mnemonic&code='y1z9v32%200xsssstwwy2z10z10t'~uuuuzv1%20y%2F%2F%20Example%20w%5CnvwPUSHuFFtwSLTs~~%01stuvwyz~_).
29+
2830
## Error cases
2931

3032
The state changes done by the current context are [reverted](#FD) in those cases:

0 commit comments

Comments
 (0)