Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 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
10 changes: 6 additions & 4 deletions packages/loopring_v3.js/src/exchange_v3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ export class ExchangeV3 {
this.exchange = new web3.eth.Contract(JSON.parse(this.exchangeV3Abi));
this.exchange.options.address = this.exchangeAddress;

const exchangeCreationTimestamp = (await this.exchange.methods
.getBlockInfo(0)
.call()).timestamp;
const exchangeCreationTimestamp = (
await this.exchange.methods.getBlockInfo(0).call()
).timestamp;
const genesisMerkleRoot = new BN(
(await this.exchange.methods.getMerkleRoot().call()).slice(2),
16
Expand Down Expand Up @@ -626,7 +626,7 @@ export class ExchangeV3 {

// Get the block data from the transaction data
//const submitBlocksFunctionSignature = "0x8dadd3af"; // submitBlocks
const submitBlocksFunctionSignature = "0xdcb2aa31"; // submitBlocksWithCallbacks
const submitBlocksFunctionSignature = "0x11edcb4d"; // submitBlocksWithCallbacks

const transaction = await this.web3.eth.getTransaction(
event.transactionHash
Expand All @@ -637,6 +637,8 @@ export class ExchangeV3 {
[
"bool",
"bytes",
"bytes",
"bytes",
"bytes"
/*{
"struct CallbackConfig": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ contract LoopringIOExchangeOwner is SelectorBasedAccessManager, ERC1271, Drainab
address[] receivers;
}

struct PostBlocksCallback
{
address to;
bytes data;
}

constructor(
address _exchange
)
Expand Down Expand Up @@ -91,9 +97,11 @@ contract LoopringIOExchangeOwner is SelectorBasedAccessManager, ERC1271, Drainab
}

function submitBlocksWithCallbacks(
bool isDataCompressed,
bytes calldata data,
CallbackConfig calldata config
bool isDataCompressed,
bytes calldata data,
CallbackConfig calldata config,
ExchangeData.FlashMint[] calldata flashMints,
PostBlocksCallback[] calldata postBlocksCallbacks
)
external
{
Expand Down Expand Up @@ -123,13 +131,27 @@ contract LoopringIOExchangeOwner is SelectorBasedAccessManager, ERC1271, Drainab
// Decode the blocks
ExchangeData.Block[] memory blocks = _decodeBlocks(decompressed);

// Process the callback logic.
_beforeBlockSubmission(blocks, config);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For AMM, maybe it's OK to move code inside _beforeBlockSubmission after target.fastCallAndVerify(gasleft(), 0, decompressed), but for other possible use cases, maybe it's still required to be run beforehand. Should we add a flag runBeforeBlockSubmission to TxCallback? Or an alternative is to pass in two CallbackConfig objects, one named txReceiverPreCallbacks, another named ``txReceiverPostCallbacks`.

I'm not sure if the current postBlocksCallbacks also has the potential of being invoked in some future scenarios before submitBlocks. It may open doors for some other possibilities.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be useful, but I don't know if we should add support for things that we currently don't plan to use (and if we use it maybe it needs additional changes again).

But a boolean before/after may indeed be useful with perhaps very little work, so perhaps still worth it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The normal callbacks can now be run before or after the blocks submission using a flag.

I kept the TransactionReceivers (AMM, Bridge) to after the block submissions only to keep things simple (a bit more difficult to do then for the normal callbacks).

// Do flash mints
if (flashMints.length > 0) {
IExchangeV3(target).flashMint(flashMints);
}

// Submit blocks
target.fastCallAndVerify(gasleft(), 0, decompressed);

// Do transaction verifying blocks callbacks
_verifyTransactions(blocks, config);

// Do post blocks callbacks
_afterBlockSubmission(blocks, postBlocksCallbacks);

// Make sure flash mints were repaid
if (flashMints.length > 0) {
IExchangeV3(target).verifyFlashMintsPaidBack(flashMints);
}
}

function _beforeBlockSubmission(
function _verifyTransactions(
ExchangeData.Block[] memory blocks,
CallbackConfig calldata config
)
Expand Down Expand Up @@ -187,6 +209,23 @@ contract LoopringIOExchangeOwner is SelectorBasedAccessManager, ERC1271, Drainab
}
}

function _afterBlockSubmission(
ExchangeData.Block[] memory /*blocks*/,
PostBlocksCallback[] calldata postBlocksCallbacks
)
private
{
for (uint i = 0; i < postBlocksCallbacks.length; i++) {
// Disallow calls to the exchange and pre block callback contracts
require(postBlocksCallbacks[i].to != target, "EXCHANGE_CANNOT_BE_POST_CALLBACK_TARGET");
require(postBlocksCallbacks[i].data.toBytes4(0) != IBlockReceiver.beforeBlockSubmission.selector, "INVALID_POST_CALLBACK_FUNCTION");
(bool success, bytes memory returnData) = postBlocksCallbacks[i].to.call(postBlocksCallbacks[i].data);
if (!success) {
assembly { revert(add(returnData, 32), mload(returnData)) }
}
}
}

function _processTxCallbacks(
ExchangeData.Block memory _block,
TxCallback[] calldata txCallbacks,
Expand Down
Loading