2. Build a Paymaster
Step 2 in the "Smart Accounts From Scratch" Series: Let's build and deploy a Paymaster!
Want a Video Walkthrough?
Check out this YouTube video of an implementation of this step!
One super nice feature of ERC 4337 Account Abstraction is the ability to have someone else pay for the gas on behalf of the smart account. In this way, the payment for gas can be sponsored or have flexibility in how that payment is done. Let's learn a bit about how the Paymaster works by deploying our own!
Create and Deploy Paymaster Contract
In this step, we'll need to implement the Paymaster interface found here: https://github.com/eth-infinitism/account-abstraction/blob/ver0.6.0/contracts/interfaces/IPaymaster.sol
Let's go ahead and create a very generous paymaster:
import "@account-abstraction/contracts/interfaces/IPaymaster.sol";
contract Paymaster is IPaymaster {
function validatePaymasterUserOp(UserOperation calldata, bytes32, uint256)
external
pure
override
returns (bytes memory context, uint256 validationData)
{
context = new bytes(0);
validationData = 0;
}
function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external override {}
}
This paymaster considers every user op valid, so it will pay for anything! Thanks paymaster. You can see this in the validatePaymasterUserOp
, which is called by the EntryPoint for every user op it receives. We also implemented a postOp
but left the function body blank here.
In the validatePaymasterUserOp
you'll notice here that we have a couple values we can return here:
- context - additional context which is supplied to the postOp
- validationData - a packed set of three variables which is parsed by the entry point here - it checks to see that the first packed value, the
sigAuthorizer
, is set to0
and that theblock.timestamp
falls between the other two values:validAfter
andvalidUntil
(zero is a special value indicating a valid signature with no expiration)
Once you have your Paymaster ready, go ahead and deploy it to your local blockchain along with the AccountFactory and EntryPoint from step 1.
✅ Task 1/4: Did you deploy the Paymaster to your local blockchain?
Update the PaymasterAndData field
In the last step we left the paymasterAndData
field in the user operation as "0x"
indicating we were not using a paymaster, and that the smart account is responsible for gas payments. Now that we've deployed our generous paymaster, it's time to use it!
Similar to the initCode
field from step 1, the first 20 bytes of the paymasterAndData
will be the address of our paymaster. You can see that being parsed by the EntryPoint here: https://github.com/eth-infinitism/account-abstraction/blob/ver0.6.0/contracts/core/EntryPoint.sol#L282-L288
The rest of the data can be parsed by the Paymaster, if it should need it. You'll notice that, in our Paymaster we built above, the first argument to the validate function is a UserOperation
. This will be the entire user operation, with the paymasterAndData
field included. Its up to the paymaster to parse out the data if its necessary here. In our case, we can forgo the data
portion and just leave the paymasterAndData
to be the address of the Paymaster you just deployed.
✅ Task 2/4: Does your paymasterAndData
field start with the paymaster address?
Pre-Fund the Paymaster
In Step 1 we pre-funded the smart account on the EntryPoint. Now, the paymaster is footing the gas bill so we'll need to deposit for them. So now you'll want to deposit some funds for the paymaster to sponsor user operation gas: entryPoint.depositTo(paymasterAddr, { value: 1 ether })
The EntryPoint
contract inherits from StakeManager
which contains the methods for managing the deposits, you can see that here: https://github.com/eth-infinitism/account-abstraction/blob/ver0.6.0/contracts/core/StakeManager.sol
✅ Task 3/4: Was the deposit on behalf of the paymaster successful? You can check with balanceOf
method.
Execute the User Operation!
Once again, test it all out by executing the user operation! This time the gas should be covered by the paymaster.
✅ Task 4/4: Was your state change initiated through the user operation and was the gas paid for by the paymaster? Was this possible with 0 ether inside of your smart account contract?
If you're able to make a state change on your smart account, just like you did in step 1, you're doing splendid! You've upgraded your smart account to be a gasless smart account 🎉
Next, let's add some validation to ensure our user operations can only be executed by the account owner!
Updated 10 months ago