Skip to content

Commit

Permalink
Customizable zkBob pools for different tokens (#66)
Browse files Browse the repository at this point in the history
  • Loading branch information
k1rill-fedoseev committed Jun 5, 2023
1 parent 0eb49ae commit e7e2255
Show file tree
Hide file tree
Showing 27 changed files with 864 additions and 833 deletions.
14 changes: 10 additions & 4 deletions script/scripts/Env.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ pragma solidity 0.8.15;

import "forge-std/Script.sol";

enum PoolType {
BOB,
ETH,
USDC,
ERC20
}

// common
address constant deployer = 0x39F0bD56c1439a22Ee90b4972c16b7868D161981;
address constant admin = 0xd4a3D9Ca00fa1fD8833D560F9217458E61c446d8;
Expand All @@ -17,7 +24,9 @@ bytes32 constant bobSalt = bytes32(uint256(285834900769));

// zkbob
uint256 constant zkBobPoolId = 0; // 0 is reserved for Polygon MVP pool, do not use for other deployments
PoolType constant zkBobPoolType = PoolType.BOB;
string constant zkBobVerifiers = "prodV1";
address constant zkBobToken = 0xB0B195aEFA3650A6908f15CdaC7D92F8a5791B0B;
uint256 constant zkBobInitialRoot = 11469701942666298368112882412133877458305516134926649826543144744382391691533;
address constant zkBobRelayer = 0xc2c4AD59B78F4A0aFD0CDB8133E640Db08Fa5b90;
address constant zkBobRelayerFeeReceiver = 0x758768EC473279c4B1Aa61FA5450745340D4B17d;
Expand All @@ -31,6 +40,7 @@ uint256 constant zkBobDailyUserDirectDepositCap = 0;
uint256 constant zkBobDirectDepositCap = 0;
uint256 constant zkBobDirectDepositFee = 0.1 gwei;
uint256 constant zkBobDirectDepositTimeout = 1 days;
address constant permit2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;

// new zkbob impl
address constant zkBobPool = 0x72e6B59D4a90ab232e55D4BB7ed2dD17494D62fB;
Expand All @@ -52,7 +62,3 @@ address constant uniV3Quoter = 0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6;
uint24 constant fee0 = 500;
address constant usdc = 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174;
uint24 constant fee1 = 500;

// zkbobpool eth
address constant weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address constant permit2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;
9 changes: 4 additions & 5 deletions script/scripts/Local.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import "./Env.s.sol";
import "../../test/shared/EIP2470.t.sol";
import "../../src/BobToken.sol";
import "../../src/proxy/EIP1967Proxy.sol";
import "../../src/zkbob/ZkBobPool.sol";
import "../../src/zkbob/ZkBobPoolERC20.sol";
import "../../src/zkbob/ZkBobPoolBOB.sol";
import "../../src/zkbob/manager/MutableOperatorManager.sol";
import "../../src/zkbob/ZkBobDirectDepositQueue.sol";

Expand Down Expand Up @@ -44,7 +43,7 @@ contract DeployLocal is Script {
EIP1967Proxy poolProxy = new EIP1967Proxy(tx.origin, mockImpl, "");
EIP1967Proxy queueProxy = new EIP1967Proxy(tx.origin, mockImpl, "");

ZkBobPoolERC20 poolImpl = new ZkBobPoolERC20(
ZkBobPoolBOB poolImpl = new ZkBobPoolBOB(
zkBobPoolId,
address(bob),
transferVerifier,
Expand All @@ -66,9 +65,9 @@ contract DeployLocal is Script {
);
poolProxy.upgradeToAndCall(address(poolImpl), initData);
}
ZkBobPoolERC20 pool = ZkBobPoolERC20(address(poolProxy));
ZkBobPoolBOB pool = ZkBobPoolBOB(address(poolProxy));

ZkBobDirectDepositQueue queueImpl = new ZkBobDirectDepositQueue(address(pool), address(bob));
ZkBobDirectDepositQueue queueImpl = new ZkBobDirectDepositQueue(address(pool), address(bob), 1_000_000_000);
queueProxy.upgradeTo(address(queueImpl));
ZkBobDirectDepositQueue queue = ZkBobDirectDepositQueue(address(queueProxy));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,15 @@ pragma solidity 0.8.15;

import "forge-std/Script.sol";
import "./Env.s.sol";
import "../../src/proxy/EIP1967Proxy.sol";
import "../../src/zkbob/ZkBobPool.sol";
import "../../src/zkbob/manager/MutableOperatorManager.sol";
import "../../src/zkbob/ZkBobPoolERC20.sol";
import "../../src/zkbob/ZkBobPoolBOB.sol";

contract DeployNewZkBobPoolERC20Impl is Script {
contract DeployNewZkBobPoolBOBImpl is Script {
function run() external {
vm.startBroadcast();

ZkBobPoolERC20 pool = ZkBobPoolERC20(zkBobPool);
ZkBobPoolBOB pool = ZkBobPoolBOB(zkBobPool);

ZkBobPoolERC20 impl = new ZkBobPoolERC20(
ZkBobPoolBOB impl = new ZkBobPoolBOB(
pool.pool_id(),
pool.token(),
pool.transfer_verifier(),
Expand Down
3 changes: 0 additions & 3 deletions script/scripts/NewZkBobPoolETHImpl.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ pragma solidity 0.8.15;

import "forge-std/Script.sol";
import "./Env.s.sol";
import "../../src/proxy/EIP1967Proxy.sol";
import "../../src/zkbob/ZkBobPool.sol";
import "../../src/zkbob/manager/MutableOperatorManager.sol";
import "../../src/zkbob/ZkBobPoolETH.sol";

contract DeployNewZkBobPoolETHImpl is Script {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ pragma solidity 0.8.15;
import "forge-std/Script.sol";
import "./Env.s.sol";
import "../../src/proxy/EIP1967Proxy.sol";
import "../../src/zkbob/ZkBobPool.sol";
import "../../src/zkbob/ZkBobDirectDepositQueue.sol";
import "../../src/zkbob/ZkBobDirectDepositQueueETH.sol";
import "../../src/zkbob/manager/MutableOperatorManager.sol";
import "../../src/zkbob/ZkBobPoolBOB.sol";
import "../../src/zkbob/ZkBobPoolETH.sol";
import "../../src/zkbob/ZkBobPoolUSDC.sol";
import "../../src/zkbob/ZkBobPoolERC20.sol";

contract DeployZkBobPoolERC20 is Script {
contract DeployZkBobPool is Script {
function run() external {
vm.startBroadcast();

Expand All @@ -33,14 +36,39 @@ contract DeployZkBobPoolERC20 is Script {
EIP1967Proxy poolProxy = new EIP1967Proxy(tx.origin, mockImpl, "");
EIP1967Proxy queueProxy = new EIP1967Proxy(tx.origin, mockImpl, "");

ZkBobPoolERC20 poolImpl = new ZkBobPoolERC20(
zkBobPoolId,
bobVanityAddr,
transferVerifier,
treeVerifier,
batchDepositVerifier,
address(queueProxy)
);
ZkBobPool poolImpl;
if (zkBobPoolType == PoolType.ETH) {
poolImpl = new ZkBobPoolETH(
zkBobPoolId, zkBobToken,
transferVerifier, treeVerifier, batchDepositVerifier,
address(queueProxy), permit2
);
} else if (zkBobPoolType == PoolType.BOB) {
poolImpl = new ZkBobPoolBOB(
zkBobPoolId, zkBobToken,
transferVerifier, treeVerifier, batchDepositVerifier,
address(queueProxy)
);
} else if (zkBobPoolType == PoolType.USDC) {
poolImpl = new ZkBobPoolUSDC(
zkBobPoolId, zkBobToken,
transferVerifier, treeVerifier, batchDepositVerifier,
address(queueProxy)
);
} else if (zkBobPoolType == PoolType.ERC20) {
uint8 decimals = IERC20Metadata(zkBobToken).decimals();
uint256 denominator = decimals > 9 ? 10 ** (decimals - 9) : 1;
uint256 precision = decimals > 9 ? 1_000_000_000 : 10 ** decimals;
poolImpl = new ZkBobPoolERC20(
zkBobPoolId, zkBobToken,
transferVerifier, treeVerifier, batchDepositVerifier,
address(queueProxy), permit2,
denominator, precision
);
} else {
revert("Unknown pool type");
}

bytes memory initData = abi.encodeWithSelector(
ZkBobPool.initialize.selector,
zkBobInitialRoot,
Expand All @@ -53,9 +81,14 @@ contract DeployZkBobPoolERC20 is Script {
zkBobDirectDepositCap
);
poolProxy.upgradeToAndCall(address(poolImpl), initData);
ZkBobPoolERC20 pool = ZkBobPoolERC20(address(poolProxy));
ZkBobPool pool = ZkBobPool(address(poolProxy));

ZkBobDirectDepositQueue queueImpl = new ZkBobDirectDepositQueue(address(pool), bobVanityAddr);
ZkBobDirectDepositQueue queueImpl;
if (zkBobPoolType == PoolType.ETH) {
queueImpl = new ZkBobDirectDepositQueueETH(address(pool), zkBobToken, pool.denominator());
} else {
queueImpl = new ZkBobDirectDepositQueue(address(pool), zkBobToken, pool.denominator());
}
queueProxy.upgradeTo(address(queueImpl));
ZkBobDirectDepositQueue queue = ZkBobDirectDepositQueue(address(queueProxy));

Expand Down
98 changes: 0 additions & 98 deletions script/scripts/ZkBobPoolETH.s.sol

This file was deleted.

18 changes: 18 additions & 0 deletions src/interfaces/IUSDCPermit.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: CC0-1.0

pragma solidity 0.8.15;

interface IUSDCPermit {
function transferWithAuthorization(
address from,
address to,
uint256 value,
uint256 validAfter,
uint256 validBefore,
bytes32 nonce,
uint8 v,
bytes32 r,
bytes32 s
)
external;
}
9 changes: 0 additions & 9 deletions src/utils/Sacrifice.sol

This file was deleted.

13 changes: 9 additions & 4 deletions src/utils/UniswapV3Seller.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import "@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol"
import "@uniswap/v3-periphery/contracts/interfaces/IQuoter.sol";
import "@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol";
import "../interfaces/ITokenSeller.sol";
import "./Sacrifice.sol";

/**
* @title UniswapV3Seller
Expand Down Expand Up @@ -56,7 +55,9 @@ contract UniswapV3Seller is ITokenSeller {

uint256 amountOut = swapRouter.exactInput(
ISwapRouter.ExactInputParams({
path: abi.encodePacked(token0, fee0, token1, fee1, WETH),
path: token1 == address(0)
? abi.encodePacked(token0, fee0, WETH)
: abi.encodePacked(token0, fee0, token1, fee1, WETH),
recipient: address(this),
deadline: block.timestamp,
amountIn: _amount,
Expand All @@ -65,7 +66,8 @@ contract UniswapV3Seller is ITokenSeller {
);
WETH.withdraw(amountOut);
if (!payable(_receiver).send(amountOut)) {
new Sacrifice{value: amountOut}(_receiver);
WETH.deposit{value: amountOut}();
WETH.transfer(_receiver, amountOut);
}
uint256 remainingBalance = IERC20(token0).balanceOf(address(this));
if (remainingBalance + _amount > balance) {
Expand All @@ -82,6 +84,9 @@ contract UniswapV3Seller is ITokenSeller {
* @return received eth amount.
*/
function quoteSellForETH(uint256 _amount) external returns (uint256) {
return quoter.quoteExactInput(abi.encodePacked(token0, fee0, token1, fee1, WETH), _amount);
bytes memory path = token1 == address(0)
? abi.encodePacked(token0, fee0, WETH)
: abi.encodePacked(token0, fee0, token1, fee1, WETH);
return quoter.quoteExactInput(path, _amount);
}
}
6 changes: 4 additions & 2 deletions src/zkbob/ZkBobDirectDepositQueue.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ contract ZkBobDirectDepositQueue is IZkBobDirectDeposits, IZkBobDirectDepositQue
using SafeERC20 for IERC20;

uint256 internal constant R = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
uint256 internal constant TOKEN_DENOMINATOR = 1_000_000_000;
uint256 internal constant MAX_NUMBER_OF_DIRECT_DEPOSITS = 16;
bytes4 internal constant MESSAGE_PREFIX_DIRECT_DEPOSIT_V1 = 0x00000001;

uint256 internal immutable TOKEN_DENOMINATOR;

address public immutable token;
uint256 public immutable pool_id;
address public immutable pool;
Expand All @@ -50,10 +51,11 @@ contract ZkBobDirectDepositQueue is IZkBobDirectDeposits, IZkBobDirectDepositQue
event RefundDirectDeposit(uint256 indexed nonce, address receiver, uint256 amount);
event CompleteDirectDepositBatch(uint256[] indices);

constructor(address _pool, address _token) {
constructor(address _pool, address _token, uint256 _denominator) {
require(Address.isContract(_token), "ZkBobDirectDepositQueue: not a contract");
pool = _pool;
token = _token;
TOKEN_DENOMINATOR = _denominator;
pool_id = uint24(IZkBobPool(_pool).pool_id());
}

Expand Down
8 changes: 7 additions & 1 deletion src/zkbob/ZkBobDirectDepositQueueETH.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ import "./ZkBobDirectDepositQueue.sol";
* Queue for zkBob ETH direct deposits.
*/
contract ZkBobDirectDepositQueueETH is IZkBobDirectDepositsETH, ZkBobDirectDepositQueue {
constructor(address _pool, address _token) ZkBobDirectDepositQueue(_pool, _token) {}
constructor(
address _pool,
address _token,
uint256 _denominator
)
ZkBobDirectDepositQueue(_pool, _token, _denominator)
{}

/// @inheritdoc IZkBobDirectDepositsETH
function directNativeDeposit(
Expand Down
Loading

0 comments on commit e7e2255

Please sign in to comment.