Beta toolkit is under development. Use only on testnet until V1 is released.
AutoGas Delegation Toolkit
This toolkit provides a framework for developers to build applications that interact with the AutoGas contract, enabling NFT owners to delegate their AutoGas NFTs to abstracted accounts and automatically receive ETH rewards. The design ensures security, restricts delegation to AutoGas NFTs only, and allows users to withdraw funds securely.Repository Structure
widgets/: JavaScript widget for wallet connection and NFT delegation.
package.json: Manages dependencies and scripts.
Below is the complete AutoGas NFT Rewards Delegation Toolkit, including all code and documentation. The toolkit is designed to integrate with the AutoGas NFT contract at the hardcoded address 0xcc03a46173ee0e73cf464910f9eff372ca204821, which is the only method for connecting delegation. This ensures security and compatibility with the official AutoGas contract.
Contracts
IDelegate.sol
This interface defines the functions that the AutoGas contract calls on delegated accounts.solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IDelegate {
function onDelegated(uint256 tokenId, address owner) external;
function onRevoked(uint256 tokenId) external;
function receiveReward(uint256 tokenId, uint256 amount) external payable;
}
AutoGasToolkit.sol
This contract manages the creation of abstracted accounts and NFT delegation, with the AutoGas contract address hardcoded.solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./IDelegate.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
interface Autogas {
function delegateToken(uint256 tokenId, address delegate) external;
function revokeDelegation(uint256 tokenId) external;
function tokenDelegations(uint256 tokenId) external view returns (address);
}
contract AutoGasToolkit is Ownable {
Autogas public autogas; // Reference to the deployed AutoGas contract
IEntryPoint public entryPoint; // Reference to the ERC-4337 EntryPoint
// Mapping from abstracted account address to its owner
mapping(address => address) public abstractedAccountOwners;
event AbstractedAccountCreated(address indexed owner, address indexed abstractedAccount);
constructor(address _entryPoint) Ownable(msg.sender) {
autogas = Autogas(0xcc03a46173ee0e73cf464910f9eff372ca204821); // Hardcoded AutoGas contract address
entryPoint = IEntryPoint(_entryPoint);
}
function createAbstractedAccount() external {
AbstractedAccount newAccount = new AbstractedAccount(address(this), msg.sender, address(entryPoint));
abstractedAccountOwners[address(newAccount)] = msg.sender;
emit AbstractedAccountCreated(msg.sender, address(newAccount));
}
function delegateToAbstractedAccount(uint256 tokenId, address abstractedAccount) external {
require(abstractedAccountOwners[abstractedAccount] == msg.sender, "Not owner of abstracted account");
autogas.delegateToken(tokenId, abstractedAccount);
}
function revokeDelegationFromAbstractedAccount(uint256 tokenId, address abstractedAccount) external {
require(abstractedAccountOwners[abstractedAccount] == msg.sender, "Not owner of abstracted account");
autogas.revokeDelegation(tokenId);
}
}
AbstractedAccount.sol
This contract handles delegated NFTs, receives ETH rewards, and supports ERC-4337 account abstraction.solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./IDelegate.sol";
import "./AutoGasToolkit.sol";
import "@account-abstraction/contracts/interfaces/IAccount.sol";
import "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract AbstractedAccount is IDelegate, IAccount, ReentrancyGuard {
AutoGasToolkit public toolkit;
address public owner;
IEntryPoint public entryPoint;
mapping(uint256 => uint256) public tokenRewards; // Tracks rewards per tokenId
constructor(address _toolkit, address _owner, address _entryPoint) {
toolkit = AutoGasToolkit(_toolkit);
owner = _owner;
entryPoint = IEntryPoint(_entryPoint);
}
function onDelegated(uint256 tokenId, address delegator) external override {
require(msg.sender == address(toolkit.autogas()), "Only AutoGas can call");
require(delegator == owner, "Delegator must be owner");
tokenRewards[tokenId] = 0; // Initialize reward tracking
}
function onRevoked(uint256 tokenId) external override {
require(msg.sender == address(toolkit.autogas()), "Only AutoGas can call");
delete tokenRewards[tokenId]; // Clean up reward tracking
}
function receiveReward(uint256 tokenId, uint256 amount) external payable override {
require(msg.sender == address(toolkit.autogas()), "Only AutoGas can call");
require(msg.value == amount, "Incorrect ETH amount");
tokenRewards[tokenId] += amount; // Accumulate rewards
}
function withdrawRewards(uint256 tokenId) external nonReentrant {
require(msg.sender == owner, "Only owner can withdraw");
uint256 amount = tokenRewards[tokenId];
require(amount > 0, "No rewards to withdraw");
tokenRewards[tokenId] = 0;
(bool success, ) = payable(owner).call{value: amount}("");
require(success, "ETH transfer failed");
}
// ERC-4337 functions
function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)
external
override
returns (uint256 validationData)
{
require(msg.sender == address(entryPoint), "Only EntryPoint can call");
// Simplified validation: check if the operation is from the owner
if (userOp.sender == address(this) && tx.origin == owner) {
return 0; // Valid operation
}
return 1; // Invalid operation
}
function executeUserOp(UserOperation calldata userOp, bytes32 userOpHash)
external
override
{
require(msg.sender == address(entryPoint), "Only EntryPoint can call");
(bool success, ) = address(this).call(userOp.callData);
require(success, "Execution failed");
}
receive() external payable {}
}
AutoConnect.js
This JavaScript widget simplifies wallet connection, abstracted account creation, and NFT delegation.javascript
# AutoGas NFT Rewards Delegation Toolkit
## Overview
This toolkit enables third-party applications to integrate with the deployed `AutoGas` contract at `0xcc03a46173ee0e73cf464910f9eff372ca204821`. It allows NFT owners to delegate their AutoGas NFTs to abstracted accounts, which automatically receive ETH rewards. The toolkit supports ERC-4337 for advanced account abstraction features.
## Prerequisites
- **Node.js**: v16 or higher
- **Hardhat**: For compiling and testing contracts
- **Ethereum Wallet**: e.g., MetaMask for deployment and interaction
## Installation
1. Clone the repository:
```bash
git clone https://github.com/lightspeedfoundation/autogas-delegation-toolkit.git
cd autogas-delegation-toolkit
Install dependencies:
npm install
Contracts
IDelegate.sol
Interface for abstracted accounts to handle delegation and rewards.
onDelegated: Called when an NFT is delegated.
onRevoked: Called when delegation is revoked.
receiveReward: Receives ETH rewards from AutoGas.
AutoGasToolkit.sol
Manages abstracted account creation and NFT delegation, hardcoded to the official AutoGas contract.
createAbstractedAccount: Deploys a new abstracted account for the caller.
delegateToAbstractedAccount: Delegates an NFT to the specified abstracted account.
revokeDelegationFromAbstractedAccount: Revokes delegation of an NFT.
AbstractedAccount.sol
Handles delegated NFTs and ETH rewards, with ERC-4337 support.
receiveReward: Accumulates ETH rewards from AutoGas.
withdrawRewards: Allows the owner to withdraw accumulated rewards.
validateUserOp & executeUserOp: ERC-4337 functions for account abstraction.
Integration Guide for Developers
Deploy AutoGasToolkit:
Deploy with the ERC-4337 EntryPoint address as a constructor argument.
Create Abstracted Accounts:
Users call createAbstractedAccount to deploy their own abstracted account.
Delegate NFTs:
Users delegate NFTs to their abstracted account using delegateToAbstractedAccount.
Receive and Withdraw Rewards:
ETH rewards are automatically sent to the abstracted account by AutoGas.
Users withdraw rewards using withdrawRewards from their abstracted account.
How It Works
Delegation:
Users create an abstracted account and delegate their AutoGas NFT to it.
Delegation is restricted to the official AutoGas contract at 0xcc03a46173ee0e73cf464910f9eff372ca204821.
Reward Distribution:
The AutoGas contract sends ETH rewards to the abstracted account via receiveReward.
Rewards are tracked per token ID in the tokenRewards mapping.
Withdrawal:
Users call withdrawRewards on their abstracted account to transfer ETH to their wallet.
ERC-4337 Support:
Abstracted accounts support gasless transactions and other features via the EntryPoint.
Security Considerations
Hardcoded AutoGas Address: Ensures only the official AutoGas contract at 0xcc03a46173ee0e73cf464910f9eff372ca204821 is used for delegation.
Reentrancy Protection: withdrawRewards uses ReentrancyGuard to prevent reentrancy attacks.
Access Control: Only the owner can withdraw rewards; only AutoGas can call delegation/reward functions.
ERC-4337 Security: validateUserOp and executeUserOp are restricted to the EntryPoint.