Created
July 17, 2023 15:41
-
-
Save pcaversaccio/49adaf6ad482a59225c3cabb18e2acc3 to your computer and use it in GitHub Desktop.
A Vyper utility function that transforms a standard signature into an EIP-2098 (https://eips.ethereum.org/EIPS/eip-2098) compliant signature.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# @version ^0.3.9 | |
@internal | |
@pure | |
def _to_2098_format(signature: Bytes[65]) -> Bytes[64]: | |
""" | |
@dev Transforms a standard signature into an EIP-2098 | |
(https://eips.ethereum.org/EIPS/eip-2098) compliant | |
signature. | |
@param signature The secp256k1 64/65-bytes signature. | |
@return Bytes The 64-bytes EIP-2098 compliant signature. | |
""" | |
assert len(signature) == 65, "ERC-2098: invalid signature length" | |
assert (convert(slice(signature, 32, 1), uint256) >> 7) != 1, "ERC-2098: invalid signature `s` value" | |
short: Bytes[64] = slice(signature, 0, 64) | |
parity_bit: uint8 = convert((convert(slice(short, 32, 1), uint256) | ((convert(slice(signature, 64, 1), uint256) % 27) << 7)), uint8) | |
return concat(slice(short, 0, 32), convert(parity_bit, bytes1), slice(short, 33, 31)) | |
@external | |
@view | |
def test_to_2098_format(): | |
""" | |
@dev Since Foundry writes tests in Solidity, I can write | |
tests in Vyper :). Use Titanoboa (https://github.com/vyperlang/titanoboa) | |
to run it: | |
```console | |
>>> import boa | |
>>> erc2098 = boa.load("./ERC2098.vy") | |
>>> erc2098.test_to_2098_format() | |
``` | |
@notice The two test cases are from here: | |
https://eips.ethereum.org/EIPS/eip-2098#test-cases. | |
""" | |
r_1: bytes32 = 0x68a020a209d3d56c46f38cc50a33f704f4a9a10a59377f8dd762ac66910e9b90 | |
s_1: bytes32 = 0x7e865ad05c4035ab5792787d4a0297a43617ae897930a6fe4d822b8faea52064 | |
v_1: uint8 = 27 | |
y_parity_and_s_1: bytes32 = 0x7e865ad05c4035ab5792787d4a0297a43617ae897930a6fe4d822b8faea52064 | |
r_2: bytes32 = 0x9328da16089fcba9bececa81663203989f2df5fe1faa6291a45381c81bd17f76 | |
s_2: bytes32 = 0x139c6d6b623b42da56557e5e734a43dc83345ddfadec52cbe24d0cc64f550793 | |
v_2: uint8 = 28 | |
y_parity_and_s_2: bytes32 = 0x939c6d6b623b42da56557e5e734a43dc83345ddfadec52cbe24d0cc64f550793 | |
signature_1: Bytes[65] = concat(r_1, s_1, convert(v_1, bytes1)) | |
signature_2: Bytes[65] = concat(r_2, s_2, convert(v_2, bytes1)) | |
compact_signature_1: Bytes[64] = concat(r_1, y_parity_and_s_1) | |
compact_signature_2: Bytes[64] = concat(r_2, y_parity_and_s_2) | |
assert self._to_2098_format(signature_1) == compact_signature_1, "ERC-2098: invalid signature" | |
assert self._to_2098_format(signature_2) == compact_signature_2, "ERC-2098: invalid signature" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment