Skip to content

Commit

Permalink
🪲 Use getNextNonce when proposing transactions to safe (LayerZero-L…
Browse files Browse the repository at this point in the history
  • Loading branch information
janjakubnanista authored May 29, 2024
1 parent 5681b64 commit c13cee5
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 17 deletions.
6 changes: 6 additions & 0 deletions .changeset/tame-mugs-count.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@layerzerolabs/devtools-evm": patch
"@layerzerolabs/toolbox-hardhat": patch
---

Use getNextNonce when proposing transactions to gnosis
15 changes: 8 additions & 7 deletions packages/devtools-evm/src/signer/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,17 @@ export class GnosisOmniSignerEVM<TSafeConfig extends ConnectSafeConfig> extends
async signAndSend(transaction: OmniTransaction): Promise<OmniTransactionResponse> {
this.assertTransaction(transaction)
const { safeSdk, apiKit } = await this.#initSafe()
const safeAddress = await safeSdk.getAddress()
const safeTransaction = await safeSdk.createTransaction({
safeTransactionData: [this.#serializeTransaction(transaction)],
options: {
nonce: await apiKit.getNextNonce(safeAddress),
},
})
const safeTxHash = await safeSdk.getTransactionHash(safeTransaction)
const senderSignature = await safeSdk.signTransactionHash(safeTxHash)
const safeAddress = await safeSdk.getAddress()
const senderAddress = await this.signer.getAddress()

await apiKit.proposeTransaction({
senderSignature: senderSignature.data,
safeAddress,
Expand Down Expand Up @@ -130,23 +134,20 @@ export class GnosisOmniSignerEVM<TSafeConfig extends ConnectSafeConfig> extends
}

async #initSafe() {
if (this.safeConfig && (!this.safeSdk || !this.apiKit)) {
if (!this.safeSdk || !this.apiKit) {
const ethAdapter = new EthersAdapter({
ethers,
signerOrProvider: this.signer,
})
this.apiKit = new SafeApiKit({ txServiceUrl: this.safeUrl, ethAdapter })

const contractNetworks = this.safeConfig.contractNetworks
this.safeSdk = await Safe.create({
ethAdapter,
safeAddress: this.safeConfig.safeAddress!,
...(!!contractNetworks && { contractNetworks }),
contractNetworks: this.safeConfig.contractNetworks,
})
}
if (!this.safeSdk || !this.apiKit) {
throw new Error('Safe SDK not initialized')
}

return { safeSdk: this.safeSdk, apiKit: this.apiKit }
}
}
21 changes: 11 additions & 10 deletions packages/devtools-evm/test/signer/sdk.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fc from 'fast-check'
import { endpointArbitrary, pointArbitrary } from '@layerzerolabs/test-devtools'
import { endpointArbitrary, evmAddressArbitrary, pointArbitrary } from '@layerzerolabs/test-devtools'
import { Signer } from '@ethersproject/abstract-signer'
import { GnosisOmniSignerEVM, OmniSignerEVM } from '@/signer'
import Safe, { SafeConfig } from '@safe-global/protocol-kit'
Expand Down Expand Up @@ -108,33 +108,34 @@ describe('signer/ethers', () => {
it('should send the transaction using the signer if the eids match', async () => {
await fc.assert(
fc.asyncProperty(
evmAddressArbitrary,
transactionArbitrary,
transactionHashArbitrary,
async (transaction, transactionHash) => {
async (safeAddress, transaction, transactionHash) => {
const sendTransaction = jest.fn()
const getAddress = jest.fn()
const signer = { getAddress, sendTransaction } as unknown as Signer
const omniSigner = new GnosisOmniSignerEVM(
transaction.point.eid,
signer,
'',
{} as SafeConfig
)
const omniSigner = new GnosisOmniSignerEVM(transaction.point.eid, signer, '', {
safeAddress,
})
// TODO These should be mocked using jest.mock
omniSigner['safeSdk'] = {
createTransaction: jest.fn().mockResolvedValue({ data: 'transaction' }),
getTransactionHash: jest.fn().mockResolvedValue(transactionHash),
getAddress: jest.fn(),
getAddress: jest.fn().mockResolvedValue(safeAddress),
signTransactionHash: jest.fn().mockResolvedValue({ data: 'signature' }),
} as unknown as Safe
const safeService = (omniSigner['apiKit'] = {
proposeTransaction: jest.fn(),
getNextNonce: jest.fn(),
} as unknown as SafeApiKit)

const result = await omniSigner.signAndSend(transaction)
expect(result.transactionHash).toEqual(transactionHash)
expect(await result.wait()).toEqual({ transactionHash })
expect(safeService.getNextNonce).toHaveBeenCalledWith(safeAddress)
expect(safeService.proposeTransaction).toHaveBeenCalledWith({
safeAddress: undefined,
safeAddress,
safeTransactionData: 'transaction',
safeTxHash: transactionHash,
senderAddress: undefined,
Expand Down

0 comments on commit c13cee5

Please sign in to comment.