-
AbstractThe gas fee is preventing new users step into the web3 world. Users must learn to get the native token(CKB or ETH) before playing a blockchain game or exchanging tokens with a DEX. The gasless feature can provide a way for developers to sponsor transaction fees for users to give them a smooth experience. There are several solutions built on Ethereum: GSN
ERC-4337
The ERC-4337 is bounded to account abstract, which means only smart wallets can adopt ERC-4337. Smart wallets with account abstracts can bring a different experience to the blockchain, but most people still use the key-based wallet. We have a gap between smart wallets and today's users. We want to combine the existing design philosophy to provide a gas-less experience for today's users. Our solution is based on ERC-4337, but we have a few key differences:
Although the design aims to offer a gas-less feature for today's "non-smart" wallet, the gas-less feature only needs changes in the application layer of the Godwoken node; The feature doesn't conflict with ERC-4337, GSN, or any other alternative solutions. The developers can deploy ERC-4337 or other implementations to Godwoken. Gas-lessThe basic approach to implementing the gas-less feature
EntryPointstruct UserOperation {
address callContract; # address of the target contract
bytes callData; # call data
uint256 callGasLimit; # gas used to execute the call
uint256 verificationGasLimit; # gas used to verification
uint256 maxFeePerGas; # gas price
uint256 maxPriorityFeePerGas; # must equals to maxFeePerGas, reserved for EIP-1559
bytes paymasterAndData; # pay master address and extra data
} APITODO Block producer changesThe block producer should be able to recognize gas-less transactions, then sort them in the mem-pool by its sponsored Godwoken node assumes a tx is a gas-less tx if it is satisfied:
For gas-less txs, the node pushes it into mem-pool and sorts it with sponsored ConclusionAccount abstraction has high uncertainty. We skip the account abstraction and focus on bringing gasless features to today's developers and users - borrowing the design philosophy from current proposals. We offer a solution that developers can integrate their contract without changes, and users can sign gasless tx with the wallet they already use. |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 2 replies
-
Could you please decribe |
Beta Was this translation helpful? Give feedback.
-
The detail of Main APIEntrypoint: /**
* Execute a UserOperation.
* @param op the operations to execute
*/
function handleOp(UserOperation calldata op) external;
/**
* Simulate a call to paymaster.validatePaymasterUserOp.
* Validation succeeds if the call doesn't revert.
* @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the wallet's data.
* In order to split the running opcodes of the wallet (validateUserOp) from the paymaster's validatePaymasterUserOp,
* it should look for the NUMBER opcode at depth=1 (which itself is a banned opcode)
* @param userOp the user operation to validate.
* @return preOpGas total gas used by validation (aka. gasUsedBeforeOperation)
* @return prefund the amount the paymaster had to prefund
* @return deadline until what time this userOp is valid (paymaster's deadline)
*/
function simulateValidation(UserOperation calldata userOp)
external returns (uint256 preOpGas, uint256 prefund, uint256 deadline); Full interface for Paymaster: /**
* payment validation: check if paymaster agree to pay.
* Must verify sender is the entryPoint.
* Revert to reject this request.
* Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted)
* The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.
* @param userOp the user operation
* @return context value to send to a postOp
* zero length to signify postOp is not required.
* @return deadline the last block timestamp this operation is valid, or zero if it is valid indefinitely.
* Note that the validation code cannot use block.timestamp (or block.number) directly.
*/
function validatePaymasterUserOp(UserOperation calldata userOp)
external returns (bytes memory context, uint256 deadline);
/**
* post-operation handler.
* Must verify sender is the entryPoint
* @param mode enum with the following options:
* opSucceeded - user operation succeeded.
* opReverted - user op reverted. still has to pay for gas.
* postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.
* Now this is the 2nd call, after user's op was deliberately reverted.
* @param context - the context value returned by validatePaymasterUserOp
* @param actualGasCost - actual gas used so far (without this postOp call).
*/
function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external;
/**
* add a deposit for this paymaster, used for paying for transaction fees
*/
function deposit() public payable;
/**
* withdraw value from the deposit
* @param withdrawAddress target to send to
* @param amount to withdraw
*/
function withdrawTo(address payable withdrawAddress, uint256 amount) public onlyOwner;
/**
* add stake for this paymaster.
* This method can also carry eth value to add to the current stake.
* @param extraUnstakeDelaySec - set the stake to the entrypoint's default unstakeDelay plus this value.
*/
function addStake(uint32 extraUnstakeDelaySec) external payable onlyOwner; Full interface for Contract WorkflowThe user signed a transaction to call Dapp Example: How to leverage gasless transactionLet's say we have the entrypoint contract at dapp frontend using ethers.js // define UserOp
const userOp: UserOperationStruct = {
callContract: realGameContract.address,
callData: realGameContractCallData,
callGasLimit: gasToExecuteRealGameContractCallData,
verificationGasLimit: gasToVerifyPaymaster,
maxFeePerGas: gasPrice,
maxPriorityFeePerGas: gasPrice,
paymasterAndData: "0x6b019795aa36dd19eb4a4d76f3b9a40239b7c19f"
}
// 1. construct and send gasless transaction
const abiCoder = new ethers.utils.AbiCoder();
const userOp = abiCoder.encode(["tuple(address callContract, bytes callData, uint256 callGasLimit, uint256 verificationGasLimit, uint256 maxFeePerGas, uint256 maxPriorityFeePerGas, bytes paymasterAndData) UserOperation"], [userOp]);
// first 4 bytes of keccak hash of handleOp((address,bytes,uint256,uint256,uint256,uint256,bytes))
const fnSelector = "fb4350d8";
// gasless payload = ENTRYPOINT_HANDLE_OP_SELECTOR + abiEncode(UserOperation)
const payload = "0x" + fnSelector + userOp.slice(2);
const gaslessTx = {
from: whitelistUser.address,
to: '0x9a11f47c0729fc56d9c44c059987d40703249569',
data: payload,
gasPrice: 0,
gasLimit: 1000000,
value: 0,
}
const signer = new ethers.Wallet("private key");
const tx = await signer.sendTransaction(gaslessTx);
await tx.wait();
// 2. or just use ethers contract factory
{
// Send tx with a valid user.
const EntryPoint = await ethers.getContractFactory("EntryPoint");
const entrypoint = await EntryPoint.attach('0x9a11f47c0729fc56d9c44c059987d40703249569');
const tx = await entryPoint.connect(whitelistUser).handleOp(userOp, {gasLimit: 100000, gasPrice: 0});
await tx.wait();
} |
Beta Was this translation helpful? Give feedback.
-
Support Gasless Transaction on Blockchain ExplorerIn order to display the actual gas price and gas cost for such gasless transactions, the blockchain explorer must parse it when collecting gasless transactions. here is how the explorer parses gasless transactions:
when a transaction meets those two requirements, it should be considered to be a gasless transaction.
// first 4 bytes of keccak hash of handleOp((address,bytes,uint256,uint256,uint256,uint256,bytes))
const fnSelector = "fb4350d8";
// gasless payload = fnSelector + abiEncode(UserOperation)
const payload = tx.data;
if(payload.slice(2,10) !== fnSelector){
throw new Error("invalid fn selector!")
}
const userOpData = "0x" + payload.slice(10);
// parse the UserOperation data
const abiCoder = new ethers.utils.AbiCoder();
const userOp = abiCoder.decode(["tuple(address callContract, bytes callData, uint256 callGasLimit, uint256 verificationGasLimit, uint256 maxFeePerGas, uint256 maxPriorityFeePerGas, bytes paymasterAndData) UserOperation"], userOpData);
const {
callContract,
callData,
callGasLimit,
verificationGasLimit,
maxFeePerGas,
maxPriorityFeePerGas,
paymasterAndData
} = userOp[0];
For better UX, we strongly recommend the explorer display the detailed UserOperation info for gasless transactions so that users can find out what the target contract is, which paymaster contract pays the fee for this transaction, etc. V1 Testnet Exampleexample gasless transaction: tx.data: 0xfb4350d800000000000000000000000000000000000000000000000000000000000000200000000000000000000000001005c8b8ee7a873576f5a6a9862c0c14909e01c100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000444dd3b30b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000168d8f646cfffa073c207eb8f83d62cb3d842ade4e123400000000000000000000 parse result: {
callContract: "0x1005C8b8ee7A873576F5A6A9862C0c14909e01c1",
callData: "0x4dd3b30b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001",
callGasLimit: "100000",
verificationGasLimit: "100000",
maxFeePerGas: "1",
maxPriorityFeePerGas: "1",
paymasterAndData: "0x8d8f646cfffa073c207eb8f83d62cb3d842ade4e1234",
} |
Beta Was this translation helpful? Give feedback.
-
we are migrating the contract repo to https://github.com/godwokenrises/evm-contract for a more clear structure. please take review the new repo. |
Beta Was this translation helpful? Give feedback.
-
Related docs
|
Beta Was this translation helpful? Give feedback.
-
We have a new article. This post is supposed to introduce our recent works about bringing a gasless-transaction feature on Godwoken. |
Beta Was this translation helpful? Give feedback.
Related docs
This feature offers our users a unique experience of using blockchain technology without any associated costs.