Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
max committed Nov 8, 2023
0 parents commit 1f6b496
Show file tree
Hide file tree
Showing 17 changed files with 9,912 additions and 0 deletions.
144 changes: 144 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# Logs
**/artifacts/
.idea
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

node_modules
.env
coverage
coverage.json
typechain
typechain-types

# Hardhat files
cache
artifacts

61 changes: 61 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# TokenPocket AA Core
## Overview

account abstraction core, include account, factory, paymaster..e.g.

ERC20 Paymaster is an ERC-4337 Paymaster contract by TokenPocket which is able to sponsor gas fees in exchange for ERC20 tokens. The contract uses an Oracle to fetch the latest token prices, power by ChainLink.

## Development setup

This repository uses hardhat for development, and assumes you have already installed hardhat.

### hardhat

[Hardhat](https://hardhat.org/) is used for gas metering and developing sdk.

1. install dependencies

```
npm install
```

2. compile contracts

```
npx hardhat compile
```

3. deploy

```
npx hardhat run ./scripts/deploy.ts
```

optional: run test or run coverage

```
npx hardhat test
npx hardhat coverage
```

## Deployed Contracts

### Polygon Mainnet

- [AADeployer](https://polygonscan.com/address/0x5b9f54243A0efF729C5045f47b2da5Ed4800C571)

tools for deploying the same contract address

- [Account abstraction Implementation](https://polygonscan.com/address/0xC9B6dFDC54Dd45958956fc65143a7B107CbC79Fe)


- [TokenPocket AA Factory](https://polygonscan.com/address/0x04DD294F3B3BB0137754cdfAb86761c2d87F54Ef)


- [TokenOraclePaymaster](https://polygonscan.com/address/0x49321c737A1Cf0c7a8b908ecB64812E98f9E2E63)

uses an Oracle to fetch the latest token prices, power by [ChainLink Price Feed](https://polygonscan.com/address/0xAB594600376Ec9fD91F8e885dADF0CE036862dE0)

- [TokenPocketPaymaster](https://polygonscan.com/address/0xab3a6a007da66f255a9ee75bf1070590c2f20a20)

any ERC20 token can be used to pay for gas
66 changes: 66 additions & 0 deletions contracts/core/AADeployer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.18;

import "./account/TokenPocketAAFactory.sol";
import "./account/TokenPocketAccount.sol";
import "@openzeppelin/contracts/utils/Create2.sol";
import "@account-abstraction/contracts/interfaces/IEntryPoint.sol";

interface IOwnable {
function transferOwnership(address newOwner) external;
}

contract AADeployer {

event Deployed(address deployedAddress, address owner, uint256 salt);

constructor(){}

function deployImplementation(IEntryPoint entryPoint, uint256 salt) external {
address addr = getDeployImplementationAddress(msg.sender, entryPoint, salt);
uint codeSize = addr.code.length;
if (codeSize > 0) {
revert("salt deployed");
}
bytes32 deploySalt = keccak256(abi.encodePacked(msg.sender, salt));
address ret = payable(new TokenPocketAccount{salt : deploySalt}(
entryPoint
));
require(addr == ret);
emit Deployed(ret, msg.sender, salt);
}

function deployFactory(address accountImplementation, address executor, uint256 salt) external {
address addr = getDeployFactoryAddress(msg.sender, accountImplementation, salt);
uint codeSize = addr.code.length;
if (codeSize > 0) {
revert("salt deployed");
}
bytes32 deploySalt = keccak256(abi.encodePacked(msg.sender, salt));
address ret = address(new TokenPocketAAFactory{salt : deploySalt}(
accountImplementation
));
require(addr == ret);
//transfer owner
IOwnable(ret).transferOwnership(executor);
emit Deployed(ret, executor, salt);
}

function getDeployImplementationAddress(address deployer, IEntryPoint entryPoint, uint256 salt) public view returns (address ret) {
bytes32 deploySalt = keccak256(abi.encodePacked(deployer, salt));
return Create2.computeAddress(deploySalt, keccak256(abi.encodePacked(
type(TokenPocketAccount).creationCode,
abi.encode(
address(entryPoint)
)
)));
}

function getDeployFactoryAddress(address deployer, address accountImplementation, uint256 salt) public view returns (address ret) {
bytes32 deploySalt = keccak256(abi.encodePacked(deployer, salt));
return Create2.computeAddress(deploySalt, keccak256(abi.encodePacked(
type(TokenPocketAAFactory).creationCode,
abi.encode(accountImplementation)
)));
}
}
66 changes: 66 additions & 0 deletions contracts/core/account/TokenPocketAAFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.18;

import "@openzeppelin/contracts/utils/Create2.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import { IEntryPoint } from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
import "./TokenPocketAAProxy.sol";

contract TokenPocketAAFactory is Ownable {

address public accountImplementation;

event Upgraded(address indexed implementation, address indexed newImplementation);
event CreateAccount(address indexed account, address indexed owner, address implementation, uint256 salt);

constructor(address _accountImplementation) Ownable() {
accountImplementation = _accountImplementation;
}

function upgradeImplementation(address newImplementation) external onlyOwner {
emit Upgraded(accountImplementation, newImplementation);
accountImplementation = newImplementation;
}

function addStake(IEntryPoint entryPoint, uint32 unstakeDelaySec) external payable onlyOwner {
entryPoint.addStake{value : msg.value}(unstakeDelaySec);
}

function unlockStake(IEntryPoint entryPoint) external onlyOwner {
entryPoint.unlockStake();
}

function withdrawStake(IEntryPoint entryPoint, address payable withdrawAddress) external onlyOwner {
entryPoint.withdrawStake(withdrawAddress);
}

function createAccount(address owner,uint256 salt) public returns (address ret) {
address addr = getAddress(owner, salt);
uint codeSize = addr.code.length;
if (codeSize > 0) {
return (payable(addr));
}
ret = payable(new TokenPocketAAProxy{salt : bytes32(salt)}(
accountImplementation,
getInitializeData(owner)
));
emit CreateAccount(address(ret), owner, accountImplementation, salt);
}

function getAddress(address owner,uint256 salt) public view returns (address) {

return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked(
type(TokenPocketAAProxy).creationCode,
abi.encode(
address(accountImplementation),
getInitializeData(owner)
)
)));
}

function getInitializeData(address owner) internal pure returns (bytes memory) {
bytes4 sig = bytes4(keccak256("initialize(address)"));
bytes memory data = abi.encodeWithSelector(sig, owner);
return data;
}
}
16 changes: 16 additions & 0 deletions contracts/core/account/TokenPocketAAProxy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.18;

import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

contract TokenPocketAAProxy is ERC1967Proxy {

constructor(address _logic, bytes memory _data) ERC1967Proxy(_logic, _data) {

}

function getImplementation() external view returns (address) {
return _getImplementation();
}

}
15 changes: 15 additions & 0 deletions contracts/core/account/TokenPocketAccount.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.18;

import { IEntryPoint } from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
import { SimpleAccount } from "@account-abstraction/contracts/samples/SimpleAccount.sol";

contract TokenPocketAccount is SimpleAccount {

string public constant VERSION = "1.0.0";

constructor(IEntryPoint _entryPoint) SimpleAccount(_entryPoint) {

}

}
8 changes: 8 additions & 0 deletions contracts/core/entryPoint/EntryPoint060.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.18;

import "@account-abstraction/contracts/core/EntryPoint.sol";

contract EntryPoint060 is EntryPoint {
string public constant version = "0.6.0";
}
Loading

0 comments on commit 1f6b496

Please sign in to comment.