You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am unable to find any documentation for this use case where i sucessfully created a smart session, and now want to use an ERC20 paymaster service for the session.
My use case is that my DAPP only uses USDT and has no concept of depositing ETH as gas fee, hence i want to use a paymaster to participate in the DAPP games. It is a game based DAPP that uses smart sessions to avoid too many signature signing that will distract the user from the game, and yes i want all these tx to be done using gas paymasters using ERC20 tokens.
An example can be the user clicks a button to enter a battle and the cost to enter battle is 50 USDT, if the user has lets say 100 USDT. 50 will be charged by the game and assuming a fee is 1 USDT for paymaster 1 will be charged by paymaster, In the end the user simply pays 51 USDT and does not have to have any ETH native currency.
Putting down a code snippet that i need help with primarily i am using Biconomy Paymaster V2 and Bundler V3 and latest @biconomy/abstractjs and viem versions.
`
const userGrantPermission = async () => {
const USDT_ADDRESS = '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9'
const clientSigner = createWalletClient({
chain,
account: account, // using metamask signer
transport: custom(global?.window?.ethereum ?? "")
})
const nexusAccount = await toNexusAccount({
signer: clientSigner,
transport: http(ARBITRUM_RPC),
chain: ARBITRUM_CHAIN
})
const nexusClient = createBicoBundlerClient({
chain: ARBITRUM_CHAIN,
account: nexusAccount,
transport: http(
BUNDLER_URL
),
paymasterContext: toBiconomyTokenPaymasterContext({ feeTokenAddress: USDT_ADDRESS, calculateGasLimits: true }),
paymaster: createBicoPaymasterClient({
paymasterUrl: PAYMASTER_URL,
chainId: 42161
})
})
const nexusAddress = await nexusClient?.account?.getAddress()
if (!nexusClient || !nexusAddress) return
const redeemerAccount = privateKeyToAccount(PRIVATE_KEY_GENERATED) // used hardcoded for POC later will be dynamic
try {
// Create sessions module
const sessionsModule = toSmartSessionsModule({
signer: clientSigner,
})
const isModuleInstalled = await nexusClient.isModuleInstalled({
module: sessionsModule
})
if (!isModuleInstalled) {
// Install module if not already installed
const hash = await nexusClient.installModule({
module: sessionsModule
})
const receipt = await nexusClient.waitForUserOperationReceipt({
hash
})
if (receipt.success.toString() !== "true") {
throw new Error(
Failed to install module
)
}
}
// Create session client
const nexusSessionClient = nexusClient.extend(
smartSessionActions()
)
const transferSelector = slice(
toFunctionSelector('transfer(address,uint256)'),
0,
4
)
const approveSelector = slice(
toFunctionSelector("approve(address,uint256)"),
0,
4
)
const storedSession = localStorage.getItem('nexusSession')
const userPermissionSession = JSON.parse(storedSession, (_, value) => {
if (typeof value === 'string' && /^\d+n$/.test(value)) {
return toBigInt(value.slice(0, -1)); // remove trailing 'n'
}
return value;
});
let createSessionsResponse = userPermissionSession;
if (!userPermissionSession) {
createSessionsResponse = await nexusSessionClient.grantPermission({
redeemer: redeemerAccount.address,
permitERC4337Paymaster: true,
actions: [
{
actionTarget: USDT_ADDRESS, // Target contract address
actionTargetSelector: transferSelector, // Function selector (e.g., increment())
actionPolicies: [getSudoPolicy()] // getSpendingLimitsPolicy, getUsageLimitPolicy, getValueLimitPolicy
},
{
actionTarget: USDT_ADDRESS, // Target contract address
actionTargetSelector: approveSelector, // Function selector (e.g., increment())
actionPolicies: [getSudoPolicy()] // getSpendingLimitsPolicy, getUsageLimitPolicy, getValueLimitPolicy
}
],
})
const serialized = JSON.stringify(createSessionsResponse, (_, value) =>
typeof value === 'bigint' ? ${value}n : value // add 'n' to mark BigInt
);
localStorage.setItem('nexusSession', serialized);
}
// Create a Nexus account pointing to the original account address
const emulatedAccount = await toNexusAccount({
accountAddress: nexusAccount.address, // The address that granted the permission
signer: redeemerAccount,
chain,
transport: viemHttp(ARBITRUM_RPC),
});
// Create a client for the emulated account
const emulatedClient = createBicoBundlerClient({
chain,
account: emulatedAccount,
transport: viemHttp(
BUNDLER_URL
),
paymasterContext: toBiconomyTokenPaymasterContext({ feeTokenAddress: USDT_ADDRESS, calculateGasLimits: true }),
paymaster: createBicoPaymasterClient({
paymasterUrl: PAYMASTER_URL,
chainId: 42161,
})
});
const smartSessionsClient = emulatedClient.extend(smartSessionActions());
// Use the permission with the sessionDetails received during grant
const userOpHash = await smartSessionsClient.usePermission({
sessionDetails: createSessionsResponse,
// The session details object returned from grantPermission
calls: [
{
to: USDT_ADDRESS, // The target contract address
data: encodeFunctionData({
abi: ABI,
functionName: "transfer",
args: [TEST_WALLET_ADDRESS, AMOUNT]
}),
value: 0,
},
],
mode: userPermissionSession ? "USE" : "ENABLE_AND_USE", // Use "ENABLE_AND_USE" for the first usage, "USE" for subsequent uses
});
// Wait for the transaction to be processed
const receipt = await emulatedClient.waitForUserOperationReceipt({
hash: userOpHash
});
// Check if the transaction was successful
if (!receipt.success) {
throw new Error("Smart sessions module validation failed");
}
console.log("Permission used successfully:", receipt);
} catch (error) {
console.log('error: ', error)
}
}
`
If i comment paymasterContext and paymaster from createBicoBundlerClient params in both "emulatedClient" and "nexusClient" my code works fully i just face issues with the paymaster and please also suggest that am i missing any approvals if any or any preOpHashes needed, i cannot use the Mee client as i want to use sessions.
The error i get is revert AA23 when i enable the paymaster
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I am unable to find any documentation for this use case where i sucessfully created a smart session, and now want to use an ERC20 paymaster service for the session.
My use case is that my DAPP only uses USDT and has no concept of depositing ETH as gas fee, hence i want to use a paymaster to participate in the DAPP games. It is a game based DAPP that uses smart sessions to avoid too many signature signing that will distract the user from the game, and yes i want all these tx to be done using gas paymasters using ERC20 tokens.
An example can be the user clicks a button to enter a battle and the cost to enter battle is 50 USDT, if the user has lets say 100 USDT. 50 will be charged by the game and assuming a fee is 1 USDT for paymaster 1 will be charged by paymaster, In the end the user simply pays 51 USDT and does not have to have any ETH native currency.
Putting down a code snippet that i need help with primarily i am using Biconomy Paymaster V2 and Bundler V3 and latest @biconomy/abstractjs and viem versions.
`
`
If i comment paymasterContext and paymaster from createBicoBundlerClient params in both "emulatedClient" and "nexusClient" my code works fully i just face issues with the paymaster and please also suggest that am i missing any approvals if any or any preOpHashes needed, i cannot use the Mee client as i want to use sessions.
The error i get is revert AA23 when i enable the paymaster
Beta Was this translation helpful? Give feedback.
All reactions