Skip to content

Fix CIP-64 gas price opcode, second take#107

Merged
karlb merged 1 commit intorelease/v1.0.0-rc.4from
karlb/fix-cip-64-gas-price-opcode
Nov 28, 2025
Merged

Fix CIP-64 gas price opcode, second take#107
karlb merged 1 commit intorelease/v1.0.0-rc.4from
karlb/fix-cip-64-gas-price-opcode

Conversation

@karlb
Copy link
Copy Markdown
Contributor

@karlb karlb commented Nov 28, 2025

No description provided.

@karlb karlb changed the base branch from main to release/v1.0.0-rc.4 November 28, 2025 14:13
The previous fix was not correct and only accidentally made the tests
pass. The GASPRICE opcodes fetches the effective gas price and passes in
the base fee in native tokens. We work around this by calculating the
correct effective gas price in advance and ignoring the passed in base
fee.
@karlb karlb force-pushed the karlb/fix-cip-64-gas-price-opcode branch from d626641 to 8d33585 Compare November 28, 2025 14:14
@karlb karlb merged commit 76bad58 into release/v1.0.0-rc.4 Nov 28, 2025
9 checks passed
@karlb karlb deleted the karlb/fix-cip-64-gas-price-opcode branch November 28, 2025 14:26
karlb added a commit that referenced this pull request Dec 2, 2025
The previous fix was not correct and only accidentally made the tests
pass. The GASPRICE opcodes fetches the effective gas price and passes in
the base fee in native tokens. We work around this by calculating the
correct effective gas price in advance and ignoring the passed in base
fee.
karlb added a commit that referenced this pull request Dec 3, 2025
The previous test case often passed even with wrong implementations
because it only noticed if a single `if` condition on the gas price
triggers. Instead, the actual gas price return value should be part of
the tested result to notice any deviations from the expected value.

This is achieved by emitting the result in an event/log so that it
becomes part of the receipt. Full bytecode explanation:

| Offset | Bytecode | Opcode       | Stack (after)   | Description                              |
|--------|----------|--------------|-----------------|------------------------------------------|
| 0x00   | `3a`     | `GASPRICE`   | `[gasPrice]`    | Pushes the tx's gas price onto the stack |
| 0x01   | `60 00`  | `PUSH1 0x00` | `[0, gasPrice]` | Pushes memory offset 0                   |
| 0x03   | `52`     | `MSTORE`     | `[]`            | Stores gasPrice at memory[0:32]          |
| 0x04   | `60 20`  | `PUSH1 0x20` | `[32]`          | Pushes 32 (0x20) - the size in bytes     |
| 0x06   | `60 00`  | `PUSH1 0x00` | `[0, 32]`       | Pushes memory offset 0                   |
| 0x08   | `a0`     | `LOG0`       | `[]`            | Emits anonymous log from memory[0:32]    |

As intended, the test behaves like this:
```
fail
cd86616 Fix CIP-64 gas price opcode (#106)
fail
9d02406 CIP-64: actual GASPRICE opcode fix (#107)
pass (the missing revert has no effect on the returned gas price)
7be19b3 Revert bad fix for GASPRICE opcode (#109)
pass
```
So if we had the test before doing the changes, we would have correctly
rejected the wrong fix.
karlb added a commit that referenced this pull request Dec 8, 2025
* Better CIP-64 GASPRICE opcode test

The previous test case often passed even with wrong implementations
because it only noticed if a single `if` condition on the gas price
triggers. Instead, the actual gas price return value should be part of
the tested result to notice any deviations from the expected value.

This is achieved by emitting the result in an event/log so that it
becomes part of the receipt. Full bytecode explanation:

| Offset | Bytecode | Opcode       | Stack (after)   | Description                              |
|--------|----------|--------------|-----------------|------------------------------------------|
| 0x00   | `3a`     | `GASPRICE`   | `[gasPrice]`    | Pushes the tx's gas price onto the stack |
| 0x01   | `60 00`  | `PUSH1 0x00` | `[0, gasPrice]` | Pushes memory offset 0                   |
| 0x03   | `52`     | `MSTORE`     | `[]`            | Stores gasPrice at memory[0:32]          |
| 0x04   | `60 20`  | `PUSH1 0x20` | `[32]`          | Pushes 32 (0x20) - the size in bytes     |
| 0x06   | `60 00`  | `PUSH1 0x00` | `[0, 32]`       | Pushes memory offset 0                   |
| 0x08   | `a0`     | `LOG0`       | `[]`            | Emits anonymous log from memory[0:32]    |

As intended, the test behaves like this:
```
fail
cd86616 Fix CIP-64 gas price opcode (#106)
fail
9d02406 CIP-64: actual GASPRICE opcode fix (#107)
pass (the missing revert has no effect on the returned gas price)
7be19b3 Revert bad fix for GASPRICE opcode (#109)
pass
```
So if we had the test before doing the changes, we would have correctly
rejected the wrong fix.

* Fix typos

Co-authored-by: Paul Lange <palango@users.noreply.github.com>

---------

Co-authored-by: Paul Lange <palango@users.noreply.github.com>
karlb added a commit that referenced this pull request Dec 8, 2025
The previous fix was not correct and only accidentally made the tests
pass. The GASPRICE opcodes fetches the effective gas price and passes in
the base fee in native tokens. We work around this by calculating the
correct effective gas price in advance and ignoring the passed in base
fee.
karlb added a commit that referenced this pull request Dec 8, 2025
* Better CIP-64 GASPRICE opcode test

The previous test case often passed even with wrong implementations
because it only noticed if a single `if` condition on the gas price
triggers. Instead, the actual gas price return value should be part of
the tested result to notice any deviations from the expected value.

This is achieved by emitting the result in an event/log so that it
becomes part of the receipt. Full bytecode explanation:

| Offset | Bytecode | Opcode       | Stack (after)   | Description                              |
|--------|----------|--------------|-----------------|------------------------------------------|
| 0x00   | `3a`     | `GASPRICE`   | `[gasPrice]`    | Pushes the tx's gas price onto the stack |
| 0x01   | `60 00`  | `PUSH1 0x00` | `[0, gasPrice]` | Pushes memory offset 0                   |
| 0x03   | `52`     | `MSTORE`     | `[]`            | Stores gasPrice at memory[0:32]          |
| 0x04   | `60 20`  | `PUSH1 0x20` | `[32]`          | Pushes 32 (0x20) - the size in bytes     |
| 0x06   | `60 00`  | `PUSH1 0x00` | `[0, 32]`       | Pushes memory offset 0                   |
| 0x08   | `a0`     | `LOG0`       | `[]`            | Emits anonymous log from memory[0:32]    |

As intended, the test behaves like this:
```
fail
cd86616 Fix CIP-64 gas price opcode (#106)
fail
9d02406 CIP-64: actual GASPRICE opcode fix (#107)
pass (the missing revert has no effect on the returned gas price)
7be19b3 Revert bad fix for GASPRICE opcode (#109)
pass
```
So if we had the test before doing the changes, we would have correctly
rejected the wrong fix.

* Fix typos

Co-authored-by: Paul Lange <palango@users.noreply.github.com>

---------

Co-authored-by: Paul Lange <palango@users.noreply.github.com>
karlb added a commit that referenced this pull request Dec 8, 2025
* Bump hokulea to v1.0.3 which fixed the maximal blob size from 4MiB to maximal 2^28 MiB (#105)

* Fix CIP-64 gas price opcode (#106)

* CIP-64: GASPRICE opcode must return effective gas price

* Add fixtures including CIP-64 tx with GASPRICE opcode

* Remove redundant fixture

* CIP-64: actual GASPRICE opcode fix (#107)

The previous fix was not correct and only accidentally made the tests
pass. The GASPRICE opcodes fetches the effective gas price and passes in
the base fee in native tokens. We work around this by calculating the
correct effective gas price in advance and ignoring the passed in base
fee.

* Revert bad fix for GASPRICE opcode (#109)

Revert the bad fix in fa7fd99. The
correct fix is in 76bad58.

* Better CIP-64 GASPRICE opcode test (#111)

* Better CIP-64 GASPRICE opcode test

The previous test case often passed even with wrong implementations
because it only noticed if a single `if` condition on the gas price
triggers. Instead, the actual gas price return value should be part of
the tested result to notice any deviations from the expected value.

This is achieved by emitting the result in an event/log so that it
becomes part of the receipt. Full bytecode explanation:

| Offset | Bytecode | Opcode       | Stack (after)   | Description                              |
|--------|----------|--------------|-----------------|------------------------------------------|
| 0x00   | `3a`     | `GASPRICE`   | `[gasPrice]`    | Pushes the tx's gas price onto the stack |
| 0x01   | `60 00`  | `PUSH1 0x00` | `[0, gasPrice]` | Pushes memory offset 0                   |
| 0x03   | `52`     | `MSTORE`     | `[]`            | Stores gasPrice at memory[0:32]          |
| 0x04   | `60 20`  | `PUSH1 0x20` | `[32]`          | Pushes 32 (0x20) - the size in bytes     |
| 0x06   | `60 00`  | `PUSH1 0x00` | `[0, 32]`       | Pushes memory offset 0                   |
| 0x08   | `a0`     | `LOG0`       | `[]`            | Emits anonymous log from memory[0:32]    |

As intended, the test behaves like this:
```
fail
cd86616 Fix CIP-64 gas price opcode (#106)
fail
9d02406 CIP-64: actual GASPRICE opcode fix (#107)
pass (the missing revert has no effect on the returned gas price)
7be19b3 Revert bad fix for GASPRICE opcode (#109)
pass
```
So if we had the test before doing the changes, we would have correctly
rejected the wrong fix.

* Fix typos

Co-authored-by: Paul Lange <palango@users.noreply.github.com>

---------

Co-authored-by: Paul Lange <palango@users.noreply.github.com>

---------

Co-authored-by: Seola Oh <osa8361@gmail.com>
Co-authored-by: Paul Lange <palango@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants