Skip to content

Commit

Permalink
adds parsing of proxy address
Browse files Browse the repository at this point in the history
  • Loading branch information
r0wdy1 committed Nov 1, 2023
1 parent 71b35a6 commit fad1333
Show file tree
Hide file tree
Showing 5 changed files with 291 additions and 29 deletions.
1 change: 1 addition & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"var-name-mixedcase": false}
14 changes: 9 additions & 5 deletions src/zkbob/sequencer/MemoUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@ pragma solidity 0.8.15;
// New memo struct
// 0-2 bytes - tx type?
// 2-22 bytes - proxy address
// 22-54 bytes - proxy fee
// 54-86 bytes - prover fee
// 22-30 bytes - proxy fee
// 30-38 bytes - prover fee
import "../utils/CustomABIDecoder.sol";

library MemoUtils {
function parseFees(bytes memory memo) public pure returns (address proxyAddress, uint256 proxyFee, uint256 proverFee) {
// TODO
contract MemoUtils is CustomABIDecoder{
function parseFees() public pure returns (address proxyAddress, uint256 proxyFee, uint256 proverFee) {
proxyAddress = _memo_proxy_address();
//TODO
proxyFee = 0;
proverFee = 0;
}

function parseTokenDelta(uint256 transferDelta) public pure returns (int64) {
Expand Down
43 changes: 25 additions & 18 deletions src/zkbob/sequencer/ZkBobSequencer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import {PriorityQueue, PriorityOperation} from "./PriorityQueue.sol";
import {ZkBobPool} from "../ZkBobPool.sol";
import {MemoUtils} from "./MemoUtils.sol";

contract ZkBobSequencer {
contract ZkBobSequencer is MemoUtils {
using PriorityQueue for PriorityQueue.Queue;

constructor(address pool) {
_pool = ZkBobPool(pool);
}
struct CommitData {
uint48 index;
uint256 out_commit;
Expand Down Expand Up @@ -39,7 +42,7 @@ contract ZkBobSequencer {
PriorityQueue.Queue priorityQueue;

// Pool contract, this contract is operator of the pool
ZkBobPool pool;
ZkBobPool _pool;

// Accumulated fees for each prover
mapping(address => uint256) accumulatedFees;
Expand All @@ -64,12 +67,12 @@ contract ZkBobSequencer {
function commit(CommitData calldata commitData) external {
require(pendingNullifiers[commitData.nullifier] == 0, "ZkBobSequencer: nullifier is already pending");

(address proxy, , ) = MemoUtils.parseFees(commitData.memo);
(address proxy, , ) = MemoUtils.parseFees();
require(msg.sender == proxy, "ZkBobSequencer: not authorized");

require(pool.nullifiers(commitData.nullifier) == 0, "ZkBobSequencer: nullifier is spent");
require(uint96(commitData.index) <= pool.pool_index(), "ZkBobSequencer: index is too high");
require(pool.transfer_verifier().verifyProof(transfer_pub(commitData), commitData.transfer_proof), "ZkBobSequencer: invalid proof");
require(_pool.nullifiers(commitData.nullifier) == 0, "ZkBobSequencer: nullifier is spent");
require(uint96(commitData.index) <= _pool.pool_index(), "ZkBobSequencer: index is too high");
require(_pool.transfer_verifier().verifyProof(transfer_pub(commitData), commitData.transfer_proof), "ZkBobSequencer: invalid proof");
require(MemoUtils.parseMessagePrefix(commitData.memo) == MESSAGE_PREFIX_COMMON_V1, "ZkBobPool: bad message prefix");

PriorityOperation memory op = PriorityOperation(commitHash(commitData), block.timestamp);
Expand All @@ -80,13 +83,17 @@ contract ZkBobSequencer {
emit Commited();
}

function head() external view returns (PriorityOperation memory) {
return priorityQueue.data[priorityQueue.head];
}

// 1. Pop first operation from priority queue
// 2. Verify that:
// 1) If we are in the grace period then msg.sender can be only proxy, otherwice it can be anyone
// 2) Provided commitData corresponds to saved commitHash
// 3) Tree proof is correct according to the current pool state
// If this checks hold then the prover did everything correctly and if the pool.transact will revert we can safely remove this operation from the queue
// 3. Call pool.transact with the provided data
// If this checks hold then the prover did everything correctly and if the _pool.transact will revert we can safely remove this operation from the queue
// 3. Call _pool.transact with the provided data
// 1) If call is successfull we store fees and emit event
// 2) If call is not successfull we only emit event. Important: we don't revert
// 4. Update lastQueueUpdateTimestamp and delete pending nullifier
Expand All @@ -100,18 +107,18 @@ contract ZkBobSequencer {
require(op.commitHash == commitHash(commitData), "ZkBobSequencer: invalid commit hash");

// We need to store proxy address in the memo to prevent front running during commit
(address proxy, uint256 proxy_fee, uint256 prover_fee) = MemoUtils.parseFees(commitData.memo);
(address proxy, uint256 proxy_fee, uint256 prover_fee) = MemoUtils.parseFees();
uint256 timestamp = max(op.timestamp, lastQueueUpdateTimestamp);
if (block.timestamp <= timestamp + PROXY_GRACE_PERIOD) {
require(msg.sender == proxy, "ZkBobSequencer: not authorized");
}

// We check proofs twice with the current implementation.
// It should be possible to avoid it but we need to modify pool contract.
require(pool.tree_verifier().verifyProof(tree_pub(commitData, proveData), proveData.tree_proof), "ZkBobSequencer: invalid proof");
require(_pool.tree_verifier().verifyProof(tree_pub(commitData, proveData), proveData.tree_proof), "ZkBobSequencer: invalid proof");

uint256 accumulatedFeeBefore = pool.accumulatedFee(address(this));
bool success = propogateToPool(commitData, proveData);
uint256 accumulatedFeeBefore = _pool.accumulatedFee(address(this));
bool success = propagateToPool(commitData, proveData);

lastQueueUpdateTimestamp = block.timestamp;
delete pendingNullifiers[commitData.nullifier];
Expand All @@ -121,7 +128,7 @@ contract ZkBobSequencer {
// absence of funds so it can't be proved
if (success) {
// We need to store fees and add ability to withdraw them
uint256 fee = pool.accumulatedFee(address(this)) - accumulatedFeeBefore;
uint256 fee = _pool.accumulatedFee(address(this)) - accumulatedFeeBefore;

require(proxy_fee + prover_fee <= fee, "ZkBobSequencer: fee is too low");
// msg.sender recieves all the fee because:
Expand Down Expand Up @@ -159,15 +166,15 @@ contract ZkBobSequencer {
}

function transfer_pub(CommitData calldata commitData) internal view returns (uint256[5] memory r) {
r[0] = pool.roots(commitData.index);
r[0] = _pool.roots(commitData.index);
r[1] = commitData.nullifier;
r[2] = commitData.out_commit;
r[3] = commitData.transfer_delta + (pool.pool_id() << (TRANSFER_DELTA_SIZE * 8));
r[3] = commitData.transfer_delta + (_pool.pool_id() << (TRANSFER_DELTA_SIZE * 8));
r[4] = uint256(keccak256(commitData.memo)) % R;
}

function tree_pub(CommitData calldata commitData, ProveData calldata proveData) internal view returns (uint256[3] memory r) {
r[0] = pool.roots(pool.pool_index());
r[0] = _pool.roots(_pool.pool_index());
r[1] = proveData.root_after;
r[2] = commitData.out_commit;
}
Expand All @@ -177,8 +184,8 @@ contract ZkBobSequencer {
return abi.encode(commitData, proveData);
}

function propogateToPool(CommitData calldata commitData, ProveData calldata proveData) internal returns (bool) {
// Call pool.transact
function propagateToPool(CommitData calldata commitData, ProveData calldata proveData) internal returns (bool) {
// Call _pool.transact
return false;
}

Expand Down
42 changes: 36 additions & 6 deletions src/zkbob/utils/CustomABIDecoder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ contract CustomABIDecoder {
r := calldataload(pos)
}
}
function _loadaddress(uint256 pos) internal pure returns (address r) {
assembly {
r := calldataload(pos)
}
}

function _transfer_nullifier() internal pure returns (uint256 r) {
r = _loaduint256(transfer_nullifier_pos);
Expand Down Expand Up @@ -150,20 +155,44 @@ contract CustomABIDecoder {
}
}

uint256 constant memo_fee_pos = memo_data_pos;
uint256 constant memo_fee_size = 8;
uint256 constant memo_fee_mask = (1 << (memo_fee_size * 8)) - 1;
// uint256 constant memo_fee_pos = memo_data_pos;
uint256 constant memo_sequencer_data_pos = memo_data_pos;
uint256 constant memo_tx_type_size = 2;
uint256 constant memo_prover_fee_size = memo_fee_size;
uint256 constant memo_proxy_fee_size = memo_fee_size;
uint256 constant memo_proxy_address_size = 20;
uint256 constant memo_sequencer_data_size = memo_tx_type_size + memo_proxy_address_size + memo_proxy_fee_size + memo_prover_fee_size ;
uint256 constant memo_tx_type_pos = memo_data_pos;

uint256 constant memo_proxy_address_pos = memo_sequencer_data_pos + memo_tx_type_size;

uint256 constant memo_prover_fee_pos = memo_proxy_address_pos + memo_proxy_address_size;

uint256 constant memo_proxy_fee_pos = memo_prover_fee_pos + memo_prover_fee_size;

function _memo_fee() internal pure returns (uint256 r) {
r = _loaduint256(memo_fee_pos + memo_fee_size - uint256_size) & memo_fee_mask;
uint256 proverFee = _loaduint256(
memo_prover_fee_pos + memo_fee_size - uint256_size
) & memo_fee_mask;
uint256 proxyFee = _loaduint256(
memo_proxy_fee_pos + memo_fee_size - uint256_size
) & memo_fee_mask;
r = proxyFee + proverFee;
}

// Withdraw specific data

uint256 constant memo_native_amount_pos = memo_fee_pos + memo_fee_size;
uint256 constant memo_native_amount_pos = memo_sequencer_data_pos + memo_sequencer_data_size;
uint256 constant memo_native_amount_size = 8;
uint256 constant memo_native_amount_mask = (1 << (memo_native_amount_size * 8)) - 1;

uint256 constant memo_fee_size = 8;
uint256 constant memo_fee_mask = (1 << (memo_fee_size * 8)) - 1;

function _memo_proxy_address() internal pure returns (address r) {
r = _loadaddress(memo_proxy_address_pos);
}

function _memo_native_amount() internal pure returns (uint256 r) {
r = _loaduint256(memo_native_amount_pos + memo_native_amount_size - uint256_size) & memo_native_amount_mask;
}
Expand All @@ -176,8 +205,9 @@ contract CustomABIDecoder {
}

// Permittable token deposit specific data
//This is mutualy exclusive with native amount i.e. they both take the same position in transactions of respective type

uint256 constant memo_permit_deadline_pos = memo_fee_pos + memo_fee_size;
uint256 constant memo_permit_deadline_pos = memo_sequencer_data_pos + memo_sequencer_data_size;
uint256 constant memo_permit_deadline_size = 8;

function _memo_permit_deadline() internal pure returns (uint64 r) {
Expand Down
Loading

0 comments on commit fad1333

Please sign in to comment.