memoscan
← all memos

Memo 0x4a0607fc…0a7ddc on Ethereum

0xacfba7ce…4082·#25,784,647·view on Etherscan
spec of row.v.split(";")){ const p=spec.trim().split(":"); if(p.length!==5||p[0]!=="v1")continue; const other=p[1]==="0"?ZERO:p[1]; const hooks=p[4]==="0"?ZERO:p[4]; if(!/^0x[0-9a-f]{40}$/i.test(other)||!/^0x[0-9a-f]{40}$/i.test(hooks))continue; if(!/^\d{1,7}$/.test(p[2])||!/^\d{1,7}$/.test(p[3]))continue; const fee=Number(p[2]),ts=Number(p[3]); if(!Number.isInteger(fee)||!Number.isInteger(ts)||ts<1)continue; if(other.toLowerCase()===tokenAddr.toLowerCase())continue; const a=tokenAddr.toLowerCase(),b=other.toLowerCase(); const zeroFirst=BigInt(a)<BigInt(b); out.push({c0:zeroFirst?tokenAddr:other,c1:zeroFirst?other:tokenAddr,fee,ts,hooks}); if(out.length===8)break; } return out; } function v4PoolsFor(f,t){ const fa=f.addr.toLowerCase(),ta=t.addr.toLowerCase(); const seen=new Set(),out=[]; for(const tok of [f,t])for(const p of (tok.v4||[])){ const c0=p.c0.toLowerCase(),c1=p.c1.toLowerCase(); if(!((c0===fa&&c1===ta)||(c0===ta&&c1===fa)))continue; const id=`${c0}:${c1}:${p.fee}:${p.ts}:${p.hooks.toLowerCase()}`; if(seen.has(id))continue; seen.add(id); out.push({...p,zeroForOne:c0===fa}); } return out; } const encPoolKey=p=>encAddr(p.c0)+encAddr(p.c1)+encUint(p.fee)+encUint(p.ts)+encAddr(p.hooks); const SEL_QUOTE_BEST="2adaa389",SEL_EFFFEE="ef66de32"; const PROUTE="0x0000007Be74558A1F8c9045301c6F44C8eD0c9eB"; const SEL_PROUTE="5d6498e1",SEL_PCHECKPOINT="0b7c6c6c"; const SEL_PROUTEWETH="78fd78b0"; const SEL_ZAPIN="c98c2c0b"; const SEL_PREVIEW_ZAP="e7cddab0"; const encPRouteWeth=(pools,tokenOut,amountIn,minOut,to)=> "0x"+SEL_PROUTEWETH+encUint(160)+encAddr(tokenOut)+encUint(amountIn) +encUint(minOut)+encAddr(to)+encUint(pools.length)+pools.map(encAddr).join(""); const encPRoute=(pools,tokenIn,tokenOut,amountIn,minOut,to)=> "0x"+SEL_PROUTE+encUint(192)+encAddr(tokenIn)+encAddr(tokenOut)+encUint(amountIn) +encUint(minOut)+encAddr(to)+encUint(BigInt(pools.length))+pools.map(encAddr).join(""); const SEL_PAIR_COUNT="355da246",SEL_CREATORBPS="17773ebb"; const PPOLICY="0x00000045fc7b570Be4d71F67219508ebD295EC6D"; const SEL_ROUTABLE="9662c498",SEL_QUOTE_ALL="89941805"; const LQ_SCAN=128; const LQ_SHOW=24; const isEthLike=a=>a===ZERO||a.toLowerCase()===WETH.toLowerCase(); async function quotePrecision(f,t,amountIn,sender,block){ if(PPLENS===ZERO||amountIn<=0n)return null; const nat=a=>a.toLowerCase()===WETH.toLowerCase()?ZERO:a; const vars=[]; const addVar=(a,b)=>{ const [x,y]=a.toLowerCase()<b.toLowerCase()?[a,b]:[b,a]; if(!vars.some(v=>v.c0===x&&v.c1===y&&v.tokenIn===a))vars.push({c0:x,c1:y,tokenIn:a}); }; const forms=a=>a===ZERO?[ZERO,WETH] :a.toLowerCase()===WETH.toLowerCase()?[WETH,ZERO]:[a]; for(const a of forms(f.addr))for(const b of forms(t.addr)){ if(nat(a)===nat(b))continue; addVar(a,b); } const reqs=[]; for(const v of vars)reqs.push( {to:PPLENS,data:"0x"+SEL_QUOTE_BEST+encAddr(v.c0)+encAddr(v.c1) +encAddr(sender)+encAddr(v.tokenIn)+encUint(amountIn)+encUint(0n)+encUint(BigInt(LQ_SCAN))}, {to:PFACTORY,data:"0x"+SEL_PAIR_COUNT+encAddr(v.c0)+encAddr(v.c1)}); const res=await mc3Deep(reqs,block); let pool="",out=0n,n=0,fA=f.addr,won=null; for(let i=0;i<vars.length;i++){ const q=res[i*2],c=res[i*2+1]; const b=decBest(q); if(!b)continue; if(b.out<=out)continue; pool=b.pool;out=b.out;fA=vars[i].tokenIn;won=vars[i]; try{if(c)n=Number(BigInt(c))}catch{n=0} } if(!pool||!won)return await hubHop(f,t,amountIn,sender,block); const tA=won.c0===fA?won.c1:won.c0; let fee=0n; const feeReq=p=>({to:PPLENS, data:"0x"+SEL_EFFFEE+encAddr(p)+encAddr(sender)+encAddr(fA)+encUint(amountIn)}); const [fx,rt]=await mc3Deep([feeReq(pool),routableReq([pool])],block); if(policyRefuses(rt,1)){ const alt=await bestRoutable(won.c0,won.c1,fA,amountIn,sender,block); if(!alt)return await hubHop(f,t,amountIn,sender,block); pool=alt.pool;out=alt.out; const [fx2]=await mc3Deep([feeReq(pool)],block); if(fx2)fee=BigInt(fx2); }else if(fx)fee=BigInt(fx); return {pools:[pool],out,fee,capped:n>LQ_SCAN,tokenIn:fA,tokenOut:tA, unwrap:fA===ZERO&&f.addr!==ZERO?amountIn:0n, wrap:fA!==ZERO&&f.addr===ZERO?amountIn:0n, outDiffers:(tA===ZERO)!==(t.addr===ZERO)}; } const routableReq=pools=>({to:PPOLICY, data:"0x"+SEL_ROUTABLE+encUint(32)+encUint(BigInt(pools.length))+pools.map(encAddr).join("")}); function policyRefuses(raw,n){ if(!raw)return false; const h=strip0x(raw); if(h.length<128+n*64)return false; const len=Number(BigInt("0x"+h.slice(64,128))); if(len!==n)return false; for(let i=0;i<n;i++)if(BigInt("0x"+h.slice(128+i*64,128+(i+1)*64))===0n)return true; return false; } async function bestRoutable(c0,c1,tokenIn,amountIn,sender,block){ const [raw]=await mc3Deep([{to:PPLENS,data:"0x"+SEL_QUOTE_ALL+encAddr(c0)+encAddr(c1) +encAddr(sender)+encAddr(tokenIn)+encUint(amountIn)+encUint(0n)+encUint(BigInt(LQ_SCAN))}],block); const cands=decAll(raw); if(!cands.length)return null; const [rt]=await mc3Deep([routableReq(cands.map(c=>c.pool))],block); if(!rt)return null; const h=strip0x(rt); if(h.length<128+cands.length*64)return null; let win=null; for(let i=0;i<cands.length;i++){ if(BigInt("0x"+h.slice(128+i*64,128+(i+1)*64))===0n)continue; if(!win||cands[i].out>win.out)win=cands[i]; } return win; } function decAll(raw){ if(!raw)return[]; const h=strip0x(raw); if(h.length<128)return[]; const n=Number(BigInt("0x"+h.slice(64,128))); const out=[]; for(let i=0;i<n;i++){ const b=128+i*192; if(h.length<b+192)break; const pool="0x"+h.slice(b+24,b+64),o=BigInt("0x"+h.slice(b+64,b+128)); if(o<=0n||/^0x0{40}$/i.test(pool))continue; out.push({pool,out:o}); } return out; } function decBest(raw){ if(!raw)return null; const h=strip0x(raw); if(h.length<128)return null; const pool="0x"+h.slice(24,64),out=BigInt("0x"+h.slice(64,128)); if(out<=0n||/^0x0{40}$/i.test(pool))return null; return {pool,out}; } async function hubHop(f,t,amountIn,sender,block){ if(isEthLike(f.addr)||isEthLike(t.addr))return null; const enc=(a,b,tokenIn,amt)=>{ const [c0,c1]=a.toLowerCase()<b.toLowerCase()?[a,b]:[b,a]; return [{to:PPLENS,data:"0x"+SEL_QUOTE_BEST+encAddr(c0)+encAddr(c1) +encAddr(sender)+encAddr(tokenIn)+encUint(amt)+encUint(0n)+encUint(BigInt(LQ_SCAN))}, {to:PFACTORY,data:"0x"+SEL_PAIR_COUNT+encAddr(c0)+encAddr(c1)}]}; const count=raw=>{try{return raw?Number(BigInt(raw)):0}catch{return 0}}; const hubs=[ZERO,WETH]; const legs=[]; const first=await mc3Deep(hubs.flatMap(h=>enc(f.addr,h,f.addr,amountIn)),block); for(let i=0;i<hubs.length;i++){ const b=decBest(first[i*2]); if(b)legs.push({hub:hubs[i],pool:b.pool,mid:b.out,n:count(first[i*2+1])}); } if(!legs.length)return null; const second=await mc3Deep(legs.flatMap(l=>enc(l.hub,t.addr,l.hub,l.mid)),block); let win=null; for(let i=0;i<legs.length;i++){ const b=decBest(second[i*2]); if(!b||(win&&b.out<=win.out))continue; win={pools:[legs[i].pool,b.pool],out:b.out,mid:legs[i].mid,hub:legs[i].hub, n:Math.max(legs[i].n,count(second[i*2+1]))}; } if(!win)return null; let fee=0n; const [a,b,rt]=await mc3Deep([ {to:PPLENS,data:"0x"+SEL_EFFFEE+encAddr(win.pools[0])+encAddr(sender)+encAddr(f.addr)+encUint(amountIn)}, {to:PPLENS,data:"0x"+SEL_EFFFEE+encAddr(win.pools[1])+encAddr(sender)+encAddr(win.hub)+encUint(win.mid)}, routableReq(win.pools), ],block); if(policyRefuses(rt,win.pools.length))return null; const fa=a?BigInt(a):0n,fb=b?BigInt(b):0n; fee=fa+fb-(fa*fb)/1000000n; return {pools:win.pools,out:win.out,fee,capped:win.n>LQ_SCAN, tokenIn:f.addr,tokenOut:t.addr,unwrap:0n,wrap:0n,outDiffers:false}; } const QPAIR=2; const SEL_BBS="e7798987"; const HUBS=()=>[WETH,...NUMERAIRES,"0x2260fac5e5542a773aa44fbcfedf7c193bc2c599","0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0"]; async function hubRoute(f,t,amt,sb,dl,to,rf,block){ const nf=(f.addr===ZERO?WETH:f.addr).toLowerCase(),nt=(t.addr===ZERO?WETH:t.addr).toLowerCase(); const H=HUBS().filter(h=>h.toLowerCase()!==nf&&h.toLowerCase()!==nt); if(!H.length)return null; const E=(x,i,o,n)=>({to:ZQUOTER,data:"0x"+SEL_BBS+encAddr(x)+encBool(false)+encAddr(i)+encAddr(o)+encUint(n)+encUint(sb)+encUint(dl)}); const D=h=>{try{return decQ(h,sb,false,0,4,0,6)}catch{return null}}; const L=[],r1=await mc3Deep(H.map(h=>E(ZROUTER,f.addr,h,amt)),block); for(let i=0;i<H.length;i++){const a=r1[i]&&D(r1[i]);if(a&&a.amountLimit>0n)L.push({h:H[i],a})} if(!L.length)return null; const r2=await mc3Deep(L.map(x=>E(to,x.h,t.addr,x.a.amountLimit)),block); let B=null; for(let i=0;i<L.length;i++){const b=r2[i]&&D(r2[i]); if(b&&b.best.amountOut>0n&&(!B||b.best.amountOut>B.b.best.amountOut))B={...L[i],b}} if(!B)return null; const c=[B.a.callData,B.b.callData,encSweep(B.h,0n,rf),encSweep(ZERO,0n,rf)]; return{best:{source:B.b.best.source,feeBps:B.b.best.feeBps,amountIn:amt,amountOut:B.b.best.amountOut}, callData:encCalls(c),amountLimit:B.b.amountLimit, msgValue:f.addr===ZERO?amt:0n,spender:f.addr===ZERO?null:ZROUTER}; } async function quoteV4Pools(f,t,amountIn,block){ const pools=v4PoolsFor(f,t); if(!pools.length||amountIn<=0n)return null; const rs=(await mc3Deep(pools.map(p=>({to:V4LENS, data:"0x"+SEL_V4QUOTE+encBool(false)+encAddr(f.addr)+encAddr(t.addr) +encUint(p.fee)+encUint(p.ts)+encAddr(p.hooks)+encUint(amountIn)})),block)) .map(h=>{try{const x=strip0x(h||"");return x.length>=128?BigInt("0x"+x.slice(64,128)):0n}catch{return 0n}}); let best=null; for(let i=0;i<pools.length;i++)if(rs[i]>0n&&(!best||rs[i]>best.amountOut)) best={pool:pools[i],amountIn,amountOut:rs[i]}; return best; } const setListNote=t=>{ const el=document.getElementById("listNote"); if(!el)return; el.textContent=t||""; el.classList.toggle("hide",!t)}; const setListSource=w=>setListNote(w?"Built-in token list — "+w:""); let rankFellBack=false; const rankedIds=async()=>{ rankFellBack=false; try{ const ids=decUintArr(await rpc(C,[{to:ZLISTLENS,data:"0x"+SEL_RANKEDIDS},L])); if(ids.length)return ids; }catch{} try{ const ids=decUintArr(await rpc(C,[{to:TOKENLIST,data:"0x"+SEL_RANKEDIDS},L])); if(ids.length)rankFellBack=true; return ids; }catch{return[]} }; async function loadTokenList(){ if(TOKENLIST===ZERO)return setListSource("registry address not set"); try{ const ids=await rankedIds(); if(!ids.length)return setListSource("registry is empty"); const raw=await mc3Deep(ids.slice(0,64).map(id=>({to:TOKENLIST,data:"0x"+SEL_JSON+encUint(id)}))); const rows=raw.map(h=>{try{return h?decStr(h):null}catch{return null}}); const next=[]; for(const row of rows){ if(!row)continue; let t;try{t=JSON.parse(row)}catch{continue} if(t.k!=="eip155")continue; const std=t.p==="Native"||t.p==="ERC-20"?"ft":t.p==="ERC-721"?"nft":""; if(!std)continue; if(!/^0x[0-9a-f]{40}$/i.test(t.a||""))continue; if(!Number.isInteger(t.d)||t.d<0||t.d>36)continue; if(next.some(x=>x.addr.toLowerCase()===t.a.toLowerCase()))continue; const sym=safeSym(t.s).slice(0,12); const logo=safeUrl(t.l); next.push({sym,addr:t.a.toLowerCase(),dec:t.d,std,icon:logo?`<img src="${logo}" width="20" height="20">`:genIcon(sym), name:String(t.n??"").slice(0,64),desc:String(t.desc??"").slice(0,240), v4:parseV4Pools(t.e,t.a)}); } next.sort((a,b)=>(a.std==="nft")-(b.std==="nft")); if(!next.some(t=>t.std==="ft"))return setListSource("registry returned nothing swappable"); const mine=TOKENS.filter(t=>t.cust&&!next.some(x=>x.addr===t.addr.toLowerCase())); let born=[]; LAUNCHED.length=0; try{ const cnt=Number(BigInt(await rpc(C,[{to:PFACTORY,data:"0x"+SEL_BYCREATOR_N+encAddr(PLAUNCH)},L])||"0x0")); const take=Math.min(cnt,LAUNCH_SCAN); const raw=take?await rpc(C,[{to:PFACTORY,data:"0x"+SEL_BYCREATOR+encAddr(PLAUNCH)+encUint(BigInt(cnt-take))+encUint(BigInt(take))},L]):"0x"; const h=strip0x(raw||""),n=h.length>=128?Number(BigInt("0x"+h.slice(64,128)||"0")):0; let pools=[]; for(let i=0;i<n&&i<take;i++)pools.push("0x"+h.slice(128+i*64+24,128+(i+1)*64)); if(pools.length){ const depth=await mc3Deep(pools.map(a=>[{to:a,data:"0x"+SEL_RESERVE0}]).flat()); const byDepth=pools.map((p,i)=>{let d=0n;try{d=BigInt(depth[i]||"0x0")}catch{}return{p,d}}) .sort((x,y)=>x.d===y.d?0:(x.d<y.d?1:-1)).slice(0,LAUNCH_SHOW); pools=byDepth.map(x=>x.p); const meta=await mc3Deep(pools.flatMap(a=>[{to:a,data:"0x"+SEL_TOKEN1}])); const toks=[]; meta.forEach((x,i)=>{const a=x?("0x"+strip0x(x).slice(24)).toLowerCase():""; if(/^0x[0-9a-f]{40}$/.test(a))toks.push({a,pi:i})}); const seen=new Set(next.map(x=>x.addr.toLowerCase())); const info=await mc3Deep(toks.flatMap(({a})=>[{to:a,data:"0x95d89b41"},{to:a,data:"0x"+SEL_CONTRACTURI}, {to:PLAUNCH,data:"0x"+SEL_CREATOROF+encAddr(a)}])); const taken=new Set(next.map(x=>x.sym.toLowerCase())); toks.forEach(({a,pi},i)=>{ if(seen.has(a))return; seen.add(a); let sym="?";try{sym=safeSym(decodeString(info[i*3]||"0x").trim()).slice(0,12)}catch{} if(!sym||sym==="?")return; if(taken.has(sym.toLowerCase()))sym+=" "+a.slice(0,6)+"…";else taken.add(sym.toLowerCase()); let art="";try{art=imgFromContractURI(decodeString(info[i*3+1]||"0x"))}catch{} if(art)logoCache[a]=art; const dep=byDepth[pi]?byDepth[pi].d:0n; let by="";try{const c="0x"+strip0x(info[i*3+2]||"").slice(24);if(/^0x[0-9a-f]{40}$/i.test(c)&&!/^0x0{40}$/i.test(c))by=short(c)}catch{} const desc=[dep>0n?`${(+formatUnits(dep,18)).toFixed(dep<10n**16n?5:3)} ETH liquidity`:"no liquidity yet", by?`by ${by}`:""].filter(Boolean).join(" \u00b7 "); born.push({sym,addr:a,dec:18,std:"ft",name:"",desc,launched:1,dep, icon:art?`<img width="20" height="20" style="border-radius:50%;object-fit:cover" src="${art}" alt="">`:genIcon(sym)}); LAUNCHED.push({addr:a,sym,pool:pools[pi]||""}); }); } }catch{} const anchors=BUILTIN.filter(b=>(b.addr===ZERO||b.addr===WETH)&&!next.some(x=>x.addr===b.addr)); const bornAt=new Set(born.map(x=>x.addr.toLowerCase())); TOKENS.splice(0,TOKENS.length,...next,...anchors,...born, ...mine.filter(t=>!bornAt.has(t.addr.toLowerCase()))); setListNote(rankFellBack?"Ranked by listing order — conviction unavailable":""); }catch(e){setListSource("could not be reached")} } const strip0x=h=>h.startsWith("0x")?h.slice(2):h; const pad32=h=>strip0x(h).padStart(64,"0"); const encUint=v=>pad32(BigInt(v).toString(16)); const encAddr=a=>pad32((a||ZERO).toLowerCase()); const isAddr=a=>/^0x[0-9a-fA-F]{40}$/.test(a||""); const decStr=hex=>{const h=strip0x(hex);const n=parseInt(h.slice(64,128),16); return new TextDecoder().decode(hexToBytes(h.slice(128,128+n*2)))}; const decUintArr=hex=>{const h=strip0x(hex);const n=parseInt(h.slice(64,128),16);const o=[]; for(let i=0;i<n;i++)o.push(BigInt("0x"+h.slice(128+i*64,192+i*64)));return o}; const encBool=b=>pad32(b?"1":"0"); const toHex=v=>"0x"+BigInt(v).toString(16); const parseUnits=(s,dec)=>{ const t=s.trim().replace(/,/g,""); if(!/^(?:\d+|\d*\.\d+|\d+\.)$/.test(t))throw Error("invalid amount"); const[ip,fp=""]=t.split("."); if(fp.length>dec)throw Error("too many decimals"); return BigInt((ip||"0")+fp.padEnd(dec,"0")); }; const formatUnits=(v,dec)=>{ if(!dec)return BigInt(v).toString(); const s=BigInt(v).toString().padStart(dec+1,"0"); const ip=s.slice(0,-dec); const fp=s.slice(-dec).replace(/0+$/,""); return fp?`${ip}.${fp}`:ip; }; const trimAmt=(v,dec)=>{const s=formatUnits(v,dec),i=s.indexOf(".");if(i<0)return s;const r=s.slice(0,i+7).replace(/\.?0+$/,"");return r==="0"&&v?s:r}; const maxAmt=(v,dec)=>{v=BigInt(v);if(dec<=6)return formatUnits(v,dec); const u=10n**BigInt(dec-6);return formatUnits((v+u-1n)/u,6)}; const fitFont=el=>{ const l=el.value.length,s=l>18?".9em":l>14?"1.1em":l>10?"1.25em":"1.65em"; if(el.style.fontSize!==s)el.style.fontSize=s; }; const decQ=(hex,slip,eo,u,v,S,mv)=>{ const h=strip0x(hex),num=i=>BigInt("0x"+h.slice(i*64,(i+1)*64)),E=()=>{throw Error("bad quote")}; if(h.length<(v+2)*64)E(); const o=Number(num(v))*2;if(o+64>h.length)E(); const n=Number(BigInt("0x"+h.slice(o,o+64)));if(!n||o+64+n*2>h.length)E(); const g=num(u+3),t=g>0n,k=S?(num(3)>0n?0:u):t?u:0,B=10000n,ai=S?num(2)+num(u+2):num(2),ao=S?num(3)+g:t?g:num(3),q=eo?ai:ao; const src=[];for(let w=0;w<=u;w+=4)if(num(w+2)>0n||num(w+3)>0n)src.push(Number(num(w))); return{best:{source:Number(num(k)),feeBps:num(k+1),amountIn:ai,amountOut:ao},sources:src,callData:"0x"+h.slice(o+64,o+64+n*2),amountLimit:eo?(q*(B+slip)+B-1n)/B:q*(B-slip)/B,msgValue:num(mv||v+1),slipBps:slip}; }; const merge=(est,exe)=>{if(!est)return exe;if(!exe)return null;return{...exe,best:est.best}}; const NO_WALLET="No wallet detected."; let PROV=null; const prov=()=>PROV||window.ethereum; const rpc=(method,params)=>{const e=prov(); return e?e.request({method,params}) :Promise.reject(Object.assign(Error(NO_WALLET),{noWallet:true}))}; 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;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!==1||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 encStr=v=>{const b=new TextEncoder().encode(v);let h=""; for(const x of b)h+=x.toString(16).padStart(2,"0"); return pad32("20")+encUint(b.length)+h.padEnd(Math.ceil(h.length/64)*64,"0")}; 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=>/^[\x21-\x7e]+$/.test(n)&&n.split(".").every(l=>l.length>0); const nsFwd=async(reg,n)=>{const id=await rpc(C,[{to:reg,data:"0x"+SEL_CID+encStr(n)},L]); if(strip0x(id||"").length!==64)return""; return retAddr(await rpc(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=> rpc(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 rpc(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 rpc(C,[{to:f.r,data:inner},L])); if(!await ensWild(f.r))return""; try{return retAddr(decBytes(await rpc(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 rpc(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=>rpc(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"])if(domainSep(name,ver,tok).toLowerCase()===ds.toLowerCase()) return{name,ver,nonce}; }catc