From 1b783bac82613e9c6ce831def0bc0c282d2badcf Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Wed, 19 May 2021 22:08:43 +0800
Subject: [PATCH 01/18] init user_map

---
 contracts/Fluidex.sol | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/contracts/Fluidex.sol b/contracts/Fluidex.sol
index aa823ca..6863015 100644
--- a/contracts/Fluidex.sol
+++ b/contracts/Fluidex.sol
@@ -30,6 +30,10 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
     mapping(uint16 => address) public tokenIdToAddr;
     mapping(address => uint16) public tokenAddrToId;
 
+    uint16 public userNum;
+    mapping(uint16 => address) public userIdToAddr;
+    mapping(address => uint16) public userAddrToId;
+
     function initialize() external {}
 
     function addToken(address tokenAddr)

From 29d683c539b07eafe58f256c30e38d7cb969b921 Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Wed, 19 May 2021 22:13:23 +0800
Subject: [PATCH 02/18] init registerUser

---
 contracts/Fluidex.sol | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/contracts/Fluidex.sol b/contracts/Fluidex.sol
index 6863015..1253e2b 100644
--- a/contracts/Fluidex.sol
+++ b/contracts/Fluidex.sol
@@ -62,6 +62,12 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
         emit NewTradingPair(baseTokenId, quoteTokenId);
     }
 
+    // TODO: priority queue? check signature?
+    function registerUser(address ethAddr) internal {
+        // TODO:
+        emit RegisterUser(userId, ethAddr);
+    }
+
     // 0 tokenId means native ETH coin
     // TODO: zkSync uses uint128 for amount
     function registerDeposit(uint16 tokenId, address to, uint256 amount) internal {

From 585f2c33de5c0affa8a4c6ba15401482335fb254 Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Wed, 19 May 2021 22:32:07 +0800
Subject: [PATCH 03/18] add registerUser()

---
 contracts/Fluidex.sol | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/contracts/Fluidex.sol b/contracts/Fluidex.sol
index 1253e2b..3523efc 100644
--- a/contracts/Fluidex.sol
+++ b/contracts/Fluidex.sol
@@ -25,6 +25,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
     using SafeMath for uint256;
 
     uint16 constant TOKEN_NUM_LIMIT = 65535;
+    uint16 constant USER_NUM_LIMIT = 65535;
 
     uint16 public tokenNum;
     mapping(uint16 => address) public tokenIdToAddr;
@@ -64,8 +65,16 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
 
     // TODO: priority queue? check signature?
     function registerUser(address ethAddr) internal {
-        // TODO:
+        userNum++;
+        require(userAddrToId[ethAddr] == 0, "user existed");
+        require(userNum < USER_NUM_LIMIT, "user num limit reached");
+
+        uint16 userId = userNum;
+        userIdToAddr[userId] = ethAddr;
+        userAddrToId[ethAddr] = userId;
+        // TODO: bjj?
         emit RegisterUser(userId, ethAddr);
+        return userId;
     }
 
     // 0 tokenId means native ETH coin

From efd4e56ee357dd1a3d5b376c1876d4c6cda7d464 Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Wed, 19 May 2021 22:36:53 +0800
Subject: [PATCH 04/18] add event

---
 contracts/Events.sol  | 1 +
 contracts/Fluidex.sol | 7 +++++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/contracts/Events.sol b/contracts/Events.sol
index a9edc67..8a58958 100644
--- a/contracts/Events.sol
+++ b/contracts/Events.sol
@@ -8,6 +8,7 @@ import "./Operations.sol";
 interface Events {
     event NewToken(address tokenAddr, uint16 tokenId);
     event NewTradingPair(uint16 baseTokenId, uint16 quoteTokenId);
+    event RegisterUser(address ethAddr, uint16 userId);
     event Deposit(uint16 tokenId, address to, uint256 amount); // emit tokenId or tokenAddr?
     event Withdraw(uint16 tokenId, address to, uint256 amount); // emit tokenId or tokenAddr?
 
diff --git a/contracts/Fluidex.sol b/contracts/Fluidex.sol
index 3523efc..36bf630 100644
--- a/contracts/Fluidex.sol
+++ b/contracts/Fluidex.sol
@@ -64,7 +64,10 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
     }
 
     // TODO: priority queue? check signature?
-    function registerUser(address ethAddr) internal {
+    function registerUser(address ethAddr)
+        internal
+        returns (uint16)
+    {
         userNum++;
         require(userAddrToId[ethAddr] == 0, "user existed");
         require(userNum < USER_NUM_LIMIT, "user num limit reached");
@@ -73,7 +76,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
         userIdToAddr[userId] = ethAddr;
         userAddrToId[ethAddr] = userId;
         // TODO: bjj?
-        emit RegisterUser(userId, ethAddr);
+        emit RegisterUser(ethAddr, userId);
         return userId;
     }
 

From f883920a59cf5973732da369c3acd4fa48385129 Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Thu, 20 May 2021 09:17:49 +0800
Subject: [PATCH 05/18] add bjjPubkey

---
 contracts/Events.sol  |  2 +-
 contracts/Fluidex.sol | 24 ++++++++++++++++++------
 2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/contracts/Events.sol b/contracts/Events.sol
index 8a58958..63b7b14 100644
--- a/contracts/Events.sol
+++ b/contracts/Events.sol
@@ -8,7 +8,7 @@ import "./Operations.sol";
 interface Events {
     event NewToken(address tokenAddr, uint16 tokenId);
     event NewTradingPair(uint16 baseTokenId, uint16 quoteTokenId);
-    event RegisterUser(address ethAddr, uint16 userId);
+    event RegisterUser(address ethAddr, uint16 userId, bytes bjjPubkey);
     event Deposit(uint16 tokenId, address to, uint256 amount); // emit tokenId or tokenAddr?
     event Withdraw(uint16 tokenId, address to, uint256 amount); // emit tokenId or tokenAddr?
 
diff --git a/contracts/Fluidex.sol b/contracts/Fluidex.sol
index 36bf630..503717a 100644
--- a/contracts/Fluidex.sol
+++ b/contracts/Fluidex.sol
@@ -63,8 +63,8 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
         emit NewTradingPair(baseTokenId, quoteTokenId);
     }
 
-    // TODO: priority queue? check signature?
-    function registerUser(address ethAddr)
+    // TODO: check signature?
+    function registerUser(address ethAddr, bytes memory bjjPubkey)
         internal
         returns (uint16)
     {
@@ -75,8 +75,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
         uint16 userId = userNum;
         userIdToAddr[userId] = ethAddr;
         userAddrToId[ethAddr] = userId;
-        // TODO: bjj?
-        emit RegisterUser(ethAddr, userId);
+        emit RegisterUser(ethAddr, userId, bjjPubkey);
         return userId;
     }
 
@@ -97,10 +96,17 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
     }
 
     /// @param to the L2 address of the deposit target.
-    // TODO: change to L2 address
-    function depositETH(address to) external payable {
+    function depositETH(
+        bytes calldata bjjPubkeyFrom,
+        address to // TODO: change to L2 address
+    ) external payable {
         // You must `approve` the allowance before calling this method
         require(to != address(0), "invalid address");
+
+        if (userAddrToId[msg.sender] == 0) {
+            registerUser(msg.sender, bjjPubkeyFrom);
+        }
+
         // 0 tokenId means native ETH coin
         registerDeposit(0, to, msg.value);
     }
@@ -109,6 +115,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
     /// @param amount the deposit amount.
     function depositERC20(
         IERC20 token,
+        bytes calldata bjjPubkeyFrom,
         address to, // TODO: change to L2 address
         uint128 amount
     ) external nonReentrant {
@@ -116,6 +123,11 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
         require(to != address(0), "invalid address");
         uint16 tokenId = tokenAddrToId[address(token)];
         require(tokenId != 0, "invalid token");
+
+        if (userAddrToId[msg.sender] == 0) {
+            registerUser(msg.sender, bjjPubkeyFrom);
+        }
+
         uint256 balanceBeforeDeposit = token.balanceOf(address(this));
         token.safeTransferFrom(msg.sender, address(this), amount);
         uint256 balanceAfterDeposit = token.balanceOf(address(this));

From 5408c07ef9aa6398dfea8f9fc21bf6251bb3dda4 Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Thu, 20 May 2021 09:35:05 +0800
Subject: [PATCH 06/18] fix test

---
 test/token.js | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/test/token.js b/test/token.js
index d861a7c..c472298 100644
--- a/test/token.js
+++ b/test/token.js
@@ -47,10 +47,11 @@ describe("Fluidex", () => {
     );
 
     // TODO: NewPriorityRequest event
+    const mockBjj = [];
     await expect(
       fluidex
         .connect(acc2)
-        .depositERC20(erc20Mock.address, acc2addr, depositAmount)
+        .depositERC20(erc20Mock.address, mockBjj, acc2addr, depositAmount)
     )
       .to.emit(fluidex, "Deposit")
       .withArgs(tokenId, acc2addr, depositAmount);
@@ -66,10 +67,11 @@ describe("Fluidex", () => {
     const withdrawAmount = 300;
 
     // TODO: NewPriorityRequest event
+    const mockBjj = [];
     await expect(
       fluidex
         .connect(acc2)
-        .depositETH(acc2addr, {value: depositAmount})
+        .depositETH(mockBjj, acc2addr, {value: depositAmount})
     )
       .to.emit(fluidex, "Deposit")
       .withArgs(0, acc2addr, depositAmount);

From 0cb6652d4ea7333ddb0a5ec3cea93e615d6b2d93 Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Thu, 20 May 2021 10:01:26 +0800
Subject: [PATCH 07/18] WIP

---
 contracts/Fluidex.sol | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/contracts/Fluidex.sol b/contracts/Fluidex.sol
index 503717a..f039235 100644
--- a/contracts/Fluidex.sol
+++ b/contracts/Fluidex.sol
@@ -97,14 +97,13 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
 
     /// @param to the L2 address of the deposit target.
     function depositETH(
-        bytes calldata bjjPubkeyFrom,
-        address to // TODO: change to L2 address
+        bytes calldata to // L2 bjjPubkey
     ) external payable {
         // You must `approve` the allowance before calling this method
-        require(to != address(0), "invalid address");
 
-        if (userAddrToId[msg.sender] == 0) {
-            registerUser(msg.sender, bjjPubkeyFrom);
+        // TODO: check `to` format
+        if (userAddrToId[to] == 0) {
+            registerUser(msg.sender, to);
         }
 
         // 0 tokenId means native ETH coin
@@ -115,17 +114,17 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
     /// @param amount the deposit amount.
     function depositERC20(
         IERC20 token,
-        bytes calldata bjjPubkeyFrom,
-        address to, // TODO: change to L2 address
+        bytes calldata to, // L2 bjjPubkey
         uint128 amount
     ) external nonReentrant {
         // You must `approve` the allowance before calling this method
-        require(to != address(0), "invalid address");
+
         uint16 tokenId = tokenAddrToId[address(token)];
         require(tokenId != 0, "invalid token");
 
-        if (userAddrToId[msg.sender] == 0) {
-            registerUser(msg.sender, bjjPubkeyFrom);
+        // TODO: check `to` format
+        if (userAddrToId[to] == 0) {
+            registerUser(msg.sender, to);
         }
 
         uint256 balanceBeforeDeposit = token.balanceOf(address(this));

From 50e153fcf45d5cc21767c320b5f3cc41d6f3a774 Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Thu, 20 May 2021 10:39:47 +0800
Subject: [PATCH 08/18] fix register logic

---
 contracts/Fluidex.sol  | 18 +++++++++++-------
 contracts/UserInfo.sol |  9 +++++++++
 2 files changed, 20 insertions(+), 7 deletions(-)
 create mode 100644 contracts/UserInfo.sol

diff --git a/contracts/Fluidex.sol b/contracts/Fluidex.sol
index f039235..121452c 100644
--- a/contracts/Fluidex.sol
+++ b/contracts/Fluidex.sol
@@ -14,6 +14,7 @@ import "hardhat/console.sol";
 import "./Utils.sol";
 
 import "./Storage.sol";
+import "./UserInfo.sol";
 import "./Config.sol";
 import "./Events.sol";
 
@@ -32,8 +33,8 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
     mapping(address => uint16) public tokenAddrToId;
 
     uint16 public userNum;
-    mapping(uint16 => address) public userIdToAddr;
-    mapping(address => uint16) public userAddrToId;
+    mapping(uint16 => UserInfo) public userIdToUserInfo;
+    mapping(bytes => uint16) public userBjjPubkeyToUserId;
 
     function initialize() external {}
 
@@ -69,12 +70,15 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
         returns (uint16)
     {
         userNum++;
-        require(userAddrToId[ethAddr] == 0, "user existed");
+        require(userBjjPubkeyToUserId[bjjPubkey] == 0, "user existed");
         require(userNum < USER_NUM_LIMIT, "user num limit reached");
 
         uint16 userId = userNum;
-        userIdToAddr[userId] = ethAddr;
-        userAddrToId[ethAddr] = userId;
+        userIdToUserInfo[userId] = UserInfo({
+            ethAddr: ethAddr,
+            bjjPubkey: bjjPubkey,
+        });
+        userBjjPubkeyToUserId[bjjPubkey] = userId;
         emit RegisterUser(ethAddr, userId, bjjPubkey);
         return userId;
     }
@@ -102,7 +106,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
         // You must `approve` the allowance before calling this method
 
         // TODO: check `to` format
-        if (userAddrToId[to] == 0) {
+        if (userBjjPubkeyToUserId[to] == 0) {
             registerUser(msg.sender, to);
         }
 
@@ -123,7 +127,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
         require(tokenId != 0, "invalid token");
 
         // TODO: check `to` format
-        if (userAddrToId[to] == 0) {
+        if (userBjjPubkeyToUserId[to] == 0) {
             registerUser(msg.sender, to);
         }
 
diff --git a/contracts/UserInfo.sol b/contracts/UserInfo.sol
new file mode 100644
index 0000000..dbc3f45
--- /dev/null
+++ b/contracts/UserInfo.sol
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity >=0.6.0 <0.8.0;
+
+/// @title Fluidex userinfo contract
+struct UserInfo {
+    address ethAddr;
+    bytes bjjPubkey;
+}
\ No newline at end of file

From b2eaae47659baeb8b9eca5aea94e9fd55ccd14c7 Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Thu, 20 May 2021 10:40:52 +0800
Subject: [PATCH 09/18] fix

---
 contracts/Fluidex.sol | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contracts/Fluidex.sol b/contracts/Fluidex.sol
index 121452c..8f00e87 100644
--- a/contracts/Fluidex.sol
+++ b/contracts/Fluidex.sol
@@ -76,7 +76,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
         uint16 userId = userNum;
         userIdToUserInfo[userId] = UserInfo({
             ethAddr: ethAddr,
-            bjjPubkey: bjjPubkey,
+            bjjPubkey: bjjPubkey
         });
         userBjjPubkeyToUserId[bjjPubkey] = userId;
         emit RegisterUser(ethAddr, userId, bjjPubkey);

From b852cf90d617ab73453086431a265f87c793c3de Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Thu, 20 May 2021 11:50:29 +0800
Subject: [PATCH 10/18] length check

---
 contracts/Fluidex.sol | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/contracts/Fluidex.sol b/contracts/Fluidex.sol
index 8f00e87..2b0464f 100644
--- a/contracts/Fluidex.sol
+++ b/contracts/Fluidex.sol
@@ -105,7 +105,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
     ) external payable {
         // You must `approve` the allowance before calling this method
 
-        // TODO: check `to` format
+        require(to.length == 32, "invalid bjjPubkey");
         if (userBjjPubkeyToUserId[to] == 0) {
             registerUser(msg.sender, to);
         }
@@ -126,7 +126,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
         uint16 tokenId = tokenAddrToId[address(token)];
         require(tokenId != 0, "invalid token");
 
-        // TODO: check `to` format
+        require(to.length == 32, "invalid bjjPubkey");
         if (userBjjPubkeyToUserId[to] == 0) {
             registerUser(msg.sender, to);
         }

From 27aaffc89e7b0411393e739e7898263f99974cc8 Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Thu, 20 May 2021 14:09:21 +0800
Subject: [PATCH 11/18] fix tobjj

---
 contracts/Events.sol     | 2 +-
 contracts/Fluidex.sol    | 2 +-
 contracts/Operations.sol | 3 ++-
 test/token.js            | 4 ++--
 4 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/contracts/Events.sol b/contracts/Events.sol
index 63b7b14..ffb4064 100644
--- a/contracts/Events.sol
+++ b/contracts/Events.sol
@@ -9,7 +9,7 @@ interface Events {
     event NewToken(address tokenAddr, uint16 tokenId);
     event NewTradingPair(uint16 baseTokenId, uint16 quoteTokenId);
     event RegisterUser(address ethAddr, uint16 userId, bytes bjjPubkey);
-    event Deposit(uint16 tokenId, address to, uint256 amount); // emit tokenId or tokenAddr?
+    event Deposit(uint16 tokenId, bytes to, uint256 amount); // emit tokenId or tokenAddr?
     event Withdraw(uint16 tokenId, address to, uint256 amount); // emit tokenId or tokenAddr?
 
     /// @notice New priority request event. Emitted when a request is placed into mapping
diff --git a/contracts/Fluidex.sol b/contracts/Fluidex.sol
index 2b0464f..01af754 100644
--- a/contracts/Fluidex.sol
+++ b/contracts/Fluidex.sol
@@ -85,7 +85,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
 
     // 0 tokenId means native ETH coin
     // TODO: zkSync uses uint128 for amount
-    function registerDeposit(uint16 tokenId, address to, uint256 amount) internal {
+    function registerDeposit(uint16 tokenId, bytes memory to, uint256 amount) internal {
         // Priority Queue request
         Operations.Deposit memory op =
             Operations.Deposit({
diff --git a/contracts/Operations.sol b/contracts/Operations.sol
index 6750300..61fa5e5 100644
--- a/contracts/Operations.sol
+++ b/contracts/Operations.sol
@@ -17,7 +17,8 @@ library Operations {
         uint32 accountId;
         uint16 tokenId;
         uint256 amount; // TODO: zkSync uses uint128 for amount
-        address owner;
+        // address owner;
+        bytes owner;
     }
 
     /// Serialize deposit pubdata
diff --git a/test/token.js b/test/token.js
index c472298..4f66830 100644
--- a/test/token.js
+++ b/test/token.js
@@ -51,7 +51,7 @@ describe("Fluidex", () => {
     await expect(
       fluidex
         .connect(acc2)
-        .depositERC20(erc20Mock.address, mockBjj, acc2addr, depositAmount)
+        .depositERC20(erc20Mock.address, mockBjj, depositAmount)
     )
       .to.emit(fluidex, "Deposit")
       .withArgs(tokenId, acc2addr, depositAmount);
@@ -71,7 +71,7 @@ describe("Fluidex", () => {
     await expect(
       fluidex
         .connect(acc2)
-        .depositETH(mockBjj, acc2addr, {value: depositAmount})
+        .depositETH(mockBjj, {value: depositAmount})
     )
       .to.emit(fluidex, "Deposit")
       .withArgs(0, acc2addr, depositAmount);

From aa1a1f3aeafae602608ad0b5e3bf5bbecc74022a Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Thu, 20 May 2021 14:20:14 +0800
Subject: [PATCH 12/18] update test

---
 test/token.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/token.js b/test/token.js
index 4f66830..e24b013 100644
--- a/test/token.js
+++ b/test/token.js
@@ -1,4 +1,5 @@
 const { expect } = require("chai");
+const { randomBytes } = require("@ethersproject/random");
 
 describe("Fluidex", () => {
   let fluidex;
@@ -7,6 +8,7 @@ describe("Fluidex", () => {
   let senderAddr;
   let acc2;
   let acc2addr;
+  const mockBjj = randomBytes(32);
   const initialBalance = 1000;
   const decimal = 2;
 
@@ -47,7 +49,6 @@ describe("Fluidex", () => {
     );
 
     // TODO: NewPriorityRequest event
-    const mockBjj = [];
     await expect(
       fluidex
         .connect(acc2)
@@ -67,7 +68,6 @@ describe("Fluidex", () => {
     const withdrawAmount = 300;
 
     // TODO: NewPriorityRequest event
-    const mockBjj = [];
     await expect(
       fluidex
         .connect(acc2)

From 7327b8394c1c354f2b2503f1eb9a09673df23df7 Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Thu, 20 May 2021 14:21:44 +0800
Subject: [PATCH 13/18] minor

---
 contracts/UserInfo.sol | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contracts/UserInfo.sol b/contracts/UserInfo.sol
index dbc3f45..7dd353d 100644
--- a/contracts/UserInfo.sol
+++ b/contracts/UserInfo.sol
@@ -6,4 +6,4 @@ pragma solidity >=0.6.0 <0.8.0;
 struct UserInfo {
     address ethAddr;
     bytes bjjPubkey;
-}
\ No newline at end of file
+}

From 45a00f07cc650582150ef365ac432876971462a2 Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Thu, 20 May 2021 14:34:59 +0800
Subject: [PATCH 14/18] minor

---
 test/token.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/token.js b/test/token.js
index e24b013..7f3f916 100644
--- a/test/token.js
+++ b/test/token.js
@@ -55,7 +55,7 @@ describe("Fluidex", () => {
         .depositERC20(erc20Mock.address, mockBjj, depositAmount)
     )
       .to.emit(fluidex, "Deposit")
-      .withArgs(tokenId, acc2addr, depositAmount);
+      .withArgs(tokenId, mockBjj, depositAmount);
     await expect(
       fluidex.withdrawERC20(erc20Mock.address, acc2addr, withdrawAmount)
     )
@@ -74,7 +74,7 @@ describe("Fluidex", () => {
         .depositETH(mockBjj, {value: depositAmount})
     )
       .to.emit(fluidex, "Deposit")
-      .withArgs(0, acc2addr, depositAmount);
+      .withArgs(0, mockBjj, depositAmount);
 
     await expect(
       fluidex.withdrawETH(acc2addr, withdrawAmount)

From 32da44ee5ce2c68de0b11a908918ff8f8b1f3e26 Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Thu, 20 May 2021 14:45:54 +0800
Subject: [PATCH 15/18] use bytes32

---
 contracts/Events.sol     |  4 ++--
 contracts/Fluidex.sol    | 12 +++++-------
 contracts/Operations.sol |  2 +-
 contracts/UserInfo.sol   |  2 +-
 4 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/contracts/Events.sol b/contracts/Events.sol
index ffb4064..a088c96 100644
--- a/contracts/Events.sol
+++ b/contracts/Events.sol
@@ -8,8 +8,8 @@ import "./Operations.sol";
 interface Events {
     event NewToken(address tokenAddr, uint16 tokenId);
     event NewTradingPair(uint16 baseTokenId, uint16 quoteTokenId);
-    event RegisterUser(address ethAddr, uint16 userId, bytes bjjPubkey);
-    event Deposit(uint16 tokenId, bytes to, uint256 amount); // emit tokenId or tokenAddr?
+    event RegisterUser(address ethAddr, uint16 userId, bytes32 bjjPubkey);
+    event Deposit(uint16 tokenId, bytes32 to, uint256 amount); // emit tokenId or tokenAddr?
     event Withdraw(uint16 tokenId, address to, uint256 amount); // emit tokenId or tokenAddr?
 
     /// @notice New priority request event. Emitted when a request is placed into mapping
diff --git a/contracts/Fluidex.sol b/contracts/Fluidex.sol
index 01af754..c883679 100644
--- a/contracts/Fluidex.sol
+++ b/contracts/Fluidex.sol
@@ -34,7 +34,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
 
     uint16 public userNum;
     mapping(uint16 => UserInfo) public userIdToUserInfo;
-    mapping(bytes => uint16) public userBjjPubkeyToUserId;
+    mapping(bytes32 => uint16) public userBjjPubkeyToUserId;
 
     function initialize() external {}
 
@@ -65,7 +65,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
     }
 
     // TODO: check signature?
-    function registerUser(address ethAddr, bytes memory bjjPubkey)
+    function registerUser(address ethAddr, bytes32 bjjPubkey)
         internal
         returns (uint16)
     {
@@ -85,7 +85,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
 
     // 0 tokenId means native ETH coin
     // TODO: zkSync uses uint128 for amount
-    function registerDeposit(uint16 tokenId, bytes memory to, uint256 amount) internal {
+    function registerDeposit(uint16 tokenId, bytes32 to, uint256 amount) internal {
         // Priority Queue request
         Operations.Deposit memory op =
             Operations.Deposit({
@@ -101,11 +101,10 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
 
     /// @param to the L2 address of the deposit target.
     function depositETH(
-        bytes calldata to // L2 bjjPubkey
+        bytes32 to // L2 bjjPubkey
     ) external payable {
         // You must `approve` the allowance before calling this method
 
-        require(to.length == 32, "invalid bjjPubkey");
         if (userBjjPubkeyToUserId[to] == 0) {
             registerUser(msg.sender, to);
         }
@@ -118,7 +117,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
     /// @param amount the deposit amount.
     function depositERC20(
         IERC20 token,
-        bytes calldata to, // L2 bjjPubkey
+        bytes32 to, // L2 bjjPubkey
         uint128 amount
     ) external nonReentrant {
         // You must `approve` the allowance before calling this method
@@ -126,7 +125,6 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
         uint16 tokenId = tokenAddrToId[address(token)];
         require(tokenId != 0, "invalid token");
 
-        require(to.length == 32, "invalid bjjPubkey");
         if (userBjjPubkeyToUserId[to] == 0) {
             registerUser(msg.sender, to);
         }
diff --git a/contracts/Operations.sol b/contracts/Operations.sol
index 61fa5e5..d8c3605 100644
--- a/contracts/Operations.sol
+++ b/contracts/Operations.sol
@@ -18,7 +18,7 @@ library Operations {
         uint16 tokenId;
         uint256 amount; // TODO: zkSync uses uint128 for amount
         // address owner;
-        bytes owner;
+        bytes32 owner;
     }
 
     /// Serialize deposit pubdata
diff --git a/contracts/UserInfo.sol b/contracts/UserInfo.sol
index 7dd353d..aa602a8 100644
--- a/contracts/UserInfo.sol
+++ b/contracts/UserInfo.sol
@@ -5,5 +5,5 @@ pragma solidity >=0.6.0 <0.8.0;
 /// @title Fluidex userinfo contract
 struct UserInfo {
     address ethAddr;
-    bytes bjjPubkey;
+    bytes32 bjjPubkey;
 }

From ec55b12e7cf9fb73684c26c20a9a2245e3783966 Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Thu, 20 May 2021 15:19:51 +0800
Subject: [PATCH 16/18] minor

---
 test/token.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/test/token.js b/test/token.js
index 7f3f916..46863be 100644
--- a/test/token.js
+++ b/test/token.js
@@ -56,6 +56,7 @@ describe("Fluidex", () => {
     )
       .to.emit(fluidex, "Deposit")
       .withArgs(tokenId, mockBjj, depositAmount);
+
     await expect(
       fluidex.withdrawERC20(erc20Mock.address, acc2addr, withdrawAmount)
     )

From 8debaa8d26f07b6e0c806cc13cc9054eca888acf Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Thu, 20 May 2021 15:31:13 +0800
Subject: [PATCH 17/18] minor

---
 contracts/Fluidex.sol | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/contracts/Fluidex.sol b/contracts/Fluidex.sol
index c883679..3e24194 100644
--- a/contracts/Fluidex.sol
+++ b/contracts/Fluidex.sol
@@ -65,10 +65,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
     }
 
     // TODO: check signature?
-    function registerUser(address ethAddr, bytes32 bjjPubkey)
-        internal
-        returns (uint16)
-    {
+    function registerUser(address ethAddr, bytes32 bjjPubkey) internal {
         userNum++;
         require(userBjjPubkeyToUserId[bjjPubkey] == 0, "user existed");
         require(userNum < USER_NUM_LIMIT, "user num limit reached");
@@ -80,7 +77,6 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
         });
         userBjjPubkeyToUserId[bjjPubkey] = userId;
         emit RegisterUser(ethAddr, userId, bjjPubkey);
-        return userId;
     }
 
     // 0 tokenId means native ETH coin

From f3113f269fd4bf957226cb8b53bee547a994f2b4 Mon Sep 17 00:00:00 2001
From: HAOYUatHZ <haoyu@protonmail.com>
Date: Thu, 20 May 2021 15:35:29 +0800
Subject: [PATCH 18/18] use string

---
 contracts/Events.sol     |  4 ++--
 contracts/Fluidex.sol    | 10 +++++-----
 contracts/Operations.sol |  2 +-
 contracts/UserInfo.sol   |  2 +-
 test/token.js            |  2 +-
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/contracts/Events.sol b/contracts/Events.sol
index a088c96..00201ad 100644
--- a/contracts/Events.sol
+++ b/contracts/Events.sol
@@ -8,8 +8,8 @@ import "./Operations.sol";
 interface Events {
     event NewToken(address tokenAddr, uint16 tokenId);
     event NewTradingPair(uint16 baseTokenId, uint16 quoteTokenId);
-    event RegisterUser(address ethAddr, uint16 userId, bytes32 bjjPubkey);
-    event Deposit(uint16 tokenId, bytes32 to, uint256 amount); // emit tokenId or tokenAddr?
+    event RegisterUser(address ethAddr, uint16 userId, string bjjPubkey);
+    event Deposit(uint16 tokenId, string to, uint256 amount); // emit tokenId or tokenAddr?
     event Withdraw(uint16 tokenId, address to, uint256 amount); // emit tokenId or tokenAddr?
 
     /// @notice New priority request event. Emitted when a request is placed into mapping
diff --git a/contracts/Fluidex.sol b/contracts/Fluidex.sol
index 3e24194..faf2191 100644
--- a/contracts/Fluidex.sol
+++ b/contracts/Fluidex.sol
@@ -34,7 +34,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
 
     uint16 public userNum;
     mapping(uint16 => UserInfo) public userIdToUserInfo;
-    mapping(bytes32 => uint16) public userBjjPubkeyToUserId;
+    mapping(string => uint16) public userBjjPubkeyToUserId;
 
     function initialize() external {}
 
@@ -65,7 +65,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
     }
 
     // TODO: check signature?
-    function registerUser(address ethAddr, bytes32 bjjPubkey) internal {
+    function registerUser(address ethAddr, string memory bjjPubkey) internal {
         userNum++;
         require(userBjjPubkeyToUserId[bjjPubkey] == 0, "user existed");
         require(userNum < USER_NUM_LIMIT, "user num limit reached");
@@ -81,7 +81,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
 
     // 0 tokenId means native ETH coin
     // TODO: zkSync uses uint128 for amount
-    function registerDeposit(uint16 tokenId, bytes32 to, uint256 amount) internal {
+    function registerDeposit(uint16 tokenId, string memory to, uint256 amount) internal {
         // Priority Queue request
         Operations.Deposit memory op =
             Operations.Deposit({
@@ -97,7 +97,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
 
     /// @param to the L2 address of the deposit target.
     function depositETH(
-        bytes32 to // L2 bjjPubkey
+        string calldata to // L2 bjjPubkey
     ) external payable {
         // You must `approve` the allowance before calling this method
 
@@ -113,7 +113,7 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
     /// @param amount the deposit amount.
     function depositERC20(
         IERC20 token,
-        bytes32 to, // L2 bjjPubkey
+        string calldata to, // L2 bjjPubkey
         uint128 amount
     ) external nonReentrant {
         // You must `approve` the allowance before calling this method
diff --git a/contracts/Operations.sol b/contracts/Operations.sol
index d8c3605..d360c4d 100644
--- a/contracts/Operations.sol
+++ b/contracts/Operations.sol
@@ -18,7 +18,7 @@ library Operations {
         uint16 tokenId;
         uint256 amount; // TODO: zkSync uses uint128 for amount
         // address owner;
-        bytes32 owner;
+        string owner;
     }
 
     /// Serialize deposit pubdata
diff --git a/contracts/UserInfo.sol b/contracts/UserInfo.sol
index aa602a8..5ae49a0 100644
--- a/contracts/UserInfo.sol
+++ b/contracts/UserInfo.sol
@@ -5,5 +5,5 @@ pragma solidity >=0.6.0 <0.8.0;
 /// @title Fluidex userinfo contract
 struct UserInfo {
     address ethAddr;
-    bytes32 bjjPubkey;
+    string bjjPubkey;
 }
diff --git a/test/token.js b/test/token.js
index 46863be..b396aa7 100644
--- a/test/token.js
+++ b/test/token.js
@@ -8,7 +8,7 @@ describe("Fluidex", () => {
   let senderAddr;
   let acc2;
   let acc2addr;
-  const mockBjj = randomBytes(32);
+  const mockBjj = "randomBytes(32)";
   const initialBalance = 1000;
   const decimal = 2;