forked from eth-infinitism/bundler
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
AA-72 bundling module (eth-infinitism#25)
- modular bundler support multi-userOp bundles. - support debug_ api for testing. - support opcode banning, using geth debug_traceCall module. - uses new v0.4 contracts.
- Loading branch information
1 parent
c36bbc4
commit 270ff68
Showing
50 changed files
with
2,841 additions
and
1,300 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
name: Build | ||
on: | ||
push: | ||
branches: | ||
- '*' | ||
pull_request: | ||
types: [opened, reopened, synchronize] | ||
|
||
env: | ||
TS_NODE_TRANSPILE_ONLY: 1 | ||
FORCE_COLORS: 1 | ||
|
||
# todo: extract shared seto/checkout/install/compile, instead of repeat in each job. | ||
jobs: | ||
|
||
test: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/setup-node@v1 | ||
with: | ||
node-version: '14' | ||
- uses: actions/checkout@v1 | ||
- uses: actions/cache@v2 | ||
with: | ||
path: node_modules | ||
key: ${{ runner.os }}-${{ hashFiles('yarn.lock') }} | ||
- run: yarn install | ||
- run: yarn run ci | ||
|
||
lint: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/setup-node@v1 | ||
with: | ||
node-version: '14' | ||
- uses: actions/checkout@v1 | ||
- uses: actions/cache@v2 | ||
with: | ||
path: node_modules | ||
key: ${{ runner.os }}-${{ hashFiles('yarn.lock') }} | ||
- run: yarn install | ||
- run: yarn preprocess | ||
- run: yarn lerna-lint | ||
|
||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
pragma solidity ^0.8.15; | ||
|
||
import "@account-abstraction/contracts/interfaces/IAccount.sol"; | ||
import "@account-abstraction/contracts/interfaces/IPaymaster.sol"; | ||
import "@account-abstraction/contracts/interfaces/IEntryPoint.sol"; | ||
import "./TestRuleAccount.sol"; | ||
|
||
contract Dummy { | ||
} | ||
|
||
|
||
/** | ||
* an account with "rules" to trigger different opcode validation rules | ||
*/ | ||
contract TestOpcodesAccount is TestRuleAccount { | ||
|
||
event TestMessage(address eventSender); | ||
|
||
function runRule(string memory rule) public virtual override returns (uint) { | ||
if (eq(rule, "number")) return block.number; | ||
else if (eq(rule, "coinbase")) return uint160(address(block.coinbase)); | ||
else if (eq(rule, "blockhash")) return uint(blockhash(0)); | ||
else if (eq(rule, "create2")) { | ||
new Dummy{salt : bytes32(uint(0x1))}(); | ||
return 0; | ||
} | ||
else if (eq(rule, "emit-msg")) { | ||
emit TestMessage(address(this)); | ||
return 0; | ||
} | ||
return super.runRule(rule); | ||
} | ||
} | ||
|
||
contract TestOpcodesAccountFactory { | ||
function create(string memory rule) public returns (TestOpcodesAccount) { | ||
TestOpcodesAccount a = new TestOpcodesAccount{salt : bytes32(uint(0))}(); | ||
a.runRule(rule); | ||
return a; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
pragma solidity ^0.8.15; | ||
|
||
import "@account-abstraction/contracts/interfaces/IAccount.sol"; | ||
import "@account-abstraction/contracts/interfaces/IPaymaster.sol"; | ||
import "@account-abstraction/contracts/interfaces/IEntryPoint.sol"; | ||
import "./TestRuleAccount.sol"; | ||
|
||
contract TestRecursionAccount is TestRuleAccount { | ||
|
||
IEntryPoint public immutable ep; | ||
constructor(IEntryPoint _ep) { | ||
ep = _ep; | ||
} | ||
|
||
function runRule(string memory rule) public virtual override returns (uint) { | ||
|
||
if (eq(rule, "handleOps")) { | ||
UserOperation[] memory ops = new UserOperation[](0); | ||
ep.handleOps(ops, payable(address (1))); | ||
return 0; | ||
} | ||
|
||
return super.runRule(rule); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
pragma solidity ^0.8.15; | ||
|
||
import "@account-abstraction/contracts/interfaces/IAccount.sol"; | ||
import "@account-abstraction/contracts/interfaces/IPaymaster.sol"; | ||
import "@account-abstraction/contracts/interfaces/IEntryPoint.sol"; | ||
|
||
/** | ||
* contract for testing account interaction. | ||
* doesn't really do validation: the signature is a "rule" to define the validation action to take. | ||
* as a paymaster, the paymasterAndData is the "rule" to take (at offset 20, just after the paymaster address) | ||
* the account also as a "state" variable and event, so we can use it to test state transitions | ||
*/ | ||
contract TestRuleAccount is IAccount, IPaymaster { | ||
|
||
uint state; | ||
|
||
event State(uint oldState, uint newState); | ||
|
||
function setState(uint _state) external { | ||
emit State(state, _state); | ||
state = _state; | ||
} | ||
|
||
function eq(string memory a, string memory b) internal pure returns (bool) { | ||
return keccak256(bytes(a)) == keccak256(bytes(b)); | ||
} | ||
|
||
/** | ||
* "rules" to test. override to add more "rules" | ||
*/ | ||
function runRule(string memory rule) public virtual returns (uint) { | ||
if (eq(rule, "")) return 0; | ||
else if (eq(rule, "ok")) return 0; | ||
else if (eq(rule, "fail")) revert("fail rule"); | ||
else | ||
revert(string.concat("unknown rule: ", rule)); | ||
} | ||
|
||
//needed in order to make it a valid paymaster | ||
function addStake(IEntryPoint entryPoint) public payable { | ||
entryPoint.addStake{value : msg.value}(1); | ||
} | ||
|
||
function validateUserOp(UserOperation calldata userOp, bytes32, address, uint256 missingAccountFunds) | ||
external virtual override returns (uint256) { | ||
if (missingAccountFunds > 0) { | ||
/* solhint-disable-next-line avoid-low-level-calls */ | ||
(bool success,) = msg.sender.call{value : missingAccountFunds}(""); | ||
success; | ||
} | ||
runRule(string(userOp.signature)); | ||
return 0; | ||
} | ||
|
||
function validatePaymasterUserOp(UserOperation calldata userOp, bytes32, uint256) | ||
public virtual override returns (bytes memory context, uint256 deadline) { | ||
string memory rule = string(userOp.paymasterAndData[20 :]); | ||
runRule(rule); | ||
return ("", 0); | ||
} | ||
|
||
function postOp(PostOpMode, bytes calldata, uint256) external {} | ||
} | ||
|
||
contract TestRuleAccountFactory { | ||
function create(string memory rule) public returns (TestRuleAccount) { | ||
TestRuleAccount a = new TestRuleAccount{salt : bytes32(uint(0))}(); | ||
a.runRule(rule); | ||
return a; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
pragma solidity ^0.8.15; | ||
|
||
import "@account-abstraction/contracts/interfaces/IAccount.sol"; | ||
import "@account-abstraction/contracts/interfaces/IPaymaster.sol"; | ||
import "@account-abstraction/contracts/interfaces/IEntryPoint.sol"; | ||
import "./TestRuleAccount.sol"; | ||
|
||
contract TestCoin { | ||
mapping(address => uint) balances; | ||
|
||
function balanceOf(address addr) public returns (uint) { | ||
return balances[addr]; | ||
} | ||
|
||
function mint(address addr) public returns (uint) { | ||
return balances[addr] += 100; | ||
} | ||
|
||
//unrelated to token: testing inner object revert | ||
function reverting() public returns (uint) { | ||
revert("inner-revert"); | ||
} | ||
|
||
function wasteGas() public returns (uint) { | ||
while (true) { | ||
require(msg.sender != ecrecover("message", 27, bytes32(0), bytes32(0))); | ||
} | ||
return 0; | ||
} | ||
} | ||
|
||
/** | ||
* an account with "rules" to trigger different opcode validation rules | ||
*/ | ||
contract TestStorageAccount is TestRuleAccount { | ||
|
||
TestCoin coin; | ||
|
||
function setCoin(TestCoin _coin) public returns (uint){ | ||
coin = _coin; | ||
return 0; | ||
} | ||
|
||
event TestMessage(address eventSender); | ||
|
||
function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost) | ||
public virtual override returns (bytes memory context, uint256 deadline) { | ||
string memory rule = string(userOp.paymasterAndData[20 :]); | ||
if (eq(rule, 'postOp-context')) { | ||
return ("some-context",0); | ||
} | ||
// return ("",0); | ||
return super.validatePaymasterUserOp(userOp, userOpHash, maxCost); | ||
} | ||
|
||
function runRule(string memory rule) public virtual override returns (uint) { | ||
if (eq(rule, "number")) return block.number; | ||
else if (eq(rule, "balance-self")) return coin.balanceOf(address(this)); | ||
else if (eq(rule, "mint-self")) return coin.mint(address(this)); | ||
else if (eq(rule, "balance-1")) return coin.balanceOf(address(1)); | ||
else if (eq(rule, "mint-1")) return coin.mint(address(1)); | ||
else if (eq(rule, "inner-revert")) { | ||
(bool success,) = address(coin).call(abi.encode(coin.reverting)); | ||
success; | ||
return 0; | ||
} | ||
else if (eq(rule, "oog")) { | ||
try coin.wasteGas{gas : 50000}() {} | ||
catch {} | ||
return 0; | ||
} | ||
return super.runRule(rule); | ||
} | ||
} | ||
|
||
contract TestStorageAccountFactory { | ||
TestCoin immutable coin; | ||
constructor() { | ||
coin = new TestCoin(); | ||
} | ||
|
||
function create(uint salt, string memory rule) public returns (TestStorageAccount) { | ||
TestStorageAccount a = new TestStorageAccount{salt : bytes32(salt)}(); | ||
a.setCoin(coin); | ||
a.runRule(rule); | ||
return a; | ||
} | ||
|
||
} |
Oops, something went wrong.