From 4f7c659ddba26809e56953a20e4f4502bdb63bd4 Mon Sep 17 00:00:00 2001 From: Wen Date: Fri, 1 May 2026 12:09:40 -0700 Subject: [PATCH 1/8] test(evm): use -b sync + sleep in lib.js cosmos-tx helpers for Autobahn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bankSend, fundSeiAddress, executeWasm, associateWasm all used -b block (broadcast-mode block), which subscribes to tendermint's EventDataTx for the submitted hash and waits up to 60s for it to fire. Under Autobahn the executeBlock path doesn't invoke FireEvents, so EventDataTx is never published and -b block hangs to the timeout, blocking every test that funds an account or runs a wasm message in beforeEach / before-all hooks. Switch to -b sync (returns on mempool acceptance) plus a fixed 2s sleep to let inclusion happen. Portable across both engines: under CometBFT this is slightly slower than the event-driven detection -b block had, but the difference is in the noise of the surrounding hardhat-ethers polling. Under Autobahn it unblocks the test paths entirely. Verified locally: EVMPrecompileTest's Bank, Addr, Distribution, Staking, Oracle precompile sections (which depend on getAdmin → fundSeiAddress) go from 0/all hung in before-all to 9/9 passing. Gov + Wasm precompile sections still fail because they have direct -b block calls inside the test files themselves; those need separate substitutions. Co-Authored-By: Claude Opus 4.7 (1M context) --- contracts/test/lib.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/contracts/test/lib.js b/contracts/test/lib.js index 83655dc40d..afbf880a7f 100644 --- a/contracts/test/lib.js +++ b/contracts/test/lib.js @@ -97,13 +97,15 @@ async function evmSend(addr, fromKey, amount="10000000000000000000000000") { } async function bankSend(toAddr, fromKey, amount="100000000000", denom="usei") { - const result = await execute(`seid tx bank send ${fromKey} ${toAddr} ${amount}${denom} -b block --fees 20000usei -y`); - await delay() + const result = await execute(`seid tx bank send ${fromKey} ${toAddr} ${amount}${denom} -b sync --fees 20000usei -y`); + await sleep(2000) return result } async function fundSeiAddress(seiAddr, amount="100000000000", denom="usei", funder=adminKeyName) { - return await execute(`seid tx bank send ${funder} ${seiAddr} ${amount}${denom} -b block --fees 20000usei -y`); + const result = await execute(`seid tx bank send ${funder} ${seiAddr} ${amount}${denom} -b sync --fees 20000usei -y`); + await sleep(2000) + return result } async function getSeiBalance(seiAddr, denom="usei") { @@ -603,14 +605,16 @@ async function queryWasm(contractAddress, operation, args={}){ async function executeWasm(contractAddress, msg, coins = "0usei") { const jsonString = JSON.stringify(msg).replace(/"/g, '\\"'); // Properly escape JSON string - const command = `seid tx wasm execute ${contractAddress} "${jsonString}" --amount ${coins} --from ${adminKeyName} --gas=5000000 --fees=1000000usei -y --broadcast-mode block -o json`; + const command = `seid tx wasm execute ${contractAddress} "${jsonString}" --amount ${coins} --from ${adminKeyName} --gas=5000000 --fees=1000000usei -y --broadcast-mode sync -o json`; const output = await execute(command); + await sleep(2000) return JSON.parse(output); } async function associateWasm(contractAddress) { - const command = `seid tx evm associate-contract-address ${contractAddress} --from ${adminKeyName} --gas=5000000 --fees=1000000usei -y --broadcast-mode block -o json`; + const command = `seid tx evm associate-contract-address ${contractAddress} --from ${adminKeyName} --gas=5000000 --fees=1000000usei -y --broadcast-mode sync -o json`; const output = await execute(command); + await sleep(2000) return JSON.parse(output); } From 88e6078c9fc47b366e730333d28fe07f7f1ce3a5 Mon Sep 17 00:00:00 2001 From: Wen Date: Fri, 1 May 2026 13:38:18 -0700 Subject: [PATCH 2/8] test(evm): also flip associateKey and passProposal vote to -b sync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same migration as the prior commit, extended to two more sites that don't read post-execution event data: - associateKey: result is unused (wrapped in try/catch swallowing all errors). The -b block timeout was a 60s wait under Autobahn before the catch fired. - passProposal gov vote: caller polls proposal status afterward; the vote-tx return value is unused. Helpers that parse post-execution events from the response (storeWasm, proposeParamChange, registerPointerForERC*, etc.) stay on -b block in this PR — they need a separate "submit then poll for tx result" change. Co-Authored-By: Claude Opus 4.7 (1M context) --- contracts/test/lib.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/test/lib.js b/contracts/test/lib.js index afbf880a7f..d774777201 100644 --- a/contracts/test/lib.js +++ b/contracts/test/lib.js @@ -157,8 +157,8 @@ async function getKeySeiAddress(name) { async function associateKey(keyName) { try { - await execute(`seid tx evm associate-address --from ${keyName} -b block`) - await delay() + await execute(`seid tx evm associate-address --from ${keyName} -b sync`) + await sleep(2000) }catch(e){ console.log("skipping associate") } @@ -500,9 +500,9 @@ async function ensureWasmDisabled(from=adminKeyName) { async function passProposal(proposalId, desposit="200000000usei", fees="200000usei", from=adminKeyName) { if(await isDocker()) { - await executeOnAllNodes(`seid tx gov vote ${proposalId} yes --from node_admin -b block -y --fees ${fees}`) + await executeOnAllNodes(`seid tx gov vote ${proposalId} yes --from node_admin -b sync -y --fees ${fees}`) } else { - await execute(`seid tx gov vote ${proposalId} yes --from ${from} -b block -y --fees ${fees}`) + await execute(`seid tx gov vote ${proposalId} yes --from ${from} -b sync -y --fees ${fees}`) } // Poll for proposal status with shorter delay for faster tests for(let i=0; i<200; i++) { From 52eb5a056b8bd462c37eb35bd3722a38f2263911 Mon Sep 17 00:00:00 2001 From: Wen Date: Fri, 1 May 2026 13:59:38 -0700 Subject: [PATCH 3/8] test(evm): revert executeWasm/associateWasm to -b block CI on this PR caught a regression: CW1155toERC1155PointerTest's "should not transfer an NFT if not owned" reads res.code from executeWasm and expects it to be non-zero (the wasm execution should fail when the sender doesn't own the tokens). Under -b block, res.code is the DeliverTx code (post-execution); under -b sync it's the CheckTx code (mempool acceptance). For a tx that passes basic checks but fails in DeliverTx, -b sync returns 0 and the test wrongly thinks the tx succeeded. executeWasm and associateWasm have callers that read post-execution fields (code, events, logs) from the response, so they can't migrate to the -b sync pattern without also adding a "submit then poll for tx result" step. Revert these two; leave the truly response-agnostic helpers (bankSend, fundSeiAddress, associateKey, passProposal vote) on -b sync. The complex helpers are deferred to the same follow-up PR that addresses storeWasm, proposeParamChange, and the other event-parsing callers. Co-Authored-By: Claude Opus 4.7 (1M context) --- contracts/test/lib.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/contracts/test/lib.js b/contracts/test/lib.js index d774777201..c403184a7b 100644 --- a/contracts/test/lib.js +++ b/contracts/test/lib.js @@ -605,16 +605,14 @@ async function queryWasm(contractAddress, operation, args={}){ async function executeWasm(contractAddress, msg, coins = "0usei") { const jsonString = JSON.stringify(msg).replace(/"/g, '\\"'); // Properly escape JSON string - const command = `seid tx wasm execute ${contractAddress} "${jsonString}" --amount ${coins} --from ${adminKeyName} --gas=5000000 --fees=1000000usei -y --broadcast-mode sync -o json`; + const command = `seid tx wasm execute ${contractAddress} "${jsonString}" --amount ${coins} --from ${adminKeyName} --gas=5000000 --fees=1000000usei -y --broadcast-mode block -o json`; const output = await execute(command); - await sleep(2000) return JSON.parse(output); } async function associateWasm(contractAddress) { - const command = `seid tx evm associate-contract-address ${contractAddress} --from ${adminKeyName} --gas=5000000 --fees=1000000usei -y --broadcast-mode sync -o json`; + const command = `seid tx evm associate-contract-address ${contractAddress} --from ${adminKeyName} --gas=5000000 --fees=1000000usei -y --broadcast-mode block -o json`; const output = await execute(command); - await sleep(2000) return JSON.parse(output); } From 6b9be10e4b9c59b76ef5368fe9ba8a392a6f3000 Mon Sep 17 00:00:00 2001 From: Wen Date: Fri, 1 May 2026 14:23:08 -0700 Subject: [PATCH 4/8] test(evm): replace fixed sleep(2000) with waitForBlocks(1) helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer flagged the magic 2s sleep after -b sync submissions: under CometBFT (block ~1s) it's marginal; under Autobahn (block ~100ms) it's 20x longer than needed. Both are arbitrary. Replace with waitForBlocks(1): poll eth_blockNumber every 50ms until the chain advances by one block, with a 15s timeout. Engine-agnostic substitute that returns as soon as the next block lands. Net wall-clock impact (Bank/Addr/Distribution precompile sections): - CometBFT: 19s → 15s - Autobahn: 39s → 10s Co-Authored-By: Claude Opus 4.7 (1M context) --- contracts/test/lib.js | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/contracts/test/lib.js b/contracts/test/lib.js index c403184a7b..96f6a8a0b7 100644 --- a/contracts/test/lib.js +++ b/contracts/test/lib.js @@ -77,6 +77,21 @@ async function delay() { await sleep(1000) } +// Wait until the chain advances by `blocks` blocks. Used after `-b sync` +// submissions to give the next block time to include the tx — engine-agnostic +// substitute for a fixed sleep, since block times differ between CometBFT +// (~1s) and Autobahn (~100ms). +async function waitForBlocks(blocks=1, timeoutMs=15000) { + const start = await ethers.provider.getBlockNumber() + const deadline = Date.now() + timeoutMs + while (Date.now() < deadline) { + const cur = await ethers.provider.getBlockNumber() + if (cur >= start + blocks) return + await sleep(50) + } + throw new Error(`block didn't advance by ${blocks} in ${timeoutMs}ms (start=${start})`) +} + async function getCosmosTx(provider, evmTxHash) { return await provider.send("sei_getCosmosTx", [evmTxHash]) } @@ -98,13 +113,13 @@ async function evmSend(addr, fromKey, amount="10000000000000000000000000") { async function bankSend(toAddr, fromKey, amount="100000000000", denom="usei") { const result = await execute(`seid tx bank send ${fromKey} ${toAddr} ${amount}${denom} -b sync --fees 20000usei -y`); - await sleep(2000) + await waitForBlocks(1) return result } async function fundSeiAddress(seiAddr, amount="100000000000", denom="usei", funder=adminKeyName) { const result = await execute(`seid tx bank send ${funder} ${seiAddr} ${amount}${denom} -b sync --fees 20000usei -y`); - await sleep(2000) + await waitForBlocks(1) return result } @@ -158,7 +173,7 @@ async function getKeySeiAddress(name) { async function associateKey(keyName) { try { await execute(`seid tx evm associate-address --from ${keyName} -b sync`) - await sleep(2000) + await waitForBlocks(1) }catch(e){ console.log("skipping associate") } From 7bd996a1ef4b521db82edf30b685ab1d2a68508a Mon Sep 17 00:00:00 2001 From: Wen Date: Fri, 1 May 2026 14:48:30 -0700 Subject: [PATCH 5/8] test(evm): bump waitForBlocks default to 2 to close empty-block race MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI on this PR caught a sequence mismatch in SeiSoloTest's "Claim CW20 Tester / before all": fundSeiAddress submits with -b sync and waitForBlocks(1) returns when the next block lands. That next block can be empty (the submitted tx is still in mempool and lands one block later), so the chain hasn't advanced the funder's account sequence yet. The follow-up storeWasm queries the funder's account, gets the stale sequence, signs with it, and is rejected when the funder tx finally lands a block later and bumps the sequence. Default to 2 blocks instead of 1: closes the empty-next-block race without reintroducing a fixed sleep. Callers no longer pass an explicit block count — the helper takes care of the safety margin. Co-Authored-By: Claude Opus 4.7 (1M context) --- contracts/test/lib.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/contracts/test/lib.js b/contracts/test/lib.js index 96f6a8a0b7..3eac2be059 100644 --- a/contracts/test/lib.js +++ b/contracts/test/lib.js @@ -78,10 +78,13 @@ async function delay() { } // Wait until the chain advances by `blocks` blocks. Used after `-b sync` -// submissions to give the next block time to include the tx — engine-agnostic +// submissions to give the chain time to include the tx — engine-agnostic // substitute for a fixed sleep, since block times differ between CometBFT -// (~1s) and Autobahn (~100ms). -async function waitForBlocks(blocks=1, timeoutMs=15000) { +// (~1s) and Autobahn (~100ms). Default is 2 blocks rather than 1 because +// the next block can be empty (the submitted tx is still in mempool and +// lands one block later); 2 blocks closes that race in nearly all cases +// without re-introducing a fixed sleep. +async function waitForBlocks(blocks=2, timeoutMs=15000) { const start = await ethers.provider.getBlockNumber() const deadline = Date.now() + timeoutMs while (Date.now() < deadline) { @@ -113,13 +116,13 @@ async function evmSend(addr, fromKey, amount="10000000000000000000000000") { async function bankSend(toAddr, fromKey, amount="100000000000", denom="usei") { const result = await execute(`seid tx bank send ${fromKey} ${toAddr} ${amount}${denom} -b sync --fees 20000usei -y`); - await waitForBlocks(1) + await waitForBlocks() return result } async function fundSeiAddress(seiAddr, amount="100000000000", denom="usei", funder=adminKeyName) { const result = await execute(`seid tx bank send ${funder} ${seiAddr} ${amount}${denom} -b sync --fees 20000usei -y`); - await waitForBlocks(1) + await waitForBlocks() return result } @@ -173,7 +176,7 @@ async function getKeySeiAddress(name) { async function associateKey(keyName) { try { await execute(`seid tx evm associate-address --from ${keyName} -b sync`) - await waitForBlocks(1) + await waitForBlocks() }catch(e){ console.log("skipping associate") } From d282033a999f6166eb4f675eff7a615f17eb18d7 Mon Sep 17 00:00:00 2001 From: Wen Date: Mon, 4 May 2026 15:38:51 -0700 Subject: [PATCH 6/8] test(evm): convert evmSend and proposeParamChange off -b block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two more lib.js helpers were still using --broadcast-mode=block. Under Autobahn the executeBlock path doesn't fire EventDataTx, so -b block hangs to its 60s timeout on every call. evmSend (used by fundAddress, called from setupSigners and many test file before-hooks): convert to -b sync + waitForBlocks. Callers read only the txhash from the output, which is present in either format, so no other adjustment needed. This unblocks EVMPrecompileTest and EVMGigaTest's `transfer to non-existent contract with data` (latter verified passing in 126ms after the fix). proposeParamChange: convert to -b sync. The tx response under -b sync no longer carries deliver_tx events, so we can't read proposal_id from the submit_proposal event. Poll gov state instead (max-id-before vs max-id-after) — autobahn doesn't run a Cosmos-side tx indexer so seid q tx isn't an option. New maxProposalId helper handles the "no proposals exist yet" case explicitly via try/catch; using a shell `|| echo '{...}'` fallback breaks because the docker-exec wrapper double-quotes the inner command. Verified by EVMCompatabilityTest test #3 (`should reproduce mismatch by changing param`) passing in 47s after the fix (was timing out at 120s with -b block). Co-Authored-By: Claude Opus 4.7 (1M context) --- contracts/test/lib.js | 55 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/contracts/test/lib.js b/contracts/test/lib.js index 3eac2be059..c9f0a0f6d3 100644 --- a/contracts/test/lib.js +++ b/contracts/test/lib.js @@ -110,7 +110,12 @@ async function fundAddress(addr, amount="1000000000000000000000") { } async function evmSend(addr, fromKey, amount="10000000000000000000000000") { - const output = await execute(`seid tx evm send ${addr} ${amount} --from ${fromKey} -b block -y`); + // -b sync (returns on mempool acceptance) instead of -b block (subscribes + // to EventDataTx). Under Autobahn, executeBlock doesn't fire EventDataTx, + // so -b block hangs to its 60s timeout. -b sync is sufficient because + // callers don't read the deliver_tx event payload from this output. + const output = await execute(`seid tx evm send ${addr} ${amount} --from ${fromKey} -b sync -y`); + await waitForBlocks() return output.replace(/.*0x/, "0x").trim() } @@ -422,19 +427,59 @@ async function proposeParamChange(title, description, changes, deposit="20000000 }; const proposalJson = JSON.stringify(proposal); const tempFile = `/tmp/param_change_${Date.now()}.json`; - + // Use base64 encoding to avoid quote escaping issues in Docker const base64Json = Buffer.from(proposalJson).toString('base64'); await execute(`echo ${base64Json} | base64 -d > ${tempFile}`); - - const command = `seid tx gov submit-proposal param-change ${tempFile} --from ${from} --fees ${fees} -y -o json --broadcast-mode=block`; + + // Snapshot max proposal id before submit so we can identify the new one + // by polling — see comment below for why we don't use the tx response. + const maxIdBefore = await maxProposalId(); + + // -b sync (returns on mempool acceptance) instead of -b block (subscribes + // to EventDataTx). Under Autobahn, executeBlock doesn't fire EventDataTx, + // so -b block hangs to its 60s timeout on every call. -b sync also means + // the tx response no longer carries the deliver_tx events — including the + // submit_proposal event we used to read proposal_id from — so we instead + // poll gov state until a new proposal appears. + const command = `seid tx gov submit-proposal param-change ${tempFile} --from ${from} --fees ${fees} -y -o json -b sync`; const output = await execute(command); await execute(`rm ${tempFile}`); const response = JSON.parse(output); if (response.code !== 0) { throw new Error(`Failed to submit proposal: ${response.raw_log}`); } - return getEventAttribute(response, "submit_proposal", "proposal_id"); + + // Poll for the new proposal to land. Tx hash lookup (`seid q tx `) + // would need a Cosmos-side tx indexer, which Autobahn doesn't run. + // 30s should comfortably cover the inclusion + commit window. + const deadline = Date.now() + 30000; + while (Date.now() < deadline) { + const cur = await maxProposalId(); + if (cur > maxIdBefore) return String(cur); + await sleep(250); + } + throw new Error(`proposal submitted (tx ${response.txhash}) but did not appear in gov state within 30s`); +} + +// Returns the highest existing proposal id, or 0 if there are no proposals. +async function maxProposalId() { + let out; + try { + // seid exits non-zero with "Error: no proposals found" on an empty + // gov set; treat that as id=0 and fall through to JSON parsing for + // the populated case. Avoid using a `|| echo` fallback inside the + // pipeline because the docker-exec wrapper double-quotes the inner + // command and a JSON literal with single quotes would terminate + // the outer quote region. + out = await execute(`seid q gov proposals --reverse --limit 1 -o json 2>/dev/null`); + } catch (e) { + return 0; + } + if (!out || !out.trim()) return 0; + const proposals = JSON.parse(out).proposals || []; + if (proposals.length === 0) return 0; + return Number(proposals[0].proposal_id || proposals[0].id); } async function proposeDisableWasm(title="Disable WASM", description="Disable cosmwasm store code and instantiate operations", deposit="200000000usei", fees="200000usei", from=adminKeyName) { From 0fb35a32dc43d6184a0dbaf15190a06e05b5613a Mon Sep 17 00:00:00 2001 From: Wen Date: Mon, 4 May 2026 16:54:51 -0700 Subject: [PATCH 7/8] test(evm): convert createTokenFactoryTokenAndMint off -b block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Last lib.js helper still using --broadcast-mode=block. Same Autobahn incompatibility as evmSend / proposeParamChange: executeBlock doesn't fire EventDataTx, so -b block hangs to its 60s timeout on every call, which blocked ERC20toNativePointerTest's before-all hook. The original code read the new denom from the create_denom event in the tx response. Under -b sync we don't get deliver_tx events, but the tokenfactory denom is deterministic — `factory//` where creator is the bech32 of the --from key. Construct it locally from getKeySeiAddress instead. Verified: ERC20toNativePointerTest passes 14/14 in 17s after the fix (previously 0/1, hung 60s+ on the before-all hook). Co-Authored-By: Claude Opus 4.7 (1M context) --- contracts/test/lib.js | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/contracts/test/lib.js b/contracts/test/lib.js index c9f0a0f6d3..4e9681ab55 100644 --- a/contracts/test/lib.js +++ b/contracts/test/lib.js @@ -244,16 +244,36 @@ async function rawHttpDebugTraceWithCallTracer(txHash) { } async function createTokenFactoryTokenAndMint(name, amount, recipient, from=adminKeyName) { - const command = `seid tx tokenfactory create-denom ${name} --from ${from} --gas=5000000 --fees=1000000usei -y --broadcast-mode block -o json` - const output = await execute(command); - const response = JSON.parse(output) - const token_denom = getEventAttribute(response, "create_denom", "new_token_denom") - const mint_command = `seid tx tokenfactory mint ${amount}${token_denom} --from ${from} --gas=5000000 --fees=1000000usei -y --broadcast-mode block -o json` - await execute(mint_command); + // -b sync everywhere (no -b block hang under Autobahn). The tokenfactory + // denom format is factory//, so we construct + // the denom locally from the from-key's address rather than reading + // the create_denom event from the tx response — -b sync doesn't carry + // deliver_tx events. + const creator = await getKeySeiAddress(from); + const token_denom = `factory/${creator}/${name}`; + + const createOut = await execute(`seid tx tokenfactory create-denom ${name} --from ${from} --gas=5000000 --fees=1000000usei -y --broadcast-mode sync -o json`); + const createResp = JSON.parse(createOut); + if (createResp.code !== 0) { + throw new Error(`createTokenFactoryTokenAndMint: create-denom rejected: ${createResp.raw_log}`); + } + await waitForBlocks(); + + const mintOut = await execute(`seid tx tokenfactory mint ${amount}${token_denom} --from ${from} --gas=5000000 --fees=1000000usei -y --broadcast-mode sync -o json`); + const mintResp = JSON.parse(mintOut); + if (mintResp.code !== 0) { + throw new Error(`createTokenFactoryTokenAndMint: mint rejected: ${mintResp.raw_log}`); + } + await waitForBlocks(); + + const sendOut = await execute(`seid tx bank send ${from} ${recipient} ${amount}${token_denom} --from ${from} --gas=5000000 --fees=1000000usei -y --broadcast-mode sync -o json`); + const sendResp = JSON.parse(sendOut); + if (sendResp.code !== 0) { + throw new Error(`createTokenFactoryTokenAndMint: bank send rejected: ${sendResp.raw_log}`); + } + await waitForBlocks(); - const send_command = `seid tx bank send ${from} ${recipient} ${amount}${token_denom} --from ${from} --gas=5000000 --fees=1000000usei -y --broadcast-mode block -o json` - await execute(send_command); - return token_denom + return token_denom; } async function getChainId() { From 0afffb9353b7de5a5804a43ae79788f677a2d2e7 Mon Sep 17 00:00:00 2001 From: Wen Date: Mon, 4 May 2026 17:53:41 -0700 Subject: [PATCH 8/8] test(evm): convert EVMPrecompileTest Gov before-hook off -b block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gov Precompile section's before-hook had its own inline 'seid tx gov submit-proposal param-change ... -b block' which hangs 60s under Autobahn. Replace with the lib.js proposeParamChange helper (now -b sync + poll gov state). EVMPrecompileTest goes from 9/11 to 10/11 — only the Wasm Precompile section still fails (out of scope; wasm being decommed). Co-Authored-By: Claude Opus 4.7 (1M context) --- contracts/test/EVMPrecompileTest.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/contracts/test/EVMPrecompileTest.js b/contracts/test/EVMPrecompileTest.js index 88450768e6..1786ed566b 100755 --- a/contracts/test/EVMPrecompileTest.js +++ b/contracts/test/EVMPrecompileTest.js @@ -4,7 +4,7 @@ const fs = require('fs'); const path = require('path'); const { expectRevert } = require('@openzeppelin/test-helpers'); -const { setupSigners, getAdmin, deployWasm, storeWasm, execute, isDocker, ABI, createTokenFactoryTokenAndMint, getSeiBalance, rawHttpDebugTraceWithCallTracer} = require("./lib"); +const { setupSigners, getAdmin, deployWasm, storeWasm, execute, isDocker, ABI, createTokenFactoryTokenAndMint, getSeiBalance, rawHttpDebugTraceWithCallTracer, proposeParamChange} = require("./lib"); function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); @@ -125,8 +125,19 @@ describe("EVM Precompile Tester", function () { let govProposal; before(async function () { - const govProposalResponse = JSON.parse(await execute(`seid tx gov submit-proposal param-change ../contracts/test/param_change_proposal.json --from admin --fees 20000usei -b block -y -o json`)) - govProposal = govProposalResponse.logs[0].events[3].attributes[1].value; + // Use lib.js proposeParamChange (Autobahn-compatible: -b sync + poll + // gov state) instead of an inline `seid tx -b block` which hangs + // 60s under Autobahn. Mirrors ../contracts/test/param_change_proposal.json + // (kept on disk for any tooling that still consumes it). + govProposal = await proposeParamChange( + "Gov Param Change", + "Update quorum to 0.45", + [{ subspace: "gov", key: "tallyparams", value: { quorum: "0.45" } }], + "200000000usei", + "20000usei", + "admin", + false, // not expedited — matches the JSON file + ); const signer = accounts[0].signer const contractABIPath = '../../precompiles/gov/abi.json';