0x28996f7d…515asent to0x00000000…5b01·#24,398,914·view on Etherscan
<!doctype html><html><head><meta name="title" content="PUSH4"><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><style>*{margin:0;padding:0;box-sizing:border-box}body,html{width:100%;height:100%;overflow:hidden;font-family:monospace}#container{width:100%;height:100%;display:flex;flex-direction:column;align-items:center}#artwork{width:100%;height:calc(100% - 30px);display:flex;align-items:flex-start;justify-content:center}#artwork iframe,#artwork img{height:100%;width:auto;max-width:100%;image-rendering:pixelated}#info{height:30px;display:flex;flex-direction:column;justify-content:flex-end;gap:5px;visibility:hidden;opacity:0;margin:0 auto}#info.loaded{visibility:visible;opacity:1}#info-text{display:flex;justify-content:space-between;padding:0 0 6px;font-size:11px;color:#666;letter-spacing:.3px}#progress-bar{height:2px;background:#555}#progress{height:100%;background:#222;width:100%}</style></head><body><div id="container"><div id="artwork"><div id="loading">Loading...</div></div><div id="info"><div id="info-text"><span><span id="title">--</span> by <span id="creator">--</span></span> <span id="proxy">--</span></div><div id="progress-bar"><div id="progress"></div></div></div></div><script>const RPC_URLS=[{{FILE_URIS}}],BLOCK_INTERVAL={{BLOCK_INTERVAL}},CONTRACT_ADDRESS="{{CORE_ADDRESS}}",GAS_LIMIT="0x20C85580";let currentRpcIndex=0,lastBlock=0,lastProxyIdx=-1,proxyAddress=null,proxyCount=0,rendererAddress=null;function showError(t){document.getElementById("artwork").innerHTML='<div style="color: #ff5555; padding: 20px; text-align: center;">'+t+"</div>"}async function fetchWithFallback(t,e){const r=[];for(let n=0;n<RPC_URLS.length;n++){const o=(currentRpcIndex+n)%RPC_URLS.length,a=RPC_URLS[o];try{const n=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:t,params:e})});if(!n.ok){const t=`HTTP ${n.status}: ${n.statusText}`;r.push({rpc:a,error:t});continue}const c=await n.text();let l;try{l=JSON.parse(c)}catch(t){const e=`JSON parse error: ${t.message} (response length: ${c.length})`;r.push({rpc:a,error:e});continue}if(l.error){const t=`RPC error: ${JSON.stringify(l.error)}`;r.push({rpc:a,error:t});continue}return currentRpcIndex=o,l.result}catch(t){const e=t.message||String(t);r.push({rpc:a,error:e});continue}}throw console.error("[RPC] All RPCs failed:",r),showError("Connection Error: All RPC nodes are unresponsive."),new Error("All RPCs failed: "+JSON.stringify(r))}async function getBlockNumber(){const t=await fetchWithFallback("eth_blockNumber",[]);return parseInt(t,16)}async function discoverProxy(){try{const t="0x"+(await fetchWithFallback("eth_call",[{to:CONTRACT_ADDRESS,data:"0xec556889"},"latest"])).slice(26,66);return"0x0000000000000000000000000000000000000000"===t?null:t}catch(t){return console.error("[Proxy] Failed to discover proxy:",t),null}}async function getProxyCount(t){if(!t)return 0;try{const e=await fetchWithFallback("eth_call",[{to:t,data:"0x37c954d8"},"latest"]);return parseInt(e,16)}catch(t){return console.error("[ProxyCount] Failed to get proxy count:",t),0}}async function getProxyAt(t,e){if(!t)return null;const r="0xcc935efe"+e.toString(16).padStart(64,"0");try{const e=await fetchWithFallback("eth_call",[{to:t,data:r},"latest"]);return"0x"+e.slice(26,66)}catch(t){return console.error("[ProxyAt] Failed to get proxy at index:",t),null}}async function getCurrentProxy(t){if(!t)return null;try{const e=await fetchWithFallback("eth_call",[{to:t,data:"0x3f2d9d88"},"latest"]);return"0x"+e.slice(26,66)}catch(t){return console.error("[CurrentProxy] Failed to get current proxy:",t),null}}async function getCurrentProxyIndex(t){if(!t)return 0;try{const e=await fetchWithFallback("eth_call",[{to:t,data:"0x81ef9a43"},"latest"]);return parseInt(e,16)}catch(t){return console.error("[CurrentProxyIndex] Failed to get current proxy index:",t),0}}function decodeString(t){const e=t.slice(2),r=2*parseInt(e.slice(0,64),16),n=2*parseInt(e.slice(r,r+64),16);return e.slice(r+64,r+64+n).match(/.{2}/g).map(t=>String.fromCharCode(parseInt(t,16))).join("")}async function getProxyTitle(t){if(!t)return"--";try{const e=await fetchWithFallback("eth_call",[{to:t,data:"0x4a79d50c"},"latest"]);return decodeString(e)}catch(t){return console.error("[ProxyTitle] Failed to get title:",t),"--"}}async function getProxyCreator(t){if(!t)return"--";try{const e=(await fetchWithFallback("eth_call",[{to:t,data:"0x02d05d3f"},"latest"])).slice(2),r=2*parseInt(e.slice(0,64),16),n=r+2*parseInt(e.slice(r,r+64),16),o=2*parseInt(e.slice(n,n+64),16),a=e.slice(n+64,n+64+o);return a.match(/.{2}/g).map(t=>String.fromCharCode(parseInt(t,16))).join("")}catch(t){return console.error("[ProxyCreator] Failed to get creator:",t),"--"}}async function discoverRenderer(){try{return"0x"+(await fetchWithFallback("eth_call",[{to:CONTRACT_ADDRESS,data:"0x8ada6b0f"},"latest"])).slice(26,66)}catch(t){return console.error("[Renderer] Failed to discover renderer:",t),null}}async function getSvgDataUri(){return decodeString(await fetchWithFallback("eth_call",[{to:rendererAddress,data:"0xbfec768f",gas:GAS_LIMIT},"latest"]))}function syncInfoWidth(){const t=document.querySelector("#artwork img"),e=document.getElementById("info");t&&(e.style.width=t.clientWidth+"px")}function renderArtwork(t){const e=document.getElementById("artwork");e.innerHTML='<img src="'+t+'" alt="PUSH4">',e.querySelector("img").onload=syncInfoWidth}function updateProgress(t){const e=document.getElementById("progress"),r=t/BLOCK_INTERVAL*100,n=Math.min((t+1)/BLOCK_INTERVAL*100,100);e.style.transition="none",e.style.width=r+"%",requestAnimationFrame(function(){requestAnimationFrame(function(){e.style.transition="width 12s linear",e.style.width=n+"%"})})}async function pollBlock(){try{const t=await getBlockNumber();if(t!==lastBlock){const e=await getCurrentProxyIndex(proxyAddress);if(e!==lastProxyIdx){const r=await getCurrentProxy(proxyAddress),[n,o,a]=await Promise.all([getProxyTitle(r),getProxyCreator(r),getSvgDataUri()]);if(!n||"--"===n||!o||"--"===o||!a)return void console.warn("[Poll] Incomplete data, skipping update");lastBlock=t,lastProxyIdx=e,updateProgress(t%BLOCK_INTERVAL),document.getElementById("title").textContent=n,document.getElementById("creator").textContent=o,document.getElementById("proxy").textContent=e+1+"/"+proxyCount,renderArtwork(a)}else lastBlock=t,updateProgress(t%BLOCK_INTERVAL)}}catch(t){console.error("[Poll] Poll failed, keeping previous state:",t)}}async function init(){[proxyAddress,rendererAddress]=await Promise.all([discoverProxy(),discoverRenderer()]),proxyCount=await getProxyCount(proxyAddress);const[t,e]=await Promise.all([getCurrentProxy(proxyAddress),getCurrentProxyIndex(proxyAddress)]);lastProxyIdx=e;const[r,n,o]=await Promise.all([getProxyTitle(t),getProxyCreator(t),getSvgDataUri()]),a=await getBlockNumber();lastBlock=a,document.getElementById("title").textContent=r,document.getElementById("creator").textContent=n,document.getElementById("proxy").textContent=e+1+"/"+proxyCount,renderArtwork(o),updateProgress(a%BLOCK_INTERVAL),document.getElementById("info").classList.add("loaded"),window.addEventListener("resize",syncInfoWidth),setInterval(pollBlock,3e3)}init().catch(t=>console.error("[Init] Fatal error:",t))</script></body></html>