memoscan
← all memos

Memo 0x63d3880d…1ed076 on Ethereum

0x68575b07…67c7·#25,913,371·view on Etherscan
urn await r.json()} catch(e){laneThrew(name,e);return null}finally{clearTimeout(k)}}; const LANE_TTL=15000,LANE_MAX=64; const _laneHit=new Map(),_laneWait=new Map(); const laneCached=(k,go)=>{ const c=_laneHit.get(k); if(c&&Date.now()-c.t<LANE_TTL){_laneHit.delete(k);_laneHit.set(k,c);return Promise.resolve(c.v)} const w=_laneWait.get(k); if(w)return w; const pr=go().then(v=>{ _laneWait.delete(k); if(v!==null&&v!==undefined){_laneHit.set(k,{v,t:Date.now()}); if(_laneHit.size>LANE_MAX)_laneHit.delete(_laneHit.keys().next().value);} return v},e=>{_laneWait.delete(k);throw e}); _laneWait.set(k,pr);return pr}; let laneOverride=null,laneOverrideFor=""; const laneScope=()=>`${fromSel.value}|${toSel.value}|${tab}|${mode}`; const lanePin=()=>laneOverride&&laneOverrideFor===laneScope()?laneOverride:null; const laneGet=async(name,url,ms)=>{ const ac=new AbortController(),k=setTimeout(()=>ac.abort(),ms); try{const r=await fetch(url,{signal:ac.signal});laneSaw(name,r.status); if(!r.ok)return null;return await r.json()} catch(e){laneThrew(name,e);return null}finally{clearTimeout(k)}}; const SOLVER_SHAPES_OUT={ "0x":async(ep,f,t,amt,slip,ms)=>{ const q=new URLSearchParams({chainId:chainCfg().slvId,sellToken:f===ZERO?OX_ETH:f,buyToken:t===ZERO?OX_ETH:t, buyAmount:amt.toString(),taker:solverExec,slippageBps:String(slip)}); const j=await laneGet("0x",`${ep}/swap/allowance-holder/quote?${q}`,ms); if(!j||!j.transaction||!j.estimatedNetSellAmount)return null; return{inp:BigInt(j.estimatedNetSellAmount), cap:j.maxSellAmount?BigInt(j.maxSellAmount):0n, target:j.transaction.to,spender:j.allowanceTarget||j.transaction.to,data:j.transaction.data}}, "ParaSwap":async(ep,f,t,amt,slip,ms,fd,td)=>{ const q=new URLSearchParams({srcToken:f===ZERO?OX_ETH:f,destToken:t===ZERO?OX_ETH:t, amount:amt.toString(),srcDecimals:String(fd??18),destDecimals:String(td??18), side:"BUY",network:chainCfg().slvId,version:"6.2"}); const pr=await laneGet("ParaSwap",`${ep}/prices?${q}`,ms); const route=pr&&pr.priceRoute;if(!route||!route.srcAmount)return null; const j=await lanePost("ParaSwap",`${ep}/transactions/${chainCfg().slvId}?ignoreChecks=true`,{ srcToken:f===ZERO?OX_ETH:f,destToken:t===ZERO?OX_ETH:t, srcDecimals:route.srcDecimals,destDecimals:route.destDecimals, priceRoute:route,userAddress:solverExec,slippage:Number(slip)},ms); if(!j||!j.to||!j.data)return null; return{inp:bmax(BigInt(route.srcAmount),BigInt(route.srcAmountAfterFee||route.srcAmount)), target:j.to,spender:route.tokenTransferProxy||j.to,data:j.data}}, }; const SOLVER_SHAPES={ "0x":async(ep,f,t,amt,slip,ms)=>{ const q=new URLSearchParams({chainId:chainCfg().slvId,sellToken:f===ZERO?OX_ETH:f,buyToken:t===ZERO?OX_ETH:t, sellAmount:amt.toString(),taker:solverExec,slippageBps:String(slip)}); const j=await laneGet("0x",`${ep}/swap/allowance-holder/quote?${q}`,ms); if(!j||!j.transaction||!j.buyAmount)return null; return{out:BigInt(j.buyAmount),target:j.transaction.to, spender:j.allowanceTarget||j.transaction.to,data:j.transaction.data}}, "ParaSwap":async(ep,f,t,amt,slip,ms,fd,td)=>{ const q=new URLSearchParams({srcToken:f===ZERO?OX_ETH:f,destToken:t===ZERO?OX_ETH:t, amount:amt.toString(),srcDecimals:String(fd??18),destDecimals:String(td??18), side:"SELL",network:chainCfg().slvId,version:"6.2"}); const pr=await laneGet("ParaSwap",`${ep}/prices?${q}`,ms); const route=pr&&pr.priceRoute;if(!route||!route.destAmount)return null; const j=await lanePost("ParaSwap",`${ep}/transactions/${chainCfg().slvId}?ignoreChecks=true`,{ srcToken:f===ZERO?OX_ETH:f,destToken:t===ZERO?OX_ETH:t, srcDecimals:route.srcDecimals,destDecimals:route.destDecimals, priceRoute:route,userAddress:solverExec,slippage:Number(slip)},ms); if(!j||!j.to||!j.data)return null; return{out:bmin(BigInt(route.destAmount),BigInt(route.destAmountAfterFee||route.destAmount)), target:j.to,spender:route.tokenTransferProxy||j.to,data:j.data}}, "KyberSwap":async(ep,f,t,amt,slip,ms)=>{ const q=new URLSearchParams({tokenIn:f===ZERO?OX_ETH:f,tokenOut:t===ZERO?OX_ETH:t,amountIn:amt.toString()}); const pr=await laneGet("KyberSwap",`${ep}/${chainCfg().slvSlug}/api/v1/routes?${q}`,ms); const rs=pr&&pr.data&&pr.data.routeSummary;if(!rs||!rs.amountOut)return null; const j=await lanePost("KyberSwap",`${ep}/${chainCfg().slvSlug}/api/v1/route/build`, {routeSummary:rs,sender:solverExec,recipient:solverExec,slippageTolerance:Number(slip)},ms); const d=j&&j.data;if(!d||!d.data||!d.routerAddress)return null; return{out:BigInt(rs.amountOut),target:d.routerAddress,spender:d.routerAddress,data:d.data}}, "Enso":async(ep,f,t,amt,slip,ms)=>{ const q=new URLSearchParams({chainId:chainCfg().slvId,fromAddress:solverExec,receiver:solverExec, tokenIn:f===ZERO?OX_ETH:f,tokenOut:t===ZERO?OX_ETH:t,amountIn:amt.toString(), slippage:String(slip),routingStrategy:"router"}); const j=await laneGet("Enso",`${ep}?${q}`,ms); if(!j||!j.amountOut||!j.tx||!j.tx.to)return null; return{out:BigInt(j.amountOut),target:j.tx.to,spender:j.tx.to,data:j.tx.data}}, "OKX":async(ep,f,t,amt,slip,ms)=>{ const q=new URLSearchParams({chainIndex:chainCfg().slvId,fromTokenAddress:f===ZERO?OX_ETH:f, toTokenAddress:t===ZERO?OX_ETH:t,amount:amt.toString(), slippagePercent:(Number(slip)/100).toString(),userWalletAddress:solverExec,swapMode:"exactIn"}); const j=await laneGet("OKX",`${ep}/dex/aggregator/swap?${q}`,ms); const d=j&&j.code==="0"&&j.data&&j.data[0]; if(!d||!d.tx||!d.tx.to||!d.routerResult||!d.routerResult.toTokenAmount)return null; let sp=f===ZERO?d.tx.to:OKX_APPROVE[CHAIN_ID]; if(!sp){const a=await laneGet("OKX",`${ep}/dex/aggregator/approve-transaction?${new URLSearchParams({chainIndex:chainCfg().slvId,tokenContractAddress:f,approveAmount:amt.toString()})}`,ms); const x=a&&a.code==="0"&&a.data&&a.data[0]&&a.data[0].dexContractAddress;if(isAddr(x))sp=OKX_APPROVE[CHAIN_ID]=x} if(!sp)return null; return{out:BigInt(d.routerResult.toTokenAmount),target:d.tx.to,spender:sp,data:d.tx.data}}, "Bebop":async(ep,f,t,amt,slip,ms)=>{ if(f===ZERO||t===ZERO)return null; const q=new URLSearchParams({sell_tokens:f,buy_tokens:t,sell_amounts:amt.toString(), taker_address:solverExec,gasless:"false",approval_type:"Standard"}); const j=await laneGet("Bebop",`${ep}/quote?${q}`,ms); const rs=j&&j.routes;if(!rs||!rs.length)return null; const route=rs.find(x=>x.type===j.bestPrice)||rs[0]; const qq=route&&route.quote;if(!qq||!qq.tx||!qq.buyTokens)return null; const info=Object.values(qq.buyTokens)[0]; if(!info||!info.amount||!qq.tx.to)return null; const bebSp=qq.approvalTarget||qq.approval_target; if(!isAddr(bebSp||""))return null; return{out:BigInt(info.amount),target:qq.tx.to,spender:bebSp,data:qq.tx.data}}, "1inch":async(ep,f,t,amt,slip,ms)=>{ const q=new URLSearchParams({src:f===ZERO?OX_ETH:f,dst:t===ZERO?OX_ETH:t,amount:amt.toString(), from:solverExec,origin:solverExec,slippage:String(Number(slip)/100),disableEstimate:"true"}); const j=await laneGet("1inch",`${ep}/swap/v6.0/${chainCfg().slvId}/swap?${q}`,ms); if(!j||!j.tx||!j.dstAmount)return null; return{out:BigInt(j.dstAmount),target:j.tx.to,spender:j.tx.to,data:j.tx.data}}, }; const RPC_TRIES=4; const nodeRead=async(method,params)=>{ let last; const pin=rpcPin(); const tries=Math.min(rpcPool.length,RPC_TRIES); const p=rpcPi; for(let i=pin?-1:0;i<tries;i++){ const j=(p+i)%rpcPool.length; const u=i<0?pin:rpcPool[j]; try{const r=await httpRead(u,method,params);if(i>=0)rpcPi=j; if(!curated)loadCurated().catch(()=>{}); return r} catch(e){last=e;if(!e.retry)throw e}} throw last||Error("no read node answered")}; const isSign=m=>m===S||m.indexOf("wallet_")===0||m==="eth_requestAccounts"||m==="eth_accounts"||WC_SIGN.indexOf(m)>=0; const hexOk=r=>typeof r==="string"&&!/^0x[0-9a-fA-F]*$/.test(r)?Promise.reject(Error("bad hex from node")):r; const rpc=(method,params)=>{const e=prov(); const p=e?e.request({method,params}) :isSign(method)?Promise.reject(Object.assign(Error(NO_WALLET),{noWallet:true})):nodeRead(method,params); return method===C?p.then(hexOk):p}; const rpcRead=async(method,params,tries=4)=>{ let last; for(let i=0;i<tries;i++){ try{return await rpc(method,params)} catch(e){last=e;if(i+1<tries)await new Promise(r=>setTimeout(r,300*(i+1)))} } throw last; }; const okRet=h=>{h=strip0x(h);if(h&&BigInt("0x"+h)===0n)throw Error("token returned false")}; const waitTx=async hash=>{ const end=Date.now()+600000; let misses=0,wait=1500; while(Date.now()<end){ try{ const r=await rpc("eth_getTransactionReceipt",[hash]); misses=0; if(r){ if(r.status!=="0x1")throw Error("tx reverted: "+hash); return r; } wait=Math.min(wait+500,5000); }catch(e){ if(/tx reverted/.test(e.message||""))throw e; if(++misses>2)wait=Math.min(wait*2,15000); } await new Promise(res=>setTimeout(res,wait)); } throw Error("tx not mined in time"); }; const checkWallet=async()=>{if(!account)throw Error("Connect a wallet first.");const[c,a]=await Promise.all([rpc(I,[]),rpc("eth_accounts",[])]);if(+c!==CHAIN_ID)throw Error("Switch your wallet to "+chainCfg().name);if(a[0]?.toLowerCase()!==account.toLowerCase())throw Error("wallet changed")}; const hexToBytes=h=>{const s=strip0x(h);const o=new Uint8Array(s.length/2);for(let i=0;i<o.length;i++)o[i]=parseInt(s.slice(i*2,i*2+2),16);return o}; const KRC=[1n,0x8082n,0x800000000000808an,0x8000000080008000n,0x808bn,0x80000001n,0x8000000080008081n,0x8000000000008009n,0x8an,0x88n,0x80008009n,0x8000000an,0x8000808bn,0x800000000000008bn,0x8000000000008089n,0x8000000000008003n,0x8000000000008002n,0x8000000000000080n,0x800an,0x800000008000000an,0x8000000080008081n,0x8000000000008080n,0x80000001n,0x8000000080008008n]; const KR=[0,1,62,28,27,36,44,6,55,20,3,10,43,25,39,41,45,15,21,8,18,2,61,56,14]; const KM=(1n<<64n)-1n; const krol=(x,n)=>n?((x<<BigInt(n))|(x>>BigInt(64-n)))&KM:x; const KCc=new Array(5),KB=new Array(25); const keccak=b=>{const A=new Array(25).fill(0n),rate=136; const pad=rate-(b.length%rate),buf=new Uint8Array(b.length+pad);buf.set(b); buf[b.length]|=1;buf[buf.length-1]|=0x80; for(let o=0;o<buf.length;o+=rate){ for(let i=0;i<17;i++){let v=0n;for(let j=7;j>=0;j--)v=(v<<8n)|BigInt(buf[o+i*8+j]);A[i]^=v} for(let r=0;r<24;r++){ for(let x=0;x<5;x++)KCc[x]=A[x]^A[x+5]^A[x+10]^A[x+15]^A[x+20]; for(let x=0;x<5;x++){const D=KCc[(x+4)%5]^krol(KCc[(x+1)%5],1);for(let y=0;y<25;y+=5)A[x+y]^=D} for(let x=0;x<5;x++)for(let y=0;y<5;y++)KB[y+5*((2*x+3*y)%5)]=krol(A[x+5*y],KR[x+5*y]); for(let x=0;x<5;x++)for(let y=0;y<5;y++)A[x+5*y]=KB[x+5*y]^((~KB[(x+1)%5+5*y]&KM)&KB[(x+2)%5+5*y]); A[0]^=KRC[r]}} let out="";for(let i=0;i<4;i++){let v=A[i];for(let j=0;j<8;j++){out+=Number(v&0xffn).toString(16).padStart(2,"0");v>>=8n}} return "0x"+out}; const namehash=n=>{let nd="0x"+"0".repeat(64); if(n)for(const l of n.split(".").reverse())nd=keccak(new Uint8Array([...hexToBytes(nd),...hexToBytes(keccak(new TextEncoder().encode(l)))])); return nd}; const strTail=v=>{const b=new TextEncoder().encode(v);let h=""; for(const x of b)h+=x.toString(16).padStart(2,"0"); return encUint(b.length)+h.padEnd(Math.ceil(h.length/64)*64,"0")}; const encStr=v=>pad32("20")+strTail(v); const retAddr=h=>{const s=strip0x(h||""); if(s.length!==64||/[^0-9a-fA-F]/.test(s)||/[^0]/.test(s.slice(0,24)))return""; const a="0x"+s.slice(24).toLowerCase(); return /^0x0{40}$/.test(a)?"":a}; const nameOk=n=>/^[a-z0-9.-]+$/.test(n) &&n.split(".").every(l=>l.length>0&&l.length<64&&l[0]!=="-"&&l[l.length-1]!=="-"); const nsFwd=async(reg,n)=>{const id=await cfgRead(C,[{to:reg,data:"0x"+SEL_CID+encStr(n)},L]); if(strip0x(id||"").length!==64)return""; return retAddr(await cfgRead(C,[{to:reg,data:"0x"+SEL_RES+strip0x(id)},L]))}; const dnsEnc=n=>{let h=""; for(const l of n.split(".")){const b=new TextEncoder().encode(l); h+=b.length.toString(16).padStart(2,"0"); for(const x of b)h+=x.toString(16).padStart(2,"0")} return h+"00"}; const encBytes=h=>{h=strip0x(h);return encUint(h.length/2)+h.padEnd(Math.ceil(h.length/64)*64,"0")}; const encResolve=(dns,inner)=>{const a=encBytes(dns); return pad32("40")+encUint(64+a.length/2)+a+encBytes(inner)}; const decBytes=hex=>{const h=strip0x(hex||""); if(h.length<128)return""; const off=Number(BigInt("0x"+h.slice(0,64)))*2; if(!Number.isSafeInteger(off)||off+64>h.length)return""; const len=Number(BigInt("0x"+h.slice(off,off+64)))*2; if(!Number.isSafeInteger(len)||off+64+len>h.length)return""; return "0x"+h.slice(off+64,off+64+len)}; const ensFind=async n=>{const parts=n.split("."), nodes=parts.map((_,i)=>namehash(parts.slice(i).join("."))); const rs=await Promise.all(nodes.map(nd=> cfgRead(C,[{to:ENSREG,data:"0x"+SEL_RSLV+pad32(nd)},L]).catch(()=>null))); for(let i=0;i<nodes.length;i++){const r=retAddr(rs[i]); if(r)return{r,nd:nodes[i],exact:i===0}} return null}; const ensWild=async r=>{ try{const s=await cfgRead(C,[{to:r,data:supports(SEL_ERESOLVE)},L]); return strip0x(s||"").length===64&&BigInt(s)===1n}catch{return false}}; const ensFwd=async n=>{const f=await ensFind(n); if(!f)return""; const inner="0x"+SEL_EADDR+pad32(f.nd); if(f.exact)return retAddr(await cfgRead(C,[{to:f.r,data:inner},L])); if(!await ensWild(f.r))return""; try{return retAddr(decBytes(await cfgRead(C,[{to:f.r, data:"0x"+SEL_ERESOLVE+encResolve(dnsEnc(n),inner)},L])))} catch(e){ if(/556f1830/i.test((e&&e.data?JSON.stringify(e.data):"")+((e&&e.message)||""))) throw Object.assign(Error(NAME_OFFCHAIN),{offchain:true}); return""; }}; const ensRevName=async(nd,r)=>{ if(!r)return""; try{return decodeString(await cfgRead(C,[{to:r,data:"0x"+SEL_ENAME+pad32(nd)},L])).trim()}catch{return""}}; const nameFwd=n=>/\.gwei$/i.test(n)?nsFwd(GNS,n):/\.wei$/i.test(n)?nsFwd(WNS,n):/\.eth$/i.test(n)?ensFwd(n):Promise.resolve(""); const FWD_TTL=30000; const fwdCache=new Map(); const nameFwdCached=n=>{const hit=fwdCache.get(n); if(hit&&hit.exp>Date.now())return hit.p; const p=nameFwd(n); fwdCache.set(n,{p,exp:Date.now()+FWD_TTL}); p.catch(()=>fwdCache.delete(n)); return p}; const nameRev=async a=>{ const nd=namehash(strip0x(a).toLowerCase()+".addr.reverse"); const [w,g,er]=await Promise.all([ {to:WNS,data:"0x"+SEL_REV+encAddr(a)}, {to:GNS,data:"0x"+SEL_REV+encAddr(a)}, {to:ENSREG,data:"0x"+SEL_RSLV+pad32(nd)}] .map(c=>cfgRead(C,[c,L]).catch(()=>null))); const str=h=>{try{return h?decodeString(h).trim():""}catch{return""}}; const agrees=async n=>{ if(!n||!nameOk(n.toLowerCase()))return""; let f="";try{f=await nameFwdCached(n.toLowerCase())}catch{} return f&&f.toLowerCase()===a.toLowerCase()?n:""}; return await agrees(str(w))||await agrees(str(g)) ||await agrees(await ensRevName(nd,retAddr(er)))||""}; const decodeString=hex=>{ const h=strip0x(hex); if(h.length<=64)return new TextDecoder().decode(hexToBytes(h)).replace(/\0+$/,""); const off=Number(BigInt("0x"+h.slice(0,64)))*2; const len=Number(BigInt("0x"+h.slice(off,off+64)))*2; return new TextDecoder().decode(hexToBytes(h.slice(off+64,off+64+len))); }; const kecStr=v=>keccak(new TextEncoder().encode(v)); const ckAddr=a=>{const s=strip0x(a); if(s===s.toLowerCase()||s===s.toUpperCase())return true; const h=strip0x(kecStr(s.toLowerCase())); for(let i=0;i<40;i++){const c=s[i]; if(c>="a"&&c<="f"&&parseInt(h[i],16)>=8)return false; if(c>="A"&&c<="F"&&parseInt(h[i],16)<8)return false} return true}; const domainSep=(name,ver,tok)=>keccak(hexToBytes( kecStr(EIP712DOM)+pad32(kecStr(name))+pad32(kecStr(ver))+encUint(CHAIN_ID)+encAddr(tok))); const permitInfo=async(tok,owner)=>{ try{ const[ds,th,nc,nm]=await mc3Deep([ {to:tok,data:"0x"+SEL_DS},{to:tok,data:"0x"+SEL_PERMIT_TH}, {to:tok,data:"0x"+SEL_NONCES+encAddr(owner)},{to:tok,data:"0x"+SEL_NAME}]); if(!ds||ds==="0x")return null; if(th&&strip0x(th).length>=64&&strip0x(th).slice(0,64).toLowerCase()!==TH_2612)return null; if(!nc||!nm)return null; const nonce=BigInt(nc); const name=decodeString(nm); for(const ver of ["1","2","1.0","V1",""])if(domainSep(name,ver,tok).toLowerCase()===ds.toLowerCase()) return{name,ver,nonce}; }catch{} return null}; const signPermit=async(tok,info,owner,value,deadline)=>{ const td={types:{EIP712Domain:[{name:"name",type:"string"},{name:"version",type:"string"}, {name:"chainId",type:"uint256"},{name:"verifyingContract",type:"address"}], Permit:[{name:"owner",type:"address"},{name:"spender",type:"address"}, {name:"value",type:"uint256"},{name:"nonce",type:"uint256"},{name:"deadline",type:"uint256"}]}, primaryType:"Permit",domain:{name:info.name,version:info.ver,chainId:CHAIN_ID,verifyingContract:tok}, message:{owner,spender:ZROUTER,value:value.toString(),nonce:info.nonce.toString(),deadline:deadline.toString()}}; const sig=strip0x(await rpc("eth_signTypedData_v4",[owner,JSON.stringify(td)])); if(sig.length!==130)throw Error("bad signature"); let v=parseInt(sig.slice(128,130),16);if(v<27)v+=27; return"0x"+SEL_RPERMIT+encAddr(tok)+encUint(value)+encUint(deadline)+encUint(v)+sig.slice(0,64)+sig.slice(64,128)}; const P2DOM=()=>({name:"Permit2",chainId:CHAIN_ID,verifyingContract:PERMIT2}); const p2Ready=async(tok,owner)=>{ try{return BigInt(await rpc(C,[{to:tok,data:"0x"+SEL_ALLOWANCE+encAddr(owner)+encAddr(PERMIT2)},L]))}catch{return 0n}}; const signPermit2=async(tok,owner,amount,deadline)=>{ const nonce=BigInt("0x"+[...crypto.getRandomValues(new Uint8Array(31))].map(b=>b.toString(16).padStart(2,"0")).join("")); const td={types:{EIP712Domain:[{name:"name",type:"string"},{name:"chainId",type:"uint256"}, {name:"verifyingContract",type:"address"}], TokenPermissions:[{name:"token",type:"address"},{name:"amount",type:"uint256"}], PermitTransferFrom:[{name:"permitted",type:"TokenPermissions"},{name:"spender",type:"address"}, {name:"nonce",type:"uint256"},{name:"deadline",type:"uint256"}]}, primaryType:"PermitTransferFrom",domain:P2DOM(), message:{permitted:{token:tok,amount:amount.toString()},spender:ZROUTER, nonce:nonce.toString(),deadline:deadline.toString()}}; const sig=strip0x(await rpc("eth_signTypedData_v4",[owner,JSON.stringify(td)])); const n=sig.length/2;if(!Number.isInteger(n)||n===0||n>4096)throw Error("bad signature"); const norm=n===65&&parseInt(sig.slice(128,130),16)<27 ?sig.slice(0,128)+(parseInt(sig.slice(128,130),16)+27).toString(16).padStart(2,"0") :sig; const tail=encUint(n)+norm.padEnd(Math.ceil(norm.length/64)*64,"0"); return"0x"+SEL_P2TF+encAddr(tok)+encUint(amount)+encUint(nonce)+encUint(deadline)+pad32("a0")+tail}; const capsFor=(c,id)=>{ for(const key of Object.keys(c)){ try{if(BigInt(key)===id)return c[key]}catch{} } return undefined}; const hasAtomicBatch=c=>{ if(!c||typeof c!=="object")return false; const own=capsFor(c,BigInt(CHAIN_ID)); const k=own!==undefined?own:capsFor(c,0n); return!!(k&&k.atomic&&(k.atomic.status==="supported"||k.atomic.status==="ready"))}; const canBatch=async owner=>{ try{const c=await rpc("wallet_getCapabilities",[owner]); return hasAtomicBatch(c)}catch{return false}}; let snd=LS.snd!=="0"; let AC;const play=ns=>{if(!snd)return;try{AC=AC||new(window.AudioContext||window.webkitAudioContext);if(AC.state==="suspended")AC.resume();const t=AC.currentTime+.02;ns.forEach(([f,d,l,v])=>{const o=AC.createOscillator(),g=AC.createGain();o.type="triangle";o.frequency.value=f;o.connect(g);g.connect(AC.destination);g.gain.setValueAtTime(0,t+d);g.gain.linearRampToValueAtTime(v,t+d+.012);g.gain.exponentialRampToValueAtTime(1e-4,t+d+l);o.start(t+d);o.stop(t+d+l+.02)})}catch{}}; const sBlip=()=>play([[880,0,.07,.05]]); const sOpen=()=>play([[523.25,0,.3,.1],[783.99,.09,.3,.1]]); const sSend=()=>play([[392,0,.12,.07],[587.33,.07,.24,.07]]); const sGot=()=>play([[392,0,.11,.09],[493.88,.08,.11,.09],[587.33,.16,.11,.09],[783.99,.24,.6,.12]]); const sFail=()=>play([[311.13,0,.18,.07],[233.08,.13,.4,.07]]); const sPew=()=>play([[720,0,.04,.03]]); const sHit=()=>play([[440,0,.07,.05],[330,.04,.09,.04]]); const sendTx=req=>rpc(S,req).then(r=>{sSend();return r}); const sendBatch=async(owner,calls)=>{ const res=await rpc("wallet_sendCalls",[{version:"2.0.0",chainId:toHex(CHAIN_ID),from:owner,atomicRequired:true,calls}]); sSend(); const id=typeof res==="string"?res:res.id; for(let i=0;i<600;i++){ try{const st=await rpc("wallet_getCallsStatus",[id]); const rs=(st&&st.receipts)||[]; if(rs.some(r=>r&&r.status==="0x0"))throw Error("batch reverted"); const q=String(st&&st.status),done=q==="200"||/CONFIRMED|SUCCESS/i.test(q); const last=rs.length&&(done||rs.length>=calls.length)?rs[rs.length-1]:null,x=last&&(last.transactionHash||last.hash); if(x)return x; if(q==="400"||q==="500"||/fail|revert|reject/i.test(q))throw Error("batch failed"); if(done)throw Error("batch confirmed on chain, but the wallet returned no receipt — check your wallet's activity before retrying"); }catch(e){if(/^batch /.test(e.message))throw e} await new Promise(r=>setTimeout(r,1000))} throw Error("batch timed out")}; const encCalls=cs=>{const n=cs.length;let head="",tail="";let off=n*32; for(const c of cs){const d=strip0x(c),len=d.length/2; head+=encUint(off);const body=encUint(len)+d.padEnd(Math.ceil(d.length/64)*64,"0"); tail+=body;off+=body.length/2} return"0x"+SEL_MULTICALL+pad32("20")+encUint(n)+head+tail}; const MC3="0xcA11bde05977b3631167028862bE2a173976CA11"; const encAgg3=cs=>{const n=cs.length;let head="",tail="",off=n*32; for(const c of cs){const d=strip0x(c.data),len=d.length/2; const body=encAddr(c.to)+encBool(true)+encUint(96)+encUint(len)+d.padEnd(Math.ceil(d.length/64)*64,"0"); head+=encUint(off);tail+=body;off+=body.length/2} return"0x82ad56cb"+pad32("20")+encUint(n)+head+tail}; let mcOk=0,mcFailed=0; const decAgg3=hex=>{const h=strip0x(hex),at=i=>h.slice(i*64,(i+1)*64); const n=Number(BigInt("0x"+at(1))),out=[]; for(let i=0;i<n;i++){const rel=Number(BigInt("0x"+at(2+i)))/32,w=2+rel; const ok=BigInt("0x"+at(w))===1n,bo=Number(BigInt("0x"+at(w+1)))/32,lw=w+bo; const len=Number(BigInt("0x"+at(lw))); if(ok)mcOk++;else mcFailed++; out.push(ok?"0x"+h.slice((lw+1)*64,(lw+1)*64+len*2):null)} return out}; const mc3=async(cs,tag=L)=>cs.length?decAgg3(await rpc(C,[{to:MC3,data:encAgg3(cs)},tag])):[]; const MC3_MAX=16; const MC3_COLD=8; const mc3Clamp=n=>Number.isFinite(n)&&n>=2&&n<=MC3_MAX?Math.floor(n):MC3_COLD; let mc3Cap=mc3Clamp(Number(LS["zswap:mc3"])); let mc3Won=0; const mc3Save=()=>{try{LS["zswap:mc3"]=String(mc3Cap)}catch{}}; const cfgBatch=async(cs,tag)=>{ if(CHAIN_ID===1)return mc3Deep(cs,tag); if(!cs.length)return[]; try{return decAgg3(await l1Read("eth_call",[{to:MC3,data:encAgg3(cs)},tag||L]))} catch{return cs.map(()=>null)} }; const mc3Split=(cs,n)=>{const o=[];for(let i=0;i<cs.length;i+=n)o.push(cs.slice(i,i+n));return o}; const MC3_LANES=12; let mc3Live=0; const mc3Waiting=[]; const mc3Gate=async fn=>{ while(mc3Live>=MC3_LANES)await new Promise(r=>mc3Waiting.push(r)); mc3Live++; try{return await fn()} finally{mc3Live--;const next=mc3Waiting.shift();if(next)next()} }; let mcGaveUp=0; const mc3Deep=async(cs,tag=L,depth=0)=>{ if(!cs.length)return[]; const fan=async n=>(await Promise.all(mc3Split(cs,n).map(c=>mc3Deep(c,tag,depth+1)))).flat(); if(cs.length>mc3Cap&&depth<8)return fan(mc3Cap); try{ const r=await mc3Gate(()=>mc3(cs,tag)); if(cs.length>=mc3Cap&&mc3Cap<MC3_MAX&&r.every(x=>x!=null)&&++mc3Won>=2){mc3Cap++;mc3Won=0;mc3Save()} return r; } catch(e){ mc3Won=0; if(cs.length<2||depth>=8){mcGaveUp+=cs.length;return cs.map(()=>null)} const h=cs.length>>1; if(h<mc3Cap){mc3Cap=h;mc3Save()} await new Promise(r=>setTimeout(r,150*(depth+1))); return fan(h); } }; let bnVal="",bnAt=0,bnJob=null; const BN_TTL=12000; const bnFetch=()=>bnJob||(bnJob=rpc("eth_blockNumber",[]) .then(n=>{bnVal=n;bnAt=Date.now();return n}) .finally(()=>{bnJob=null})); const blockNow=()=>{ const age=Date.now()-bnAt; if(!bnVal||age>=BN_TTL)return bnFetch(); if(age>BN_TTL/2)bnFetch().catch(()=>{}); return Promise.resolve(bnVal); }; const codeSeen={}; const CODE_MISS_TTL=60000; const hasCode=async a=>{ if(codeSeen[a]===true)return true; const miss=codeSeen[a]; if(miss&&Date.now()-miss<CODE_MISS_TTL)return false; const h=await rpc("eth_getCode",[a,L]); const ok=(h||"").length>4; codeSeen[a]=ok||Date.now(); return ok; }; const REF_N=100n; const CH_WICK_CAP=3; const IMPACT_HIDE=50n, IMPACT_WARN=500n, IMPACT_CONFIRM=1500n, IMPACT_TYPED=3000n; const impactBps=(v,ref,eo)=>{if(!v||!ref)return null;const lin=ref*REF_N; if(lin===0n)return 0n; return eo?(v<=lin?0n:(v-lin)*10000n/lin):(v>=lin?0n:(lin-v)*10000n/lin)}; const sa