Created
December 18, 2024 10:31
-
-
Save uF4No/1c4e0c68e9490106815ec92c7524446a to your computer and use it in GitHub Desktop.
Script to send an EIP712 transaction via paymaster on ZKsync using Remix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as ethers from "ethers"; | |
import {Provider, Contract, utils, Signer, BrowserProvider, Wallet} from "zksync-ethers"; | |
// Address of the ZeekMessages contract | |
const GREETER_CONTRACT_ADDRESS = "0x2f5Fa95a28EEd40DD80ED3fFC718094EB41253b4"; | |
// Address of the ERC20 token contract | |
const TOKEN_CONTRACT_ADDRESS = "0xF4dF2c515581A9fA5bAa078d04703c0f3Fd9115a"; | |
// Message to be sent to the contract | |
const NEW_MESSAGE = "This tx cost me no ETH!"; | |
const GREETER_ABI = [ | |
{ | |
"inputs": [], | |
"name": "greet", | |
"outputs": [{ "internalType": "string", "name": "", "type": "string" }], | |
"stateMutability": "view", | |
"type": "function" | |
}, | |
{ | |
"inputs": [{ "internalType": "string", "name": "_greeting", "type": "string" }], | |
"name": "setGreeting", | |
"outputs": [], | |
"stateMutability": "nonpayable", | |
"type": "function" | |
} | |
]; | |
(async () => { | |
try { | |
console.log('Sending a transaction via the testnet paymaster') | |
const browserProvider = new ethers.BrowserProvider(web3Provider) | |
const signer = await browserProvider.getSigner() | |
console.log("Signer:", await signer.getAddress()); | |
const zkProvider = new Provider("https://sepolia.era.zksync.dev"); | |
const zkBrowserProvider = new BrowserProvider(web3Provider); | |
const chainId = Number((await browserProvider.getNetwork()).chainId) | |
console.log("chain id >> ", chainId) | |
const zkSigner = Signer.from(await zkBrowserProvider.getSigner(), chainId, zkProvider); | |
// const zkSigner = Signer.from(signer, , zkProvider); | |
console.log(`ZK Signer ${await zkSigner.getAddress()}`) | |
const testnetPaymasterAddress = await zkProvider.getTestnetPaymasterAddress() | |
console.log(`Testnet paymaster address is ${testnetPaymasterAddress}`); | |
const gasPrice = await zkProvider.getGasPrice(); | |
console.log("gasPrice is >> ", gasPrice) | |
// initialise messages and token contracts with address, abi and signer | |
const messagesContract= new Contract(GREETER_CONTRACT_ADDRESS, GREETER_ABI, zkSigner); | |
// define paymaster parameters for gas estimation | |
const paramsForFeeEstimation = utils.getPaymasterParams(testnetPaymasterAddress, { | |
type: "ApprovalBased", | |
token: TOKEN_CONTRACT_ADDRESS, | |
// set minimalAllowance to 1 for estimation | |
minimalAllowance: 1n, | |
// empty bytes as testnet paymaster does not use innerInput | |
innerInput: new Uint8Array(0), | |
}); | |
console.log(paramsForFeeEstimation) | |
// estimate gasLimit via paymaster | |
const gasLimit = await messagesContract.setGreeting.estimateGas(NEW_MESSAGE, { | |
customData: { | |
gasPerPubdata: utils.DEFAULT_GAS_PER_PUBDATA_LIMIT, | |
paymasterParams: paramsForFeeEstimation, | |
}, | |
}); | |
console.log("gasLimit is >> ", gasLimit) | |
// fee calculated in ETH will be the same in | |
// ERC20 token using the testnet paymaster | |
const fee = gasPrice * gasLimit; | |
console.log("Fee is >>", fee); | |
// new paymaster params with fee as minimalAllowance | |
const paymasterParams = utils.getPaymasterParams(testnetPaymasterAddress, { | |
type: "ApprovalBased", | |
token: TOKEN_CONTRACT_ADDRESS, | |
// provide estimated fee as allowance | |
minimalAllowance: fee, | |
// minimalAllowance: 1n, | |
// empty bytes as testnet paymaster does not use innerInput | |
innerInput: new Uint8Array(0), | |
}); | |
// full overrides object including maxFeePerGas and maxPriorityFeePerGas | |
const txOverrides = { | |
maxFeePerGas: gasPrice, | |
maxPriorityFeePerGas: "1", | |
// hardcoded | |
// gasLimit: 600000, | |
gasLimit, | |
customData: { | |
gasPerPubdata: utils.DEFAULT_GAS_PER_PUBDATA_LIMIT, | |
paymasterParams, | |
} | |
} | |
console.log(`Sending tx via your wallet`); | |
// send transaction with additional paymaster params as overrides | |
const txHandle = await messagesContract.setGreeting(NEW_MESSAGE, txOverrides); | |
await txHandle.wait(); | |
console.log(`Transaction processed`) | |
console.log(`Done!`); | |
} catch (e) { | |
console.error('Error in script!') | |
console.error(e.message) | |
console.error(e) | |
} | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment