Skip to content

Commit

Permalink
first version
Browse files Browse the repository at this point in the history
  • Loading branch information
kopy-kat committed Sep 10, 2023
1 parent 11ce087 commit 8ecbed7
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 183 deletions.
69 changes: 26 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
<img align="right" width="150" height="150" top="100" src="./assets/blueprint.png">

# huff-project-template • [![ci](https://github.com/huff-language/huff-project-template/actions/workflows/ci.yaml/badge.svg)](https://github.com/huff-language/huff-project-template/actions/workflows/ci.yaml) ![license](https://img.shields.io/github/license/huff-language/huff-project-template.svg) ![solidity](https://img.shields.io/badge/solidity-^0.8.15-lightgrey)
# MinimalAccount

Versatile Huff Project Template using Foundry.
The most gas optimized ERC-4337 account - written directly in Huff.

> **Note**
>
> These contracts are **unaudited** and are not recommended for use in production.
>
> The main usage of these contracts is to benchmark other ERC-4337 accounts against the lowest possible gas cost for an account.
## Getting Started
## Gas calculations (as of Sep 10, 2023)

### Requirements
| | Creation | Native transfer | ERC20 transfer | Total |
| ---------------- | -------- | --------------- | -------------- | ------ |
| MinimalAccount | 199914 | 90645 | 79382 | 369941 |
| SimpleAccount | 410061 | 97690 | 86754 | 594505 |
| Biconomy | 296892 | 100780 | 89577 | 487249 |
| Etherspot | 305769 | 100091 | 89172 | 495032 |
| Kernel v2.0 | 366662 | 106800 | 95877 | 569339 |
| Kernel v2.1 | 291413 | 103240 | 92289 | 486942 |
| Kernel v2.1-lite | 256965 | 97331 | 86121 | 440417 |

The following will need to be installed in order to use this template. Please follow the links and instructions.
Calculations are based on ZeroDev's [AA Benchmark](https://github.com/zerodevapp/aa-benchmark)

- [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
- You'll know you've done it right if you can run `git --version`
- [Foundry / Foundryup](https://github.com/gakonst/foundry)
- This will install `forge`, `cast`, and `anvil`
- You can test you've installed them right by running `forge --version` and get an output like: `forge 0.2.0 (92f8951 2022-08-06T00:09:32.96582Z)`
- To get the latest of each, just run `foundryup`
- [Huff Compiler](https://docs.huff.sh/get-started/installing/)
- You'll know you've done it right if you can run `huffc --version` and get an output like: `huffc 0.3.0`
## Using this repo

### Quickstart

1. Clone this repo or use template

Click "Use this template" on [GitHub](https://github.com/huff-language/huff-project-template) to create a new repository with this repo as the initial state.

Or run:
1. Clone this repo

```
git clone https://github.com/huff-language/huff-project-template
cd huff-project-template
git clone https://github.com/kopy-kat/MinimalAccount.git
cd MinimalAccount
```

2. Install dependencies
Expand All @@ -52,33 +52,16 @@ forge test

For more information on how to use Foundry, check out the [Foundry Github Repository](https://github.com/foundry-rs/foundry/tree/master/forge) and the [foundry-huff library repository](https://github.com/huff-language/foundry-huff).


## Blueprint

```ml
lib
├─ forge-std — https://github.com/foundry-rs/forge-std
├─ foundry-huff — https://github.com/huff-language/foundry-huff
scripts
├─ Deploy.s.sol — Deployment Script
src
├─ SimpleStore — A Simple Storage Contract in Huff
test
└─ SimpleStore.t — SimpleStoreTests
```


## License

[The Unlicense](https://github.com/huff-language/huff-project-template/blob/master/LICENSE)


## Acknowledgements

- [forge-template](https://github.com/foundry-rs/forge-template)
- [femplate](https://github.com/abigger87/femplate)

- [ERC4337's SimpleAccount](https://github.com/eth-infinitism/account-abstraction/blob/develop/contracts/samples/SimpleAccount.sol)
- [Huffmate](https://github.com/huff-language/huffmate)
- [Huff](https://huff.sh)

## Disclaimer

_These smart contracts are being provided as is. No guarantee, representation or warranty is being made, express or implied, as to the safety or correctness of the user interface or the smart contracts. They have not been audited and as such there can be no assurance they will work as intended, and users may experience delays, failures, errors, omissions, loss of transmitted information or loss of funds. The creators are not liable for any of the foregoing. Users should proceed with caution and use at their own risk._
_These smart contracts are being provided as is. No guarantee, representation or warranty is being made, express or implied, as to the safety or correctness of the user interface or the smart contracts. They have not been audited and as such there can be no assurance they will work as intended, and users may experience delays, failures, errors, omissions, loss of transmitted information or loss of funds. The creators are not liable for any of the foregoing. Users should proceed with caution and use at their own risk._
31 changes: 20 additions & 11 deletions src/SimpleHuffAccount.huff → src/MinimalAccount.huff
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
/// @title SimpleHuffAccount
/// @notice Gas optimized ECDSA wrapper.
/// @title MinimalAccount
/// @notice Gas optimized minimal ERC-4337 account
/// @author kopy-kat <https://github.com/kopy-kat>
/// @custom:inspiration SimpleAccount <https://github.com/eth-infinitism/account-abstraction/blob/develop/contracts/samples/SimpleAccount.sol>
/// @custom:inspiration Huffmate <https://github.com/huff-language/huffmate>

/* Interface */
#define function execute(address,uint256,bytes) nonpayable returns ()
#define function validateUserOp(address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes32,uint256) nonpayable returns (uint256)

/* Constants */
#define constant ENTRYPOINT_ADDRESS = 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789
#define constant OWNER_ADDRESS = 0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf // replaced by the factory

///@dev The number which `s` must not exceed in order for the signature to be non-malleable
#define constant MALLEABILITY_THRESHOLD = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0
Expand All @@ -24,7 +24,6 @@
0x00 0x00 revert

fromEntrypoint:

}

#define macro PAY_PREFUND() = takes (0) returns (0) {
Expand All @@ -45,8 +44,18 @@
}

#define macro VALIDATE_SIGNATURE() = takes (0) returns (0) {

0x24 calldataload // [hash, v, r, s]
0x1a4 calldataload // [sigSlot]
0xa4 add // [sSlot]
dup1 calldataload // [s, sSlot]
swap1 // [sSlot, s]
0x20 swap1 sub // [rSlot, s]
dup1 calldataload // [r, rSlot, s]
swap1 // [rSlot, r, s]
0x40 add // [vSlot, r, s]
calldataload // [v, r, s]
0xF8 shr

0x24 calldataload // [hash, v, r, s]

// Store in scratch space for hashing.
0x20 mstore // [v, r, s]
Expand Down Expand Up @@ -78,12 +87,12 @@
pop pop pop pop 0x00 // [0x00]
end:

[OWNER_ADDRESS] eq validationFailed jumpi
[OWNER_ADDRESS] eq success jumpi

validationFailed:
0x01 0x00 mstore
0x20 0x00 return
0x01 0x00 mstore
0x20 0x00 return

success:
}

/* External functions */
Expand All @@ -92,7 +101,7 @@
VALIDATE_SIGNATURE()
PAY_PREFUND()

0x20 0x00
0x20 0x80
return
}

Expand Down
120 changes: 120 additions & 0 deletions src/MinimalAccountFactory.huff
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/// @title MinimalAccountFactory
/// @notice Factory for the MinimalAccount
/// @author kopy-kat <https://github.com/kopy-kat>
/// @custom:inspiration SimpleAccountFactory <https://github.com/eth-infinitism/account-abstraction/blob/develop/contracts/samples/SimpleAccountFactory.sol>

/* Interface */
#define function createAccount(address,uint256) nonpayable returns (address)
#define function getAddress(address,uint256) view returns (address)

/* Constants */
#define constant ACCOUNT_INITCODE = 0x61015880600a3d393df360003560e01c80633a871cdd14610021578063b61d27f61461011e5760006000fd5b33735ff137d4b0fdcd49dca30c7cf57e578a026d2789146100425760006000fd5b6101a43560a401803590602090038035906040013560f81c6024356020527b19457468657265756d205369676e6564204d6573736167653a0a3332600052603c6004207f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116100d457600052602052604052606052602060406080600060015afa5060006060523d606003516100db565b5050505060005b737e5f4552091a69125d5dfcb7b8c2659029395bdf1461010057600160005260206000f35b6044358060001461011857600060006000600093335af15b60206080f35b33735ff137d4b0fdcd49dca30c7cf57e578a026d27891461013f5760006000fd5b606435806084600037600060209160006024356004355af1
#define constant ACCOUNT_INITCODE_LENGTH = 0x164
#define constant ACCOUNT_INITCODE_HASH = 0xf62ad50462f93b6a5d1b025f45d9b88bb5ea39d677f69a666816cfdf628fd446

/* Internal functions */
#define macro GET_ACCOUNT_INITCODE() = takes (0) returns (0) {
0x61015880600a3d393df360003560e01c80633a871cdd14610021578063b61d27 0x00 mstore
0xf61461011e5760006000fd5b33735ff137d4b0fdcd49dca30c7cf57e578a026d 0x20 mstore
0x2789146100425760006000fd5b6101a43560a401803590602090038035906040 0x40 mstore
0x013560f81c6024356020527b19457468657265756d205369676e6564204d6573 0x60 mstore
0x736167653a0a3332600052603c6004207f7fffffffffffffffffffffffffffff 0x80 mstore
0xff5d576e7357a4501ddfe92f46681b20a084116100d457600052602052604052 0xa0 mstore
0x606052602060406080600060015afa5060006060523d606003516100db565b50 0xc0 mstore
0x50505060005b737e5f4552091a69125d5dfcb7b8c2659029395bdf1461010057 0xe0 mstore
0x600160005260206000f35b604435806000146101185760006000600060009333 0x100 mstore
0x5af15b60206080f35b33735ff137d4b0fdcd49dca30c7cf57e578a026d278914 0x120 mstore
0x61013f5760006000fd5b60643580608460003760006020916000602435600435 0x140 mstore
0x5af1000000000000000000000000000000000000000000000000000000000000 0x160 mstore
}

/* External functions */
#define macro CREATE_ACCOUNT() = takes (0) returns (0) {

// [ACCOUNT_BYTECODE] 0x00 mstore

// 0x60908060093d393df360003560e01c80633a871cdd14610021578063b61d27f6 0x00 mstore
// 0x146100565760006000fd5b33735ff137d4b0fdcd49dca30c7cf57e578a026d27 0x20 mstore
// 0x89146100425760006000fd5b6000600060006000604435335af160206000f35b 0x40 mstore
// 0x33735ff137d4b0fdcd49dca30c7cf57e578a026d2789146100775760006000fd 0x60 mstore
// 0x5b606435806084600037600060209160006024356004355af100000000000000 0x80 mstore

// 0x61018480600a3d393df360003560e01c80633a871cdd14610021578063b61d27 0x00 mstore
// 0xf61461014a5760006000fd5b33735ff137d4b0fdcd49dca30c7cf57e578a026d 0x20 mstore
// 0x2789146100425760006000fd5b7f68eaa91fcee1235f6cbcdfed4958c9eb8bfe 0x40 mstore
// 0x0a270174ed08e8bca0bc5b3cf93e7f498e7bf7455b69dbf0b2e93f1c23f206f4 0x60 mstore
// 0xabd35d22bd73df5daea4f668ed43b0601c6024356020527b1945746865726575 0x80 mstore
// 0x6d205369676e6564204d6573736167653a0a3332600052603c6004207f7fffff 0xa0 mstore
// 0xffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841161 0xc0 mstore
// 0x010057600052602052604052606052602060406080600060015afa5060006060 0xe0 mstore
// 0x523d60600351610107565b5050505060005b737e5f4552091a69125d5dfcb7b8 0x100 mstore
// 0xc2659029395bdf1461012c57600160005260206000f35b604435806000146101 0x120 mstore
// 0x4457600060006000600093335af15b60206080f35b33735ff137d4b0fdcd49dc 0x140 mstore
// 0xa30c7cf57e578a026d27891461016b5760006000fd5b60643580608460003760 0x160 mstore
// 0x0060209160006024356004355af1000000000000000000000000000000000000 0x180 mstore

// 0x61015880600a3d393df360003560e01c80633a871cdd14610021578063b61d27 0x00 mstore
// 0xf61461011e5760006000fd5b33735ff137d4b0fdcd49dca30c7cf57e578a026d 0x20 mstore
// 0x2789146100425760006000fd5b6101a43560a401803590602090038035906040 0x40 mstore
// 0x013560f81c6024356020527b19457468657265756d205369676e6564204d6573 0x60 mstore
// 0x736167653a0a3332600052603c6004207f7fffffffffffffffffffffffffffff 0x80 mstore
// 0xff5d576e7357a4501ddfe92f46681b20a084116100d457600052602052604052 0xa0 mstore
// 0x606052602060406080600060015afa5060006060523d606003516100db565b50 0xc0 mstore
// 0x50505060005b737e5f4552091a69125d5dfcb7b8c2659029395bdf1461010057 0xe0 mstore
// 0x600160005260206000f35b604435806000146101185760006000600060009333 0x100 mstore
// 0x5af15b60206080f35b33735ff137d4b0fdcd49dca30c7cf57e578a026d278914 0x120 mstore
// 0x61013f5760006000fd5b60643580608460003760006020916000602435600435 0x140 mstore
// 0x5af1000000000000000000000000000000000000000000000000000000000000 0x160 mstore

GET_ACCOUNT_INITCODE()

0x24 calldataload // [salt]
[ACCOUNT_INITCODE_LENGTH] // [bytesize, salt]
0x00 // [offset, bytesize, salt]
0x00 // [value, offset, bytesize, salt]
create2

0x00 mstore
0x20 0x00 return
}

#define macro GET_ADDRESS() = takes (0) returns (0) {
// Store the code hash @ 0x54:0x74
GET_ACCOUNT_INITCODE()
[ACCOUNT_INITCODE_LENGTH] 0x00 sha3
0x54 mstore

// Store the prefix @ 0x00:0x20
0xff 0x00 mstore

// Store this address @ 0x20:0x34
address 0x60 shl 0x20 mstore

// Store the salt @ 0x34:0x54
0x24 calldataload
0x34 mstore

// Hash the packed data
0x55 0x1f sha3 // [raw_hash]

// Clean the upper 12 bytes (96 bits or 0x60)
0x60 shl 0x60 shr // [address]

0x74 mstore
0x20 0x74 return
}

#define macro MAIN() = takes (0) returns (0) {
// Identify which function is being called.
0x00 calldataload 0xE0 shr
dup1 __FUNC_SIG(createAccount) eq createAccount jumpi
dup1 __FUNC_SIG(getAddress) eq getAddress jumpi

0x00 0x00 revert

createAccount:
CREATE_ACCOUNT()
getAddress:
GET_ADDRESS()

}
78 changes: 0 additions & 78 deletions src/SimpleHuffAccountFactory.huff

This file was deleted.

Loading

0 comments on commit 8ecbed7

Please sign in to comment.