-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from akamo778/feature/submission-session-account
session account wallet implementation
- Loading branch information
Showing
17 changed files
with
3,902 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
# Logs | ||
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.* | ||
|
||
artifacts-zk/ | ||
cache-zk/ |
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,2 @@ | ||
twitter: https://twitter.com/akamo778 | ||
discord: Ryo#2410 |
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,71 @@ | ||
# Session Wallet | ||
## Overview | ||
|
||
In most cases, the wallet must be opened when sending a transaction. | ||
|
||
With an app that requires only a few transaction sends, such as DeFi, the operation of opening the wallet is not stressful. | ||
However, if it is an app that sends transactions frequently, such as gaming or social media, it becomes a big problem. You need to open the wallet frequently and cannot fully use the app. | ||
|
||
It is the worst UX in the world. | ||
|
||
To solve this problem, I created a wallet that can issue session keys. | ||
You give the issued session key to a trusted institution (e.g., a gaming company) to send transactions on your behalf. | ||
In other words, your wallet is temporarily under the control of that institution. | ||
However, you do not need to give them your private key, you just need to give them your session key. | ||
Of course, you can deactivate the session key. | ||
|
||
Now you can open your wallet once and focus on your game the rest of the time. | ||
|
||
## Deploy contracts | ||
|
||
Execute the following command to setup | ||
|
||
``` | ||
yarn install | ||
yarn workspace contracts setup | ||
yarn workspace contracts hardhat compile | ||
``` | ||
|
||
Then, set the following environment variables | ||
* INFURA_API_KEY | ||
* DEPLOYER_PRIVATE_KEY | ||
* ACCOUNT_OWNER_ADDRESS | ||
|
||
Deploy the AccountFactory contract with the following command | ||
|
||
``` | ||
yarn workspace contracts deploy:factory | ||
``` | ||
|
||
The address of the deployed AccountFactory contract will be displayed on your terminal, copy it to ACCOUNT_FACTORY_ADDRESS in the .env file. | ||
|
||
Deploy the Account contract with the following command | ||
|
||
``` | ||
yarn workspace contracts deploy:account | ||
``` | ||
|
||
The address of the deployed Account contract will be displayed on your terminal, copy it to ACCOUNT_ADDRESS in the .env file. | ||
|
||
## Running Sample Scripts | ||
|
||
After deployment is complete, you can run the following sample script to create a session and send transactions by the session. | ||
|
||
ACCOUNT_OWNER_PRIVATE_KEY and SESSION_OWNER_PRIVATE_KEY must be specified in the .env file | ||
|
||
``` | ||
yarn workspace contracts hardhat run scripts/create-session.ts | ||
yarn workspace contracts hardhat run scripts/transfer-by-session.ts | ||
``` | ||
|
||
Finally, delete the session. | ||
|
||
``` | ||
yarn workspace contracts hardhat run scripts/delete-session.ts | ||
``` | ||
|
||
If you retransfer by old session, some error will occur. | ||
|
||
``` | ||
yarn workspace contracts hardhat run scripts/transfer-by-session.ts | ||
``` |
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,14 @@ | ||
INFURA_API_KEY= | ||
|
||
# to deploy contracts | ||
DEPLOYER_PRIVATE_KEY=0x | ||
ACCOUNT_OWNER_ADDRESS=0x | ||
ACCOUNT_DEPLOYMENT_SALT=0x0000000000000000000000000000000000000000000000000000000000000000 | ||
|
||
# memo deployed contracts | ||
ACCOUNT_FACTORY_ADDRESS=0x | ||
ACCOUNT_ADDRESS=0x | ||
|
||
# scripts | ||
ACCOUNT_OWNER_PRIVATE_KEY=0x | ||
SESSION_OWNER_PRIVATE_KEY=0x |
136 changes: 136 additions & 0 deletions
136
submissions/session-wallet/code/contracts/contracts/Account.sol
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,136 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import "@matterlabs/zksync-contracts/l2/system-contracts/interfaces/IAccount.sol"; | ||
import "@matterlabs/zksync-contracts/l2/system-contracts/TransactionHelper.sol"; | ||
import "@openzeppelin/contracts/access/Ownable.sol"; | ||
import "@openzeppelin/contracts/interfaces/IERC1271.sol"; | ||
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; | ||
import "@matterlabs/zksync-contracts/l2/system-contracts/Constants.sol"; | ||
import "@matterlabs/zksync-contracts/l2/system-contracts/SystemContractsCaller.sol"; | ||
|
||
import "./SocialRecovery.sol"; | ||
import "./Session.sol"; | ||
|
||
contract Account is Ownable, Session, SocialRecovery, IAccount { | ||
using TransactionHelper for Transaction; | ||
|
||
bytes4 constant EIP1271_SUCCESS_RETURN_VALUE = 0x1626ba7e; | ||
|
||
modifier onlyBootloader() { | ||
require( | ||
msg.sender == BOOTLOADER_FORMAL_ADDRESS, | ||
"Only bootloader can call this method" | ||
); | ||
_; | ||
} | ||
|
||
constructor(address owner) { | ||
_transferOwnership(owner); | ||
} | ||
|
||
function validateTransaction( | ||
bytes32, | ||
bytes32 _suggestedSignedHash, | ||
Transaction calldata _transaction | ||
) external payable override onlyBootloader { | ||
_validateTransaction(_suggestedSignedHash, _transaction); | ||
} | ||
|
||
function _validateTransaction( | ||
bytes32 _suggestedSignedHash, | ||
Transaction calldata _transaction | ||
) internal { | ||
SystemContractsCaller.systemCall( | ||
uint32(gasleft()), | ||
address(NONCE_HOLDER_SYSTEM_CONTRACT), | ||
0, | ||
abi.encodeCall( | ||
INonceHolder.incrementMinNonceIfEquals, | ||
(_transaction.reserved[0]) | ||
) | ||
); | ||
|
||
bytes32 txHash; | ||
if (_suggestedSignedHash == bytes32(0)) { | ||
txHash = _transaction.encodeHash(); | ||
} else { | ||
txHash = _suggestedSignedHash; | ||
} | ||
|
||
|
||
require(_transaction.signature.length == 65, "Signature length is incorrect"); | ||
|
||
address signer = ECDSA.recover(txHash, _transaction.signature); | ||
address to = address(uint160(_transaction.to)); | ||
|
||
require(owner() == signer || inSession(signer, to, _transaction.data), "Signature is invalid"); | ||
} | ||
|
||
function executeTransaction( | ||
bytes32, | ||
bytes32, | ||
Transaction calldata _transaction | ||
) external payable override onlyBootloader { | ||
_executeTransaction(_transaction); | ||
} | ||
|
||
function _executeTransaction(Transaction calldata _transaction) internal { | ||
address to = address(uint160(_transaction.to)); | ||
uint256 value = _transaction.reserved[1]; | ||
bytes memory data = _transaction.data; | ||
|
||
if (to == address(DEPLOYER_SYSTEM_CONTRACT)) { | ||
SystemContractsCaller.systemCall( | ||
uint32(gasleft()), | ||
to, | ||
uint128(_transaction.reserved[1]), | ||
_transaction.data | ||
); | ||
} else { | ||
bool success; | ||
assembly { | ||
success := call( | ||
gas(), | ||
to, | ||
value, | ||
add(data, 0x20), | ||
mload(data), | ||
0, | ||
0 | ||
) | ||
} | ||
require(success); | ||
} | ||
} | ||
|
||
function executeTransactionFromOutside(Transaction calldata _transaction) | ||
external | ||
payable | ||
{ | ||
_validateTransaction(bytes32(0), _transaction); | ||
|
||
_executeTransaction(_transaction); | ||
} | ||
|
||
function payForTransaction( | ||
bytes32, | ||
bytes32, | ||
Transaction calldata _transaction | ||
) external payable override onlyBootloader { | ||
bool success = _transaction.payToTheBootloader(); | ||
require(success, "Failed to pay the fee to the operator"); | ||
} | ||
|
||
function prePaymaster( | ||
bytes32, | ||
bytes32, | ||
Transaction calldata _transaction | ||
) external payable override onlyBootloader { | ||
_transaction.processPaymasterInput(); | ||
} | ||
|
||
receive() external payable { | ||
assert(msg.sender != BOOTLOADER_FORMAL_ADDRESS); | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
submissions/session-wallet/code/contracts/contracts/AccountFactory.sol
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,30 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import "@matterlabs/zksync-contracts/l2/system-contracts/Constants.sol"; | ||
import "@matterlabs/zksync-contracts/l2/system-contracts/SystemContractsCaller.sol"; | ||
|
||
contract AccountFactory { | ||
bytes32 public aaBytecodeHash; | ||
|
||
constructor(bytes32 _aaBytecodeHash) { | ||
aaBytecodeHash = _aaBytecodeHash; | ||
} | ||
|
||
function deployAccount( | ||
bytes32 salt, | ||
address owner | ||
) external returns (address accountAddress) { | ||
bytes memory returnData = SystemContractsCaller.systemCall( | ||
uint32(gasleft()), | ||
address(DEPLOYER_SYSTEM_CONTRACT), | ||
0, | ||
abi.encodeCall( | ||
DEPLOYER_SYSTEM_CONTRACT.create2Account, | ||
(salt, aaBytecodeHash, abi.encode(owner)) | ||
) | ||
); | ||
|
||
(accountAddress, ) = abi.decode(returnData, (address, bytes)); | ||
} | ||
} |
Oops, something went wrong.