Skip to content

Commit

Permalink
fix: resolves #2721
Browse files Browse the repository at this point in the history
  • Loading branch information
jxom committed Sep 14, 2024
1 parent 408948b commit 644f72d
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/grumpy-melons-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"viem": patch
---

Fixed an issue where \`hashAuthorization\` & \`serializeAuthorizationList\` did not RLP-serialize zeroish nonces correctly.
46 changes: 46 additions & 0 deletions src/actions/wallet/sendTransaction.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { maxUint256 } from '~viem/constants/number.js'
import { BatchCallInvoker } from '../../../contracts/generated.js'
import { getSmartAccounts_07 } from '../../../test/src/account-abstraction.js'
import { deploy } from '../../../test/src/utils.js'
import { generatePrivateKey } from '../../accounts/generatePrivateKey.js'
import { createWalletClient } from '../../clients/createWalletClient.js'
import { http } from '../../clients/transports/http.js'
import { signAuthorization } from '../../experimental/index.js'
Expand Down Expand Up @@ -1406,3 +1407,48 @@ describe('errors', () => {
)
})
})

test('https://github.com/wevm/viem/issues/2721', async () => {
const invoker = privateKeyToAccount(generatePrivateKey())
const authority = privateKeyToAccount(generatePrivateKey())
const recipient = privateKeyToAccount(generatePrivateKey())

await setBalance(client, {
address: invoker.address,
value: parseEther('100'),
})
await setBalance(client, {
address: authority.address,
value: parseEther('100'),
})

const { contractAddress } = await deploy(client, {
abi: BatchCallInvoker.abi,
bytecode: BatchCallInvoker.bytecode.object,
})

const authorization = await signAuthorization(client, {
account: authority,
contractAddress: contractAddress!,
})

const hash = await sendTransaction(client, {
account: invoker,
authorizationList: [authorization],
data: encodeFunctionData({
abi: BatchCallInvoker.abi,
functionName: 'execute',
args: [
[
{
to: recipient.address,
data: '0x',
value: parseEther('1'),
},
],
],
}),
to: authority.address,
})
expect(hash).toBeDefined()
})
6 changes: 5 additions & 1 deletion src/experimental/eip7702/utils/hashAuthorization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ export function hashAuthorization<to extends To = 'hex'>(
const hash = keccak256(
concatHex([
'0x05',
toRlp([numberToHex(chainId), contractAddress, numberToHex(nonce)]),
toRlp([
numberToHex(chainId),
contractAddress,
nonce ? numberToHex(nonce) : '0x',
]),
]),
)
if (to === 'bytes') return hexToBytes(hash) as HashAuthorizationReturnType<to>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function serializeAuthorizationList(
serializedAuthorizationList.push([
toHex(chainId),
contractAddress,
toHex(nonce),
nonce ? toHex(nonce) : '0x',
...toYParitySignatureArray({}, signature),
])
}
Expand Down

0 comments on commit 644f72d

Please sign in to comment.