ox 1.8.12 → 1.8.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/core/TxEnvelope.d.ts.map +1 -1
- package/dist/core/TxEnvelope.js +5 -3
- package/dist/core/TxEnvelope.js.map +1 -1
- package/dist/core/TxEnvelopeEip1559.d.ts.map +1 -1
- package/dist/core/TxEnvelopeEip1559.js +6 -2
- package/dist/core/TxEnvelopeEip1559.js.map +1 -1
- package/dist/core/TxEnvelopeEip4844.d.ts.map +1 -1
- package/dist/core/TxEnvelopeEip4844.js +4 -0
- package/dist/core/TxEnvelopeEip4844.js.map +1 -1
- package/dist/core/TxEnvelopeEip7702.d.ts.map +1 -1
- package/dist/core/TxEnvelopeEip7702.js +4 -0
- package/dist/core/TxEnvelopeEip7702.js.map +1 -1
- package/dist/core/TypedData.d.ts +8 -1
- package/dist/core/TypedData.d.ts.map +1 -1
- package/dist/core/TypedData.js +51 -14
- package/dist/core/TypedData.js.map +1 -1
- package/dist/core/internal/abiItem.d.ts.map +1 -1
- package/dist/core/internal/abiItem.js +44 -13
- package/dist/core/internal/abiItem.js.map +1 -1
- package/dist/core/internal/abiParameters.d.ts +2 -2
- package/dist/core/internal/abiParameters.d.ts.map +1 -1
- package/dist/core/internal/abiParameters.js +24 -7
- package/dist/core/internal/abiParameters.js.map +1 -1
- package/dist/core/internal/rpcSchemas/eth.d.ts +3 -2
- package/dist/core/internal/rpcSchemas/eth.d.ts.map +1 -1
- package/dist/tempo/KeyAuthorization.d.ts +21 -6
- package/dist/tempo/KeyAuthorization.d.ts.map +1 -1
- package/dist/tempo/KeyAuthorization.js +7 -4
- package/dist/tempo/KeyAuthorization.js.map +1 -1
- package/dist/tempo/TxEnvelopeTempo.d.ts.map +1 -1
- package/dist/tempo/TxEnvelopeTempo.js +6 -2
- package/dist/tempo/TxEnvelopeTempo.js.map +1 -1
- package/package.json +5 -2
- package/src/core/TxEnvelope.ts +5 -3
- package/src/core/TxEnvelopeEip1559.ts +8 -2
- package/src/core/TxEnvelopeEip4844.ts +6 -0
- package/src/core/TxEnvelopeEip7702.ts +6 -0
- package/src/core/TypedData.ts +57 -13
- package/src/core/_test/AbiItem.test.ts +238 -4
- package/src/core/_test/AbiParameters.decode.test.ts +140 -1
- package/src/core/_test/RpcSchema.test-d.ts +23 -1
- package/src/core/_test/TransactionEnvelopeEip1559.test.ts +24 -0
- package/src/core/_test/TransactionEnvelopeEip4844.test.ts +13 -0
- package/src/core/_test/TransactionEnvelopeEip7702.test.ts +13 -0
- package/src/core/_test/TypedData.test.ts +188 -1
- package/src/core/internal/abiItem.ts +48 -17
- package/src/core/internal/abiParameters.ts +26 -8
- package/src/core/internal/rpcSchemas/eth.ts +2 -1
- package/src/tempo/KeyAuthorization.test.ts +6 -4
- package/src/tempo/KeyAuthorization.ts +26 -8
- package/src/tempo/TxEnvelopeTempo.test.ts +26 -0
- package/src/tempo/TxEnvelopeTempo.ts +8 -2
- package/src/tempo/e2e.test.ts +73 -17
- package/src/version.ts +1 -1
|
@@ -1021,7 +1021,201 @@ describe('fromAbi', () => {
|
|
|
1021
1021
|
`)
|
|
1022
1022
|
})
|
|
1023
1023
|
|
|
1024
|
+
test('behavior: overloads: bytes32 vs bytes', () => {
|
|
1025
|
+
expect(() =>
|
|
1026
|
+
AbiItem.fromAbi(
|
|
1027
|
+
Abi.from([
|
|
1028
|
+
'function isValidSignature(bytes32 hash, bytes signature)',
|
|
1029
|
+
'function isValidSignature(bytes data, bytes signature)',
|
|
1030
|
+
]),
|
|
1031
|
+
'isValidSignature',
|
|
1032
|
+
{
|
|
1033
|
+
args: [
|
|
1034
|
+
'0x0000000000000000000000000000000000000000000000000000000000000001',
|
|
1035
|
+
'0x1234',
|
|
1036
|
+
],
|
|
1037
|
+
},
|
|
1038
|
+
),
|
|
1039
|
+
).toThrowErrorMatchingInlineSnapshot(`
|
|
1040
|
+
[AbiItem.AmbiguityError: Found ambiguous types in overloaded ABI Items.
|
|
1041
|
+
|
|
1042
|
+
\`bytes\` in \`isValidSignature(bytes,bytes)\`, and
|
|
1043
|
+
\`bytes32\` in \`isValidSignature(bytes32,bytes)\`
|
|
1044
|
+
|
|
1045
|
+
These types encode differently and cannot be distinguished at runtime.
|
|
1046
|
+
Remove one of the ambiguous items in the ABI.]
|
|
1047
|
+
`)
|
|
1048
|
+
})
|
|
1049
|
+
|
|
1050
|
+
test('behavior: overloads: uint256 vs int256', () => {
|
|
1051
|
+
expect(() =>
|
|
1052
|
+
AbiItem.fromAbi(
|
|
1053
|
+
Abi.from(['function foo(uint256 x)', 'function foo(int256 x)']),
|
|
1054
|
+
'foo',
|
|
1055
|
+
{ args: [1n] },
|
|
1056
|
+
),
|
|
1057
|
+
).toThrowErrorMatchingInlineSnapshot(`
|
|
1058
|
+
[AbiItem.AmbiguityError: Found ambiguous types in overloaded ABI Items.
|
|
1059
|
+
|
|
1060
|
+
\`int256\` in \`foo(int256)\`, and
|
|
1061
|
+
\`uint256\` in \`foo(uint256)\`
|
|
1062
|
+
|
|
1063
|
+
These types encode differently and cannot be distinguished at runtime.
|
|
1064
|
+
Remove one of the ambiguous items in the ABI.]
|
|
1065
|
+
`)
|
|
1066
|
+
|
|
1067
|
+
expect(
|
|
1068
|
+
AbiItem.fromAbi(
|
|
1069
|
+
Abi.from(['function foo(uint256 x)', 'function foo(int256 x)']),
|
|
1070
|
+
'foo',
|
|
1071
|
+
{ args: [-1n] },
|
|
1072
|
+
).inputs,
|
|
1073
|
+
).toMatchInlineSnapshot(`
|
|
1074
|
+
[
|
|
1075
|
+
{
|
|
1076
|
+
"name": "x",
|
|
1077
|
+
"type": "int256",
|
|
1078
|
+
},
|
|
1079
|
+
]
|
|
1080
|
+
`)
|
|
1081
|
+
})
|
|
1082
|
+
|
|
1083
|
+
test('behavior: overloads: uint256[] vs uint256[2]', () => {
|
|
1084
|
+
expect(() =>
|
|
1085
|
+
AbiItem.fromAbi(
|
|
1086
|
+
Abi.from(['function foo(uint256[] x)', 'function foo(uint256[2] x)']),
|
|
1087
|
+
'foo',
|
|
1088
|
+
{ args: [[1n, 1n]] },
|
|
1089
|
+
),
|
|
1090
|
+
).toThrowErrorMatchingInlineSnapshot(`
|
|
1091
|
+
[AbiItem.AmbiguityError: Found ambiguous types in overloaded ABI Items.
|
|
1092
|
+
|
|
1093
|
+
\`uint256[2]\` in \`foo(uint256[2])\`, and
|
|
1094
|
+
\`uint256[]\` in \`foo(uint256[])\`
|
|
1095
|
+
|
|
1096
|
+
These types encode differently and cannot be distinguished at runtime.
|
|
1097
|
+
Remove one of the ambiguous items in the ABI.]
|
|
1098
|
+
`)
|
|
1099
|
+
|
|
1100
|
+
expect(
|
|
1101
|
+
AbiItem.fromAbi(
|
|
1102
|
+
Abi.from(['function foo(uint256[] x)', 'function foo(uint256[2] x)']),
|
|
1103
|
+
'foo',
|
|
1104
|
+
{ args: [[1n, 1n, 1n]] },
|
|
1105
|
+
).inputs,
|
|
1106
|
+
).toMatchInlineSnapshot(`
|
|
1107
|
+
[
|
|
1108
|
+
{
|
|
1109
|
+
"name": "x",
|
|
1110
|
+
"type": "uint256[]",
|
|
1111
|
+
},
|
|
1112
|
+
]
|
|
1113
|
+
`)
|
|
1114
|
+
})
|
|
1115
|
+
|
|
1116
|
+
test('behavior: overloads: uint256[2][] vs uint256[][2]', () => {
|
|
1117
|
+
expect(() =>
|
|
1118
|
+
AbiItem.fromAbi(
|
|
1119
|
+
Abi.from([
|
|
1120
|
+
'function foo(uint256[2][] x)',
|
|
1121
|
+
'function foo(uint256[][2] x)',
|
|
1122
|
+
]),
|
|
1123
|
+
'foo',
|
|
1124
|
+
{
|
|
1125
|
+
args: [
|
|
1126
|
+
[
|
|
1127
|
+
[1n, 1n],
|
|
1128
|
+
[1n, 1n],
|
|
1129
|
+
],
|
|
1130
|
+
],
|
|
1131
|
+
},
|
|
1132
|
+
),
|
|
1133
|
+
).toThrowErrorMatchingInlineSnapshot(`
|
|
1134
|
+
[AbiItem.AmbiguityError: Found ambiguous types in overloaded ABI Items.
|
|
1135
|
+
|
|
1136
|
+
\`uint256[]\` in \`foo(uint256[][2])\`, and
|
|
1137
|
+
\`uint256[2]\` in \`foo(uint256[2][])\`
|
|
1138
|
+
|
|
1139
|
+
These types encode differently and cannot be distinguished at runtime.
|
|
1140
|
+
Remove one of the ambiguous items in the ABI.]
|
|
1141
|
+
`)
|
|
1142
|
+
})
|
|
1143
|
+
|
|
1144
|
+
test('behavior: overloads: selector chooses one of two matches', () => {
|
|
1145
|
+
expect(
|
|
1146
|
+
AbiItem.fromAbi(
|
|
1147
|
+
Abi.from([
|
|
1148
|
+
'function isValidSignature(bytes32 hash, bytes signature)',
|
|
1149
|
+
'function isValidSignature(bytes data, bytes signature)',
|
|
1150
|
+
]),
|
|
1151
|
+
'0x1626ba7e',
|
|
1152
|
+
{
|
|
1153
|
+
args: [
|
|
1154
|
+
'0x0000000000000000000000000000000000000000000000000000000000000001',
|
|
1155
|
+
'0x1234',
|
|
1156
|
+
],
|
|
1157
|
+
},
|
|
1158
|
+
).inputs,
|
|
1159
|
+
).toMatchInlineSnapshot(`
|
|
1160
|
+
[
|
|
1161
|
+
{
|
|
1162
|
+
"name": "hash",
|
|
1163
|
+
"type": "bytes32",
|
|
1164
|
+
},
|
|
1165
|
+
{
|
|
1166
|
+
"name": "signature",
|
|
1167
|
+
"type": "bytes",
|
|
1168
|
+
},
|
|
1169
|
+
]
|
|
1170
|
+
`)
|
|
1171
|
+
})
|
|
1172
|
+
|
|
1024
1173
|
describe('getAmbiguousTypes', () => {
|
|
1174
|
+
test('bytes', () => {
|
|
1175
|
+
expect(
|
|
1176
|
+
getAmbiguousTypes(
|
|
1177
|
+
AbiParameters.from('bytes32'),
|
|
1178
|
+
AbiParameters.from('bytes'),
|
|
1179
|
+
[
|
|
1180
|
+
'0x0000000000000000000000000000000000000000000000000000000000000001',
|
|
1181
|
+
],
|
|
1182
|
+
),
|
|
1183
|
+
).toMatchInlineSnapshot(`
|
|
1184
|
+
[
|
|
1185
|
+
"bytes32",
|
|
1186
|
+
"bytes",
|
|
1187
|
+
]
|
|
1188
|
+
`)
|
|
1189
|
+
})
|
|
1190
|
+
|
|
1191
|
+
test('integers', () => {
|
|
1192
|
+
expect(
|
|
1193
|
+
getAmbiguousTypes(
|
|
1194
|
+
AbiParameters.from('uint256'),
|
|
1195
|
+
AbiParameters.from('int256'),
|
|
1196
|
+
[1n],
|
|
1197
|
+
),
|
|
1198
|
+
).toMatchInlineSnapshot(`
|
|
1199
|
+
[
|
|
1200
|
+
"uint256",
|
|
1201
|
+
"int256",
|
|
1202
|
+
]
|
|
1203
|
+
`)
|
|
1204
|
+
|
|
1205
|
+
expect(
|
|
1206
|
+
getAmbiguousTypes(
|
|
1207
|
+
AbiParameters.from('uint256'),
|
|
1208
|
+
AbiParameters.from('uint128'),
|
|
1209
|
+
[69420n],
|
|
1210
|
+
),
|
|
1211
|
+
).toMatchInlineSnapshot(`
|
|
1212
|
+
[
|
|
1213
|
+
"uint256",
|
|
1214
|
+
"uint128",
|
|
1215
|
+
]
|
|
1216
|
+
`)
|
|
1217
|
+
})
|
|
1218
|
+
|
|
1025
1219
|
test('string/address', () => {
|
|
1026
1220
|
expect(
|
|
1027
1221
|
getAmbiguousTypes(
|
|
@@ -1163,7 +1357,7 @@ describe('fromAbi', () => {
|
|
|
1163
1357
|
expect(
|
|
1164
1358
|
getAmbiguousTypes(
|
|
1165
1359
|
AbiParameters.from('uint256, (address)'),
|
|
1166
|
-
AbiParameters.from('
|
|
1360
|
+
AbiParameters.from('uint256, (bytes20)'),
|
|
1167
1361
|
[69420n, ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e']],
|
|
1168
1362
|
),
|
|
1169
1363
|
).toMatchInlineSnapshot(`
|
|
@@ -1175,7 +1369,7 @@ describe('fromAbi', () => {
|
|
|
1175
1369
|
expect(
|
|
1176
1370
|
getAmbiguousTypes(
|
|
1177
1371
|
AbiParameters.from('uint256, (string, (address))'),
|
|
1178
|
-
AbiParameters.from('
|
|
1372
|
+
AbiParameters.from('uint256, (string, (bytes20))'),
|
|
1179
1373
|
[69420n, ['foo', ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e']]],
|
|
1180
1374
|
),
|
|
1181
1375
|
).toMatchInlineSnapshot(`
|
|
@@ -1187,7 +1381,7 @@ describe('fromAbi', () => {
|
|
|
1187
1381
|
expect(
|
|
1188
1382
|
getAmbiguousTypes(
|
|
1189
1383
|
AbiParameters.from('uint256, (string, (address, bytes))'),
|
|
1190
|
-
AbiParameters.from('
|
|
1384
|
+
AbiParameters.from('uint256, (string, (bytes20, address))'),
|
|
1191
1385
|
[
|
|
1192
1386
|
123n,
|
|
1193
1387
|
[
|
|
@@ -1360,7 +1554,19 @@ describe('fromAbi', () => {
|
|
|
1360
1554
|
{ arg: 'true', abiParameter: { type: 'bool' }, expected: false },
|
|
1361
1555
|
// bytes
|
|
1362
1556
|
{ arg: 'foo', abiParameter: { type: 'bytes' }, expected: true },
|
|
1363
|
-
{ arg: 'foo', abiParameter: { type: 'bytes32' }, expected:
|
|
1557
|
+
{ arg: 'foo', abiParameter: { type: 'bytes32' }, expected: false },
|
|
1558
|
+
{ arg: '0x1234', abiParameter: { type: 'bytes2' }, expected: true },
|
|
1559
|
+
{ arg: '0x1234', abiParameter: { type: 'bytes4' }, expected: false },
|
|
1560
|
+
{
|
|
1561
|
+
arg: Bytes.fromString('foo'),
|
|
1562
|
+
abiParameter: { type: 'bytes3' },
|
|
1563
|
+
expected: true,
|
|
1564
|
+
},
|
|
1565
|
+
{
|
|
1566
|
+
arg: Bytes.fromString('foo'),
|
|
1567
|
+
abiParameter: { type: 'bytes4' },
|
|
1568
|
+
expected: false,
|
|
1569
|
+
},
|
|
1364
1570
|
{
|
|
1365
1571
|
arg: Bytes.fromString('foo'),
|
|
1366
1572
|
abiParameter: { type: 'bytes' },
|
|
@@ -1381,6 +1587,34 @@ describe('fromAbi', () => {
|
|
|
1381
1587
|
{ arg: 1, abiParameter: { type: 'uint256' }, expected: true },
|
|
1382
1588
|
{ arg: 1, abiParameter: { type: 'int69' }, expected: false },
|
|
1383
1589
|
{ arg: 1, abiParameter: { type: 'uint69' }, expected: false },
|
|
1590
|
+
{ arg: -129, abiParameter: { type: 'int8' }, expected: false },
|
|
1591
|
+
{ arg: -128, abiParameter: { type: 'int8' }, expected: true },
|
|
1592
|
+
{ arg: 127, abiParameter: { type: 'int8' }, expected: true },
|
|
1593
|
+
{ arg: 128, abiParameter: { type: 'int8' }, expected: false },
|
|
1594
|
+
{ arg: -1n, abiParameter: { type: 'uint8' }, expected: false },
|
|
1595
|
+
{ arg: 0n, abiParameter: { type: 'uint8' }, expected: true },
|
|
1596
|
+
{ arg: 255n, abiParameter: { type: 'uint8' }, expected: true },
|
|
1597
|
+
{ arg: 256n, abiParameter: { type: 'uint8' }, expected: false },
|
|
1598
|
+
{ arg: 2n ** 256n - 1n, abiParameter: { type: 'uint256' }, expected: true },
|
|
1599
|
+
{ arg: 2n ** 256n, abiParameter: { type: 'uint256' }, expected: false },
|
|
1600
|
+
{ arg: -(2n ** 255n), abiParameter: { type: 'int256' }, expected: true },
|
|
1601
|
+
{
|
|
1602
|
+
arg: -(2n ** 255n) - 1n,
|
|
1603
|
+
abiParameter: { type: 'int256' },
|
|
1604
|
+
expected: false,
|
|
1605
|
+
},
|
|
1606
|
+
{ arg: Number.NaN, abiParameter: { type: 'uint256' }, expected: false },
|
|
1607
|
+
{
|
|
1608
|
+
arg: Number.POSITIVE_INFINITY,
|
|
1609
|
+
abiParameter: { type: 'uint256' },
|
|
1610
|
+
expected: false,
|
|
1611
|
+
},
|
|
1612
|
+
{ arg: 1.5, abiParameter: { type: 'uint256' }, expected: false },
|
|
1613
|
+
{
|
|
1614
|
+
arg: Number.MAX_SAFE_INTEGER + 1,
|
|
1615
|
+
abiParameter: { type: 'uint256' },
|
|
1616
|
+
expected: true,
|
|
1617
|
+
},
|
|
1384
1618
|
// string
|
|
1385
1619
|
{ arg: 'foo', abiParameter: { type: 'string' }, expected: true },
|
|
1386
1620
|
{ arg: 1, abiParameter: { type: 'string' }, expected: false },
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AbiItem, AbiParameters,
|
|
1
|
+
import { AbiItem, AbiParameters, Address, Bytes, Hex } from 'ox'
|
|
2
2
|
import { assertType, describe, expect, test } from 'vp/test'
|
|
3
3
|
|
|
4
4
|
import {
|
|
@@ -1887,3 +1887,142 @@ describe('zero-width types', () => {
|
|
|
1887
1887
|
}
|
|
1888
1888
|
})
|
|
1889
1889
|
})
|
|
1890
|
+
|
|
1891
|
+
describe('integer range', () => {
|
|
1892
|
+
test('uint8: max', () => {
|
|
1893
|
+
expect(
|
|
1894
|
+
AbiParameters.decode(
|
|
1895
|
+
AbiParameters.from('uint8'),
|
|
1896
|
+
'0x00000000000000000000000000000000000000000000000000000000000000ff',
|
|
1897
|
+
),
|
|
1898
|
+
).toEqual([255])
|
|
1899
|
+
})
|
|
1900
|
+
|
|
1901
|
+
test('uint8: above max', () => {
|
|
1902
|
+
expect(() =>
|
|
1903
|
+
AbiParameters.decode(
|
|
1904
|
+
AbiParameters.from('uint8'),
|
|
1905
|
+
'0x0000000000000000000000000000000000000000000000000000000000000100',
|
|
1906
|
+
),
|
|
1907
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
1908
|
+
`[Hex.IntegerOutOfRangeError: Number \`256\` is not in safe 8-bit unsigned integer range (\`0\` to \`255\`)]`,
|
|
1909
|
+
)
|
|
1910
|
+
})
|
|
1911
|
+
|
|
1912
|
+
test('int8: -1', () => {
|
|
1913
|
+
expect(
|
|
1914
|
+
AbiParameters.decode(
|
|
1915
|
+
AbiParameters.from('int8'),
|
|
1916
|
+
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
|
|
1917
|
+
),
|
|
1918
|
+
).toEqual([-1])
|
|
1919
|
+
})
|
|
1920
|
+
|
|
1921
|
+
test('int8: missing sign extension', () => {
|
|
1922
|
+
expect(() =>
|
|
1923
|
+
AbiParameters.decode(
|
|
1924
|
+
AbiParameters.from('int8'),
|
|
1925
|
+
'0x0000000000000000000000000000000000000000000000000000000000000080',
|
|
1926
|
+
),
|
|
1927
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
1928
|
+
`[Hex.IntegerOutOfRangeError: Number \`128\` is not in safe 8-bit signed integer range (\`-128\` to \`127\`)]`,
|
|
1929
|
+
)
|
|
1930
|
+
})
|
|
1931
|
+
|
|
1932
|
+
test('int8: below min', () => {
|
|
1933
|
+
expect(() =>
|
|
1934
|
+
AbiParameters.decode(
|
|
1935
|
+
AbiParameters.from('int8'),
|
|
1936
|
+
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f',
|
|
1937
|
+
),
|
|
1938
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
1939
|
+
`[Hex.IntegerOutOfRangeError: Number \`-129\` is not in safe 8-bit signed integer range (\`-128\` to \`127\`)]`,
|
|
1940
|
+
)
|
|
1941
|
+
})
|
|
1942
|
+
|
|
1943
|
+
test('uint8[]: element above max', () => {
|
|
1944
|
+
expect(() =>
|
|
1945
|
+
AbiParameters.decode(
|
|
1946
|
+
AbiParameters.from('uint8[]'),
|
|
1947
|
+
'0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100',
|
|
1948
|
+
),
|
|
1949
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
1950
|
+
`[Hex.IntegerOutOfRangeError: Number \`256\` is not in safe 8-bit unsigned integer range (\`0\` to \`255\`)]`,
|
|
1951
|
+
)
|
|
1952
|
+
})
|
|
1953
|
+
|
|
1954
|
+
test('uint16: 2^64', () => {
|
|
1955
|
+
expect(() =>
|
|
1956
|
+
AbiParameters.decode(
|
|
1957
|
+
AbiParameters.from('uint16'),
|
|
1958
|
+
'0x0000000000000000000000000000000000000000000000010000000000000000',
|
|
1959
|
+
),
|
|
1960
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
1961
|
+
`[Hex.IntegerOutOfRangeError: Number \`18446744073709551616\` is not in safe 16-bit unsigned integer range (\`0\` to \`65535\`)]`,
|
|
1962
|
+
)
|
|
1963
|
+
})
|
|
1964
|
+
|
|
1965
|
+
test('every size: min and max round-trip, out of range throws', () => {
|
|
1966
|
+
for (let size = 8; size <= 256; size += 8) {
|
|
1967
|
+
for (const signed of [false, true]) {
|
|
1968
|
+
const type = (signed ? 'int' : 'uint') + size
|
|
1969
|
+
const parameters = AbiParameters.from(type)
|
|
1970
|
+
const max = (1n << BigInt(signed ? size - 1 : size)) - 1n
|
|
1971
|
+
const min = signed ? -max - 1n : 0n
|
|
1972
|
+
const cast = (value: bigint) => (size > 48 ? value : Number(value))
|
|
1973
|
+
|
|
1974
|
+
for (const value of [min, max])
|
|
1975
|
+
expect(
|
|
1976
|
+
AbiParameters.decode(
|
|
1977
|
+
parameters,
|
|
1978
|
+
AbiParameters.encode(parameters, [cast(value)] as never),
|
|
1979
|
+
),
|
|
1980
|
+
).toEqual([cast(value)])
|
|
1981
|
+
|
|
1982
|
+
if (size === 256) continue
|
|
1983
|
+
const word = (value: bigint) =>
|
|
1984
|
+
Hex.fromNumber(BigInt.asUintN(256, value), { size: 32 })
|
|
1985
|
+
expect(() => AbiParameters.decode(parameters, word(max + 1n))).toThrow(
|
|
1986
|
+
Hex.IntegerOutOfRangeError,
|
|
1987
|
+
)
|
|
1988
|
+
if (signed)
|
|
1989
|
+
expect(() =>
|
|
1990
|
+
AbiParameters.decode(parameters, word(min - 1n)),
|
|
1991
|
+
).toThrow(Hex.IntegerOutOfRangeError)
|
|
1992
|
+
}
|
|
1993
|
+
}
|
|
1994
|
+
})
|
|
1995
|
+
})
|
|
1996
|
+
|
|
1997
|
+
describe('address padding', () => {
|
|
1998
|
+
test('dirty high bytes', () => {
|
|
1999
|
+
expect(() =>
|
|
2000
|
+
AbiParameters.decode(
|
|
2001
|
+
AbiParameters.from('address'),
|
|
2002
|
+
'0x00000000000000000000000114dc79964da2c08b23698b3d3cc7ca32193d9955',
|
|
2003
|
+
),
|
|
2004
|
+
).toThrowErrorMatchingInlineSnapshot(`
|
|
2005
|
+
[Address.InvalidAddressError: Address "0x00000000000000000000000114dc79964da2c08b23698b3d3cc7ca32193d9955" is invalid.
|
|
2006
|
+
|
|
2007
|
+
Details: Address is not a 20 byte (40 hexadecimal character) value.]
|
|
2008
|
+
`)
|
|
2009
|
+
})
|
|
2010
|
+
|
|
2011
|
+
test('dirty first byte', () => {
|
|
2012
|
+
expect(() =>
|
|
2013
|
+
AbiParameters.decode(
|
|
2014
|
+
AbiParameters.from('address'),
|
|
2015
|
+
'0xff000000000000000000000014dc79964da2c08b23698b3d3cc7ca32193d9955',
|
|
2016
|
+
),
|
|
2017
|
+
).toThrow(Address.InvalidAddressError)
|
|
2018
|
+
})
|
|
2019
|
+
|
|
2020
|
+
test('address[2]: second element dirty', () => {
|
|
2021
|
+
expect(() =>
|
|
2022
|
+
AbiParameters.decode(
|
|
2023
|
+
AbiParameters.from('address[2]'),
|
|
2024
|
+
'0x00000000000000000000000014dc79964da2c08b23698b3d3cc7ca32193d99550000000000000000000000ff14dc79964da2c08b23698b3d3cc7ca32193d9955',
|
|
2025
|
+
),
|
|
2026
|
+
).toThrow(Address.InvalidAddressError)
|
|
2027
|
+
})
|
|
2028
|
+
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RpcSchema } from 'ox'
|
|
1
|
+
import { type Frame, RpcSchema } from 'ox'
|
|
2
2
|
import { z } from 'ox/zod'
|
|
3
3
|
import { describe, expectTypeOf, test } from 'vp/test'
|
|
4
4
|
|
|
@@ -246,6 +246,28 @@ test('frame fill responses do not require raw bytes or lookup metadata', () => {
|
|
|
246
246
|
expectTypeOf(filled).toExtend<Filled>()
|
|
247
247
|
})
|
|
248
248
|
|
|
249
|
+
test('fill responses expose fields not shared by every envelope as optional', () => {
|
|
250
|
+
type Tx = Extract<
|
|
251
|
+
RpcSchema.Eth,
|
|
252
|
+
{ Request: { method: 'eth_fillTransaction' } }
|
|
253
|
+
>['ReturnType']['tx']
|
|
254
|
+
expectTypeOf<Tx['from']>().toEqualTypeOf<`0x${string}`>()
|
|
255
|
+
expectTypeOf<Tx['gas']>().toEqualTypeOf<`0x${string}` | undefined>()
|
|
256
|
+
expectTypeOf<Tx['frames']>().toEqualTypeOf<readonly Frame.Rpc[] | undefined>()
|
|
257
|
+
|
|
258
|
+
type Eip1559 = Extract<Tx, { type: '0x2' }>
|
|
259
|
+
expectTypeOf<Eip1559['gas']>().toEqualTypeOf<`0x${string}` | undefined>()
|
|
260
|
+
expectTypeOf<Eip1559['gasPrice']>().toEqualTypeOf<undefined>()
|
|
261
|
+
expectTypeOf<Eip1559['maxFeePerGas']>().toEqualTypeOf<
|
|
262
|
+
`0x${string}` | undefined
|
|
263
|
+
>()
|
|
264
|
+
expectTypeOf<Eip1559['frames']>().toEqualTypeOf<undefined>()
|
|
265
|
+
|
|
266
|
+
type Eip8141 = Extract<Tx, { type: '0x6' }>
|
|
267
|
+
expectTypeOf<Eip8141['frames']>().toEqualTypeOf<readonly Frame.Rpc[]>()
|
|
268
|
+
expectTypeOf<Eip8141['gas']>().toEqualTypeOf<undefined>()
|
|
269
|
+
})
|
|
270
|
+
|
|
249
271
|
test('frame simulation results expose payer and frame results', () => {
|
|
250
272
|
type Result = Extract<
|
|
251
273
|
RpcSchema.Eth,
|
|
@@ -27,6 +27,18 @@ describe('assert', () => {
|
|
|
27
27
|
)
|
|
28
28
|
})
|
|
29
29
|
|
|
30
|
+
test('tip higher than zero fee cap', () => {
|
|
31
|
+
expect(() =>
|
|
32
|
+
TxEnvelopeEip1559.assert({
|
|
33
|
+
maxFeePerGas: 0n,
|
|
34
|
+
maxPriorityFeePerGas: 1n,
|
|
35
|
+
chainId: 1,
|
|
36
|
+
}),
|
|
37
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
38
|
+
'[TransactionEnvelope.TipAboveFeeCapError: The provided tip (`maxPriorityFeePerGas` = 0.000000001 gwei) cannot be higher than the fee cap (`maxFeePerGas` = 0 gwei).]',
|
|
39
|
+
)
|
|
40
|
+
})
|
|
41
|
+
|
|
30
42
|
test('invalid chainId', () => {
|
|
31
43
|
expect(() =>
|
|
32
44
|
TxEnvelopeEip1559.assert({ chainId: 0 }),
|
|
@@ -225,6 +237,18 @@ describe('deserialize', () => {
|
|
|
225
237
|
})
|
|
226
238
|
|
|
227
239
|
describe('errors', () => {
|
|
240
|
+
test('tip above empty fee cap', () => {
|
|
241
|
+
const serialized = TxEnvelopeEip1559.serialize({
|
|
242
|
+
chainId: 1,
|
|
243
|
+
maxPriorityFeePerGas: 1n,
|
|
244
|
+
})
|
|
245
|
+
expect(() =>
|
|
246
|
+
TxEnvelopeEip1559.deserialize(serialized),
|
|
247
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
248
|
+
`[TransactionEnvelope.TipAboveFeeCapError: The provided tip (\`maxPriorityFeePerGas\` = 0.000000001 gwei) cannot be higher than the fee cap (\`maxFeePerGas\` = 0 gwei).]`,
|
|
249
|
+
)
|
|
250
|
+
})
|
|
251
|
+
|
|
228
252
|
test('invalid access list (invalid address)', () => {
|
|
229
253
|
expect(() =>
|
|
230
254
|
TxEnvelopeEip1559.deserialize(
|
|
@@ -203,6 +203,19 @@ describe('deserialize', () => {
|
|
|
203
203
|
})
|
|
204
204
|
|
|
205
205
|
describe('errors', () => {
|
|
206
|
+
test('tip above empty fee cap', () => {
|
|
207
|
+
const serialized = TxEnvelopeEip4844.serialize({
|
|
208
|
+
blobVersionedHashes,
|
|
209
|
+
chainId: 1,
|
|
210
|
+
maxPriorityFeePerGas: 1n,
|
|
211
|
+
})
|
|
212
|
+
expect(() =>
|
|
213
|
+
TxEnvelopeEip4844.deserialize(serialized),
|
|
214
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
215
|
+
`[TransactionEnvelope.TipAboveFeeCapError: The provided tip (\`maxPriorityFeePerGas\` = 0.000000001 gwei) cannot be higher than the fee cap (\`maxFeePerGas\` = 0 gwei).]`,
|
|
216
|
+
)
|
|
217
|
+
})
|
|
218
|
+
|
|
206
219
|
test('invalid access list (invalid address)', () => {
|
|
207
220
|
expect(() =>
|
|
208
221
|
TxEnvelopeEip4844.deserialize(
|
|
@@ -311,6 +311,19 @@ describe('deserialize', () => {
|
|
|
311
311
|
})
|
|
312
312
|
|
|
313
313
|
describe('errors', () => {
|
|
314
|
+
test('tip above empty fee cap', () => {
|
|
315
|
+
const serialized = TxEnvelopeEip7702.serialize({
|
|
316
|
+
authorizationList: [],
|
|
317
|
+
chainId: 1,
|
|
318
|
+
maxPriorityFeePerGas: 1n,
|
|
319
|
+
})
|
|
320
|
+
expect(() =>
|
|
321
|
+
TxEnvelopeEip7702.deserialize(serialized),
|
|
322
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
323
|
+
`[TransactionEnvelope.TipAboveFeeCapError: The provided tip (\`maxPriorityFeePerGas\` = 0.000000001 gwei) cannot be higher than the fee cap (\`maxFeePerGas\` = 0 gwei).]`,
|
|
324
|
+
)
|
|
325
|
+
})
|
|
326
|
+
|
|
314
327
|
test('invalid access list (invalid address)', () => {
|
|
315
328
|
expect(() =>
|
|
316
329
|
TxEnvelopeEip7702.deserialize(
|