Skip to content
3 changes: 2 additions & 1 deletion contracts/Events.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import "./Operations.sol";
interface Events {
event NewToken(address tokenAddr, uint16 tokenId);
event NewTradingPair(uint16 baseTokenId, uint16 quoteTokenId);
event Deposit(uint16 tokenId, address 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
Expand Down
43 changes: 37 additions & 6 deletions contracts/Fluidex.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import "hardhat/console.sol";
import "./Utils.sol";

import "./Storage.sol";
import "./UserInfo.sol";
import "./Config.sol";
import "./Events.sol";

Expand All @@ -25,11 +26,16 @@ 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;
mapping(address => uint16) public tokenAddrToId;

uint16 public userNum;
mapping(uint16 => UserInfo) public userIdToUserInfo;
mapping(string => uint16) public userBjjPubkeyToUserId;

function initialize() external {}

function addToken(address tokenAddr)
Expand Down Expand Up @@ -58,9 +64,24 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
emit NewTradingPair(baseTokenId, quoteTokenId);
}

// TODO: check signature?
function registerUser(address ethAddr, string memory bjjPubkey) internal {
userNum++;
require(userBjjPubkeyToUserId[bjjPubkey] == 0, "user existed");
require(userNum < USER_NUM_LIMIT, "user num limit reached");

uint16 userId = userNum;
userIdToUserInfo[userId] = UserInfo({
ethAddr: ethAddr,
bjjPubkey: bjjPubkey
});
userBjjPubkeyToUserId[bjjPubkey] = userId;
emit RegisterUser(ethAddr, userId, bjjPubkey);
}

// 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, string memory to, uint256 amount) internal {
// Priority Queue request
Operations.Deposit memory op =
Operations.Deposit({
Expand All @@ -75,10 +96,15 @@ 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(
string calldata to // L2 bjjPubkey
) external payable {
// You must `approve` the allowance before calling this method
require(to != address(0), "invalid address");

if (userBjjPubkeyToUserId[to] == 0) {
registerUser(msg.sender, to);
}

// 0 tokenId means native ETH coin
registerDeposit(0, to, msg.value);
}
Expand All @@ -87,13 +113,18 @@ contract Fluidex is ReentrancyGuard, Storage, Config, Events, Ownable {
/// @param amount the deposit amount.
function depositERC20(
IERC20 token,
address to, // TODO: change to L2 address
string 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 (userBjjPubkeyToUserId[to] == 0) {
registerUser(msg.sender, to);
}

uint256 balanceBeforeDeposit = token.balanceOf(address(this));
token.safeTransferFrom(msg.sender, address(this), amount);
uint256 balanceAfterDeposit = token.balanceOf(address(this));
Expand Down
3 changes: 2 additions & 1 deletion contracts/Operations.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ library Operations {
uint32 accountId;
uint16 tokenId;
uint256 amount; // TODO: zkSync uses uint128 for amount
address owner;
// address owner;
string owner;
}

/// Serialize deposit pubdata
Expand Down
9 changes: 9 additions & 0 deletions contracts/UserInfo.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/// @title Fluidex userinfo contract
struct UserInfo {
address ethAddr;
string bjjPubkey;
}
11 changes: 7 additions & 4 deletions test/token.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const { expect } = require("chai");
const { randomBytes } = require("@ethersproject/random");

describe("Fluidex", () => {
let fluidex;
Expand All @@ -7,6 +8,7 @@ describe("Fluidex", () => {
let senderAddr;
let acc2;
let acc2addr;
const mockBjj = "randomBytes(32)";
const initialBalance = 1000;
const decimal = 2;

Expand Down Expand Up @@ -50,10 +52,11 @@ describe("Fluidex", () => {
await expect(
fluidex
.connect(acc2)
.depositERC20(erc20Mock.address, acc2addr, depositAmount)
.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)
)
Expand All @@ -69,10 +72,10 @@ describe("Fluidex", () => {
await expect(
fluidex
.connect(acc2)
.depositETH(acc2addr, {value: depositAmount})
.depositETH(mockBjj, {value: depositAmount})
)
.to.emit(fluidex, "Deposit")
.withArgs(0, acc2addr, depositAmount);
.withArgs(0, mockBjj, depositAmount);

await expect(
fluidex.withdrawETH(acc2addr, withdrawAmount)
Expand Down