// FETCH LIDO ABI const _l2Receiver = "0xF518Fa3344Ba498f1b9DEcBE1B9c7f0e1960ea29"; const _l1Token = "0xd35CCeEAD182dcee0F148EbaC9447DA2c4D449c4"; const _amount = 100000; const _l2TxGasLimi = 734935; const _l2TxGasPerPubdataByte = 800; const usdc = "0xd35CCeEAD182dcee0F148EbaC9447DA2c4D449c4"; const zkContract = "0x57891966931Eb4Bb6FB81430E6cE0A03AAbDe063"; const tokenDecimals = 18; const zkAbi = '[{"inputs":[{"internalType":"address","name":"_logic","type":"address"},{"internalType":"address","name":"admin_","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"admin_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"implementation_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]'; if (!zkAbi.ok) { return "Loading"; } const iface = new ethers.utils.Interface(zkAbi.body); const getUSDCBalance = (receiver) => { const encodedData = iface.encodeFunctionData("balanceOf", [receiver]); return Ethers.provider() .call({ to: usdc, data: encodedData, }) .then((rawBalance) => { const receiverBalanceHex = iface.decodeFunctionResult( "balanceOf", rawBalance ); return Big(receiverBalanceHex.toString()) .div(Big(10).pow(tokenDecimals)) .toFixed(2) .replace(/\d(?=(\d{3})+\.)/g, "$&,"); }); }; const submitEthers = (strEther, _referral) => { if (!strEther) { return console.log("Amount is missing"); } const erc20 = new ethers.Contract( zkContract, zkAbi.body, Ethers.provider().getSigner() ); let amount = ethers.utils.parseUnits(strEther, tokenDecimals).toHexString(); erc20 .deposit( _l2Receiver, _l1Token, _amount, _l2TxGasLimi, _l2TxGasPerPubdataByte, { value: amount } ) .then((transactionHash) => { console.log("transactionHash is " + transactionHash); }); }; // DETECT SENDER if (state.sender === undefined) { const accounts = Ethers.send("eth_requestAccounts", []); if (accounts.length) { State.update({ sender: accounts[0] }); console.log("set sender", accounts[0]); } } //if (!state.sender) return "Please login first"; // FETCH SENDER BALANCE if (state.balance === undefined && state.sender) { Ethers.provider() .getBalance(state.sender) .then((balance) => { State.update({ balance: Big(balance).div(Big(10).pow(18)).toFixed(2) }); }); } // FETCH SENDER STETH BALANCE if (state.usdcBalance === undefined && state.sender) { getUSDCBalance(state.sender).then((usdcBalance) => { State.update({ usdcBalance }); }); } // FETCH TX COST if (state.txCost === undefined) { const gasEstimate = ethers.BigNumber.from(1875000); const gasPrice = ethers.BigNumber.from(1500000000); const gasCostInWei = gasEstimate.mul(gasPrice); const gasCostInEth = ethers.utils.formatEther(gasCostInWei); let responseGql = fetch( "https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query: `{ bundle(id: "1" ) { ethPrice } }`, }), } ); if (!responseGql) return ""; const ethPriceInUsd = responseGql.body.data.bundle.ethPrice; const txCost = Number(gasCostInEth) * Number(ethPriceInUsd); State.update({ txCost: `$${txCost.toFixed(2)}` }); } // FETCH CSS const cssFont = fetch( "https://fonts.googleapis.com/css2?family=Manrope:wght@200;300;400;500;600;700;800" ).body; const css = fetch( "https://pluminite.mypinata.cloud/ipfs/Qmboz8aoSvVXLeP5pZbRtNKtDD3kX5D9DEnfMn2ZGSJWtP" ).body; if (!cssFont || !css) return ""; if (!state.theme) { State.update({ theme: styled.div` font-family: Manrope, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; ${cssFont} ${css} `, }); } const Theme = state.theme; // OUTPUT UI const getSender = () => { return !state.sender ? "" : state.sender.substring(0, 6) + "..." + state.sender.substring(state.sender.length - 4, state.sender.length); }; return ( <Theme> <div class="LidoContainer"> <div class="Header">zkSync Bridge</div> <div class="SubHeader">Transfer to zkSync</div> <div class="LidoForm"> {state.sender && ( <> <div class="LidoFormTopContainer"> <div class="LidoFormTopContainerLeft"> <div class="LidoFormTopContainerLeftContent1"> <div class="LidoFormTopContainerLeftContent1Container"> <span>Available to send</span> <div class="LidoFormTopContainerLeftContent1Circle" /> </div> </div> <div class="LidoFormTopContainerLeftContent2"> <span> {state.balance ?? (!state.sender ? "0" : "...")} ETH </span> </div> </div> <div class="LidoFormTopContainerRight"> <div class="LidoFormTopContainerRightContent1"> <div class="LidoFormTopContainerRightContent1Text"> <span>{getSender()}</span> </div> </div> </div> </div> <div class="LidoSplitter" /> </> )} <div class={ state.sender ? "LidoFormBottomContainer" : "LidoFormTopContainer" } > <div class="LidoFormTopContainerLeft"> <div class="LidoFormTopContainerLeftContent1"> <div class="LidoFormTopContainerLeftContent1Container"> <span>Staked amount</span> </div> </div> <div class="LidoFormTopContainerLeftContent2"> <span> {state.stakedBalance ?? (!state.sender ? "0" : "...")} stETH </span> </div> </div> <div class="LidoFormTopContainerRight"> <div class="LidoAprContainer"> <div class="LidoAprTitle">Lido APR</div> </div> </div> </div> </div> <div class="LidoStakeForm"> <div class="LidoStakeFormInputContainer"> <span class="LidoStakeFormInputContainerSpan1"> <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path opacity="0.6" d="M11.999 3.75v6.098l5.248 2.303-5.248-8.401z" ></path> <path d="M11.999 3.75L6.75 12.151l5.249-2.303V3.75z"></path> <path opacity="0.6" d="M11.999 16.103v4.143l5.251-7.135L12 16.103z" ></path> <path d="M11.999 20.246v-4.144L6.75 13.111l5.249 7.135z"></path> <path opacity="0.2" d="M11.999 15.144l5.248-2.993-5.248-2.301v5.294z" ></path> <path opacity="0.6" d="M6.75 12.151l5.249 2.993V9.85l-5.249 2.3z" ></path> </svg> </span> <span class="LidoStakeFormInputContainerSpan2"> <input disabled={!state.sender} class="LidoStakeFormInputContainerSpan2Input" value={state.strEther} onChange={(e) => State.update({ strEther: e.target.value })} placeholder="Amount" /> </span> <span class="LidoStakeFormInputContainerSpan3" onClick={() => { State.update({ strEther: (parseFloat(state.balance) - 0.05).toFixed(2), }); }} > <button class="LidoStakeFormInputContainerSpan3Content" disabled={!state.sender} > <span class="LidoStakeFormInputContainerSpan3Max">MAX</span> </button> </span> </div> {!!state.sender ? ( <button class="LidoStakeFormSubmitContainer" onClick={() => submitEthers(state.strEther, state.sender)} > <span>Deposit</span> </button> ) : ( <Web3Connect className="LidoStakeFormSubmitContainer" connectLabel="Connect with Web3" /> )} <div class="LidoFooterContainer"> {state.sender && ( <div class="LidoFooterRaw"> <div class="LidoFooterRawLeft">You will receive</div> <div class="LidoFooterRawRight">${state.strEther ?? 0} stETH</div> </div> )} <div class="LidoFooterRaw"> <div class="LidoFooterRawLeft">Exchange rate</div> <div class="LidoFooterRawRight">1 ETH = 1 stETH</div> </div> <div class="LidoFooterRaw"> <div class="LidoFooterRawLeft">Transaction cost</div> <div class="LidoFooterRawRight">{state.txCost}</div> </div> <div class="LidoFooterRaw"> <div class="LidoFooterRawLeft">Reward fee</div> <div class="LidoFooterRawRight">10%</div> </div> </div> </div> </div> </Theme> );