Skip to content

refactor: move event to delegate and fix erc20 #42

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 76 additions & 56 deletions contracts/FluiDex.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,18 @@ import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "hardhat/console.sol"; // for debugging

import "./Events.sol";
import "./IFluiDex.sol";
import "./IVerifier.sol";

/**
* @title FluiDexDemo
*/
contract FluiDexDemo is
AccessControl,
Events,
IFluiDex,
Ownable,
ReentrancyGuard
{
contract FluiDexDemo is AccessControl, IFluiDex, Ownable, ReentrancyGuard {
using SafeERC20 for IERC20;

bytes32 public constant PLUGIN_ADMIN_ROLE = keccak256("PLUGIN_ADMIN_ROLE");
bytes32 public constant TOKEN_ADMIN_ROLE = keccak256("TOKEN_ADMIN_ROLE");
bytes32 public constant DELEGATE_ROLE = keccak256("DELEGATE_ROLE");

enum BlockState {
Empty,
Committed,
Verified
}

struct UserInfo {
address ethAddr;
bytes32 bjjPubkey;
}

/// hard limit for ERC20 tokens
uint16 constant TOKEN_NUM_LIMIT = 65535;
/// hard limit for users
Expand All @@ -66,10 +47,8 @@ contract FluiDexDemo is
GENESIS_ROOT = _genesis_root;
verifier = _verifier;
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setRoleAdmin(TOKEN_ADMIN_ROLE, DEFAULT_ADMIN_ROLE);
_setRoleAdmin(PLUGIN_ADMIN_ROLE, DEFAULT_ADMIN_ROLE);
_setRoleAdmin(DELEGATE_ROLE, DEFAULT_ADMIN_ROLE);
grantRole(TOKEN_ADMIN_ROLE, msg.sender);
grantRole(PLUGIN_ADMIN_ROLE, msg.sender);
grantRole(DELEGATE_ROLE, msg.sender);
}
Expand All @@ -91,14 +70,13 @@ contract FluiDexDemo is
* @param tokenAddr the ERC20 token address
* @return the new ERC20 token tokenId
*/
function addToken(address origin, address tokenAddr)
function addToken(address tokenAddr)
external
override
nonReentrant
onlyRole(DELEGATE_ROLE)
returns (uint16)
{
require(hasRole(TOKEN_ADMIN_ROLE, origin));
require(tokenAddrToId[tokenAddr] == 0, "token existed");
tokenNum++;
require(tokenNum < TOKEN_NUM_LIMIT, "token num limit reached");
Expand All @@ -107,64 +85,65 @@ contract FluiDexDemo is
tokenIdToAddr[tokenId] = tokenAddr;
tokenAddrToId[tokenAddr] = tokenId;

emit NewToken(origin, tokenAddr, tokenId);
return tokenId;
}

/**
* @param to the L2 address (bjjPubkey) of the deposit target.
*/
function depositETH(address origin, bytes32 to)
external
payable
override
orCreateUser(origin, to)
onlyRole(DELEGATE_ROLE)
{
emit Deposit(ETH_ID, to, msg.value);
}
function depositETH(bytes32 to)
external
payable
override
onlyRole(DELEGATE_ROLE)
{}

/**
* @param to the L2 address (bjjPubkey) of the deposit target.
* @param amount the deposit amount.
*/
function depositERC20(
address origin,
IERC20 token,
bytes32 to,
uint128 amount
) external override nonReentrant tokenExist(token) orCreateUser(origin, to) {
uint16 tokenId = tokenAddrToId[address(token)];
function depositERC20(IERC20 token, uint256 amount)
external
override
nonReentrant
tokenExist(token)
onlyRole(DELEGATE_ROLE)
returns (uint16 tokenId, uint256 realAmount)
{
tokenId = tokenAddrToId[address(token)];

uint256 balanceBeforeDeposit = token.balanceOf(address(this));
token.safeTransferFrom(origin, address(this), amount);
token.safeTransferFrom(msg.sender, address(this), amount);
uint256 balanceAfterDeposit = token.balanceOf(address(this));
uint256 realAmount = balanceAfterDeposit - balanceBeforeDeposit;
emit Deposit(tokenId, to, realAmount);
realAmount = balanceAfterDeposit - balanceBeforeDeposit;
}

/**
* @dev this won't verify the pubkey
* @param ethAddr the L1 address
* @param bjjPubkey the L2 address (bjjPubkey)
*/
function registerUser(address ethAddr, bytes32 bjjPubkey) public {
function registerUser(address ethAddr, bytes32 bjjPubkey)
external
override
onlyRole(DELEGATE_ROLE)
returns (uint16 userId)
{
require(userBjjPubkeyToUserId[bjjPubkey] == 0, "user existed");
userNum++;
require(userNum < USER_NUM_LIMIT, "user num limit reached");

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

function getBlockStateByBlockId(uint256 _block_id)
public
external
view
override
returns (BlockState)
{
return block_states[_block_id];
Expand Down Expand Up @@ -230,13 +209,54 @@ contract FluiDexDemo is
}

/**
* @dev create a user if not exist
* @param bjjPubkey the L2 address (bjjPubkey)
* @param tokenId tokenId
* @return tokenAddr
*/
modifier orCreateUser(address origin, bytes32 bjjPubkey) {
if (userBjjPubkeyToUserId[bjjPubkey] == 0) {
registerUser(origin, bjjPubkey);
}
_;
function getTokenAddr(uint16 tokenId)
external
view
override
returns (address)
{
return tokenIdToAddr[tokenId];
}

/**
* @param tokenAddr tokenAddr
* @return tokenId
*/
function getTokenId(address tokenAddr)
external
view
override
returns (uint16)
{
return tokenAddrToId[tokenAddr];
}

/**
* @param userId userId
* @return UserInfo
*/
function getUserInfo(uint16 userId)
external
view
override
returns (UserInfo memory)
{
return userIdToUserInfo[userId];
}

/**
* @param bjjPubkey user's pubkey
* @return userId, returns 0 if not exist
*/
function getUserId(bytes32 bjjPubkey)
external
view
override
returns (uint16)
{
return userBjjPubkeyToUserId[bjjPubkey];
}
}
65 changes: 55 additions & 10 deletions contracts/FluiDexDelegate.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,31 @@ pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/AccessControl.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./Events.sol";
import "./IFluiDex.sol";
import "./IFluiDexDelegate.sol";

contract FluiDexDelegate is AccessControl, IFluiDexDelegate, ReentrancyGuard {
contract FluiDexDelegate is
AccessControl,
Events,
IFluiDexDelegate,
ReentrancyGuard
{
using SafeERC20 for IERC20;

bytes32 public constant TOKEN_ADMIN_ROLE = keccak256("TOKEN_ADMIN_ROLE");

/// use 0 representing ETH in tokenId
uint16 constant ETH_ID = 0;

IFluiDex target;
event TargetChange(IFluiDex prev, IFluiDex now);

constructor(IFluiDex _target) {
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setRoleAdmin(TOKEN_ADMIN_ROLE, DEFAULT_ADMIN_ROLE);
grantRole(TOKEN_ADMIN_ROLE, msg.sender);
target = _target;
}

Expand All @@ -32,21 +47,29 @@ contract FluiDexDelegate is AccessControl, IFluiDexDelegate, ReentrancyGuard {
/**
* @notice request to add a new ERC20 token
* @param tokenAddr the ERC20 token address
* @return the new ERC20 token tokenId
* @return tokenId the new ERC20 token tokenId
*/
function addToken(address tokenAddr)
external
function addToken(address tokenAddr)
external
override
returns (uint16)
onlyRole(TOKEN_ADMIN_ROLE)
returns (uint16 tokenId)
{
return target.addToken(msg.sender, tokenAddr);
tokenId = target.addToken(tokenAddr);
emit NewToken(msg.sender, tokenAddr, tokenId);
}

/**
* @param to the L2 address (bjjPubkey) of the deposit target.
*/
function depositETH(bytes32 to) external payable override {
target.depositETH{value: msg.value}(msg.sender, to);
function depositETH(bytes32 to)
external
payable
override
orCreateUser(msg.sender, to)
{
target.depositETH{value: msg.value}(to);
emit Deposit(ETH_ID, to, msg.value);
}

/**
Expand All @@ -56,9 +79,19 @@ contract FluiDexDelegate is AccessControl, IFluiDexDelegate, ReentrancyGuard {
function depositERC20(
IERC20 token,
bytes32 to,
uint128 amount
uint256 amount
) external override {
target.depositERC20(msg.sender, token, to, amount);
uint256 balanceBeforeDeposit = token.balanceOf(address(this));
token.safeTransferFrom(msg.sender, address(this), amount);
uint256 balanceAfterDeposit = token.balanceOf(address(this));
uint256 realAmount = balanceAfterDeposit - balanceBeforeDeposit;
token.safeIncreaseAllowance(address(target), realAmount);

(uint16 tokenId, uint256 finalAmount) = target.depositERC20(
token,
realAmount
);
emit Deposit(tokenId, to, finalAmount);
}

/**
Expand All @@ -75,4 +108,16 @@ contract FluiDexDelegate is AccessControl, IFluiDexDelegate, ReentrancyGuard {
) external override returns (bool) {
return target.submitBlock(_block_id, _public_inputs, _serialized_proof);
}

/**
* @dev create a user if not exist
* @param bjjPubkey the L2 address (bjjPubkey)
*/
modifier orCreateUser(address origin, bytes32 bjjPubkey) {
if (target.getUserId(bjjPubkey) == 0) {
uint16 userId = target.registerUser(origin, bjjPubkey);
emit RegisterUser(msg.sender, userId, bjjPubkey);
}
_;
}
}
Loading