ox
Version:
Ethereum Standard Library
385 lines (372 loc) • 10.3 kB
text/typescript
import { AbiParameters } from 'ox'
import { describe, expect, test } from 'vp/test'
import { address } from '../../../test/constants/addresses.js'
describe('encodePacked', () => {
test.each([
{
types: [],
values: [],
expected: '0x',
},
{
types: ['address'],
values: [address.vitalik],
expected: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
},
{
types: ['string'],
values: ['hello world'],
expected: '0x68656c6c6f20776f726c64',
},
{
types: ['bytes'],
values: ['0xdeadbeef'],
expected: '0xdeadbeef',
},
{
types: ['bool'],
values: [true],
expected: '0x01',
},
{
types: ['uint'],
values: [69420n],
expected:
'0x0000000000000000000000000000000000000000000000000000000000010f2c',
},
{
types: ['uint8'],
values: [200],
expected: '0xc8',
},
{
types: ['uint48'],
values: [20123120],
expected: '0x000001330df0',
},
{
types: ['uint128'],
values: [20123120n],
expected: '0x00000000000000000000000001330df0',
},
{
types: ['int'],
values: [69420n],
expected:
'0x0000000000000000000000000000000000000000000000000000000000010f2c',
},
{
types: ['int'],
values: [-69420n],
expected:
'0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef0d4',
},
{
types: ['int8'],
values: [121],
expected: '0x79',
},
{
types: ['int8'],
values: [-121],
expected: '0x87',
},
{
types: ['int48'],
values: [121231],
expected: '0x00000001d98f',
},
{
types: ['int48'],
values: [-1212311],
expected: '0xffffffed8069',
},
{
types: ['int128'],
values: [12312312],
expected: '0x00000000000000000000000000bbdef8',
},
{
types: ['int128'],
values: [-121231231211],
expected: '0xffffffffffffffffffffffe3c60e3715',
},
{
types: ['bytes'],
values: ['0xdeadbeef'],
expected: '0xdeadbeef',
},
{
types: ['bytes4'],
values: ['0xdeadbeef'],
expected: '0xdeadbeef',
},
{
types: ['bytes8'],
values: ['0xdeadeefdeaadbeef'],
expected: '0xdeadeefdeaadbeef',
},
{
types: ['bytes16'],
values: ['0xdeadeefdeaadbeefdeadeefdeaadbeef'],
expected: '0xdeadeefdeaadbeefdeadeefdeaadbeef',
},
{
types: ['address[]'],
values: [[address.vitalik, address.usdcHolder]],
expected:
'0x000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa960450000000000000000000000005414d89a8bf7e99d732bc52f3e6a3ef461c0c078',
},
{
types: ['address[2]'],
values: [[address.vitalik, address.usdcHolder]],
expected:
'0x000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa960450000000000000000000000005414d89a8bf7e99d732bc52f3e6a3ef461c0c078',
},
{
types: ['address[][]'],
values: [[[address.vitalik, address.usdcHolder], [address.burn]]],
expected:
'0x000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa960450000000000000000000000005414d89a8bf7e99d732bc52f3e6a3ef461c0c0780000000000000000000000000000000000000000000000000000000000000000',
},
{
types: ['string[]'],
values: [['hello', 'world']],
expected: '0x68656c6c6f776f726c64',
},
{
types: ['string[][]'],
values: [[['hello', 'world'], ['lol']]],
expected: '0x68656c6c6f776f726c646c6f6c',
},
{
types: ['bytes[]'],
values: [['0xdead', '0xbeef']],
expected: '0xdeadbeef',
},
{
types: ['bytes[]'],
values: [['0x', '0xbeef']],
expected: '0xbeef',
},
{
types: ['bytes[]'],
values: [[]],
expected: '0x',
},
{
types: ['bool[]'],
values: [[true, false, true]],
expected:
'0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001',
},
{
types: ['uint[]'],
values: [[69420n, 42069n]],
expected:
'0x0000000000000000000000000000000000000000000000000000000000010f2c000000000000000000000000000000000000000000000000000000000000a455',
},
{
types: ['uint8[]'],
values: [[200, 201]],
expected:
'0x00000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000c9',
},
{
types: ['int[]'],
values: [[20123120n, 20123121n]],
expected:
'0x0000000000000000000000000000000000000000000000000000000001330df00000000000000000000000000000000000000000000000000000000001330df1',
},
{
types: ['bytes4[]'],
values: [['0xdeadbeef', '0xcafebabe']],
expected:
'0xdeadbeef00000000000000000000000000000000000000000000000000000000cafebabe00000000000000000000000000000000000000000000000000000000',
},
{
types: ['bytes16[]'],
values: [
[
'0xdeadbeefdeadbeefdeadbeefdeadbeef',
'0xcafebabecafebabecafebabecafebabe',
],
],
expected:
'0xdeadbeefdeadbeefdeadbeefdeadbeef00000000000000000000000000000000cafebabecafebabecafebabecafebabe00000000000000000000000000000000',
},
{
types: ['address', 'string'],
values: [address.vitalik, 'hello world'],
expected:
'0xd8da6bf26964af9d7eed9e03e53415d37aa9604568656c6c6f20776f726c64',
},
{
types: ['address', 'string', 'bytes4[]'],
values: [address.vitalik, 'hello world', ['0xdeadbeef', '0xcafebabe']],
expected:
'0xd8da6bf26964af9d7eed9e03e53415d37aa9604568656c6c6f20776f726c64deadbeef00000000000000000000000000000000000000000000000000000000cafebabe00000000000000000000000000000000000000000000000000000000',
},
])(
"encodePacked($types, $values) -> '$expected'",
({ types, values, expected }) => {
expect(AbiParameters.encodePacked(types, values)).toBe(expected)
},
)
test('error: invalid address', () => {
expect(() => AbiParameters.encodePacked(['address'], ['0xdeadbeef']))
.toThrowErrorMatchingInlineSnapshot(`
[Address.InvalidAddressError: Address "0xdeadbeef" is invalid.
Details: Address is not a 20 byte (40 hexadecimal character) value.]
`)
})
test('error: length mismatch', () => {
expect(
// @ts-expect-error
() => AbiParameters.encodePacked(['address'], [address.vitalik, '0x']),
).toThrowErrorMatchingInlineSnapshot(`
[AbiParameters.LengthMismatchError: ABI encoding parameters/values length mismatch.
Expected length (parameters): 1
Given length (values): 2]
`)
})
test('error: bytes size mismatch', () => {
expect(() =>
AbiParameters.encodePacked(['bytes8'], ['0xdeadbeef']),
).toThrowErrorMatchingInlineSnapshot(
`[AbiParameters.BytesSizeMismatchError: Size of bytes "0xdeadbeef" (bytes4) does not match expected size (bytes8).]`,
)
})
test('error: unsupported type', () => {
expect(
// @ts-expect-error
() => AbiParameters.encodePacked(['function'], ['0x']),
).toThrowErrorMatchingInlineSnapshot(
'[AbiParameters.InvalidTypeError: Type `function` is not a valid ABI Type.]',
)
})
test('error: fixed-array length mismatch', () => {
expect(() =>
// @ts-expect-error
AbiParameters.encodePacked(['uint256[2]'], [[1n, 2n, 3n]]),
).toThrowErrorMatchingInlineSnapshot(
'[AbiParameters.ArrayLengthMismatchError: Array length mismatch for type `uint256[2]`. Expected: `2`. Given: `3`.]',
)
})
})
describe('from', () => {
test('default', () => {
{
const abiItem = AbiParameters.from([
{
name: 'spender',
type: 'address',
},
{
name: 'amount',
type: 'uint256',
},
])
expect(abiItem).toMatchInlineSnapshot(`
[
{
"name": "spender",
"type": "address",
},
{
"name": "amount",
"type": "uint256",
},
]
`)
}
{
const abiItem = AbiParameters.from('address spender, uint256 amount')
expect(abiItem).toMatchInlineSnapshot(`
[
{
"name": "spender",
"type": "address",
},
{
"name": "amount",
"type": "uint256",
},
]
`)
}
{
const abiItem = AbiParameters.from([
'struct Foo { address owner; address spender; uint256 amount; }',
'Foo foo, address bar',
])
expect(abiItem).toMatchInlineSnapshot(`
[
{
"components": [
{
"name": "owner",
"type": "address",
},
{
"name": "spender",
"type": "address",
},
{
"name": "amount",
"type": "uint256",
},
],
"name": "foo",
"type": "tuple",
},
{
"name": "bar",
"type": "address",
},
]
`)
}
})
})
describe('format', () => {
test('default', () => {
const parameters = AbiParameters.from([
{
name: 'spender',
type: 'address',
},
{
name: 'amount',
type: 'uint256',
},
])
const formatted = AbiParameters.format(parameters)
expect(formatted).toMatchInlineSnapshot(`"address spender, uint256 amount"`)
})
})
test('exports', () => {
expect(Object.keys(AbiParameters)).toMatchInlineSnapshot(`
[
"InvalidAbiParametersError",
"InvalidAbiTypeParameterError",
"InvalidFunctionModifierError",
"InvalidModifierError",
"InvalidParameterError",
"SolidityProtectedKeywordError",
"InvalidParenthesisError",
"decode",
"encode",
"encodePacked",
"format",
"from",
"DataSizeTooSmallError",
"ZeroDataError",
"ArrayLengthMismatchError",
"BytesSizeMismatchError",
"LengthMismatchError",
"InvalidArrayError",
"InvalidTypeError",
]
`)
})