Skip to content
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
17 changes: 12 additions & 5 deletions contracts/HubPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ contract HubPool is HubPoolInterface, Testable, Lockable, MultiCaller, Ownable {
event RootBundleCanceled(address indexed disputer, uint256 requestTime, bytes disputedAncillaryData);

modifier noActiveRequests() {
require(rootBundleProposal.unclaimedPoolRebalanceLeafCount == 0, "proposal has unclaimed leafs");
require(!_activeRequest(), "proposal has unclaimed leafs");
_;
}

Expand Down Expand Up @@ -666,12 +666,15 @@ contract HubPool is HubPoolInterface, Testable, Lockable, MultiCaller, Ownable {
function _sync(address l1Token) internal {
// Check if the l1Token balance of the contract is greater than the liquidReserves. If it is then the bridging
// action from L2 -> L1 has concluded and the local accounting can be updated.
uint256 l1TokenBalance = IERC20(l1Token).balanceOf(address(this));
if (l1TokenBalance > pooledTokens[l1Token].liquidReserves) {
// Note: this calculation must take into account the bond when it's acting on the bond token and there's an
// active request.
uint256 balance = IERC20(l1Token).balanceOf(address(this));
uint256 balanceSansBond = l1Token == address(bondToken) && _activeRequest() ? balance - bondAmount : balance;
if (balanceSansBond > pooledTokens[l1Token].liquidReserves) {
// Note the numerical operation below can send utilizedReserves to negative. This can occur when tokens are
// dropped onto the contract, exceeding the liquidReserves.
pooledTokens[l1Token].utilizedReserves -= int256(l1TokenBalance - pooledTokens[l1Token].liquidReserves);
pooledTokens[l1Token].liquidReserves = l1TokenBalance;
pooledTokens[l1Token].utilizedReserves -= int256(balanceSansBond - pooledTokens[l1Token].liquidReserves);
pooledTokens[l1Token].liquidReserves = balanceSansBond;
}
}

Expand Down Expand Up @@ -722,6 +725,10 @@ contract HubPool is HubPoolInterface, Testable, Lockable, MultiCaller, Ownable {
emit SpokePoolAdminFunctionTriggered(chainId, functionData);
}

function _activeRequest() internal view returns (bool) {
return rootBundleProposal.unclaimedPoolRebalanceLeafCount != 0;
}

// If functionCallStackOriginatesFromOutsideThisContract is true then this was called by the callback function
// by dropping ETH onto the contract. In this case, deposit the ETH into WETH. This would happen if ETH was sent
// over the optimism bridge, for example. If false then this was set as a result of unwinding LP tokens, with the
Expand Down
6 changes: 6 additions & 0 deletions test/HubPool.PooledTokenSynchronization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ describe("HubPool Pooled Token Synchronization", function () {
await hubPool
.connect(dataWorker)
.proposeRootBundle([3117], 1, tree.getHexRoot(), consts.mockTreeRoot, consts.mockSlowRelayRoot);

// Bond being paid in should not impact liquid reserves.
await hubPool.exchangeRateCurrent(weth.address); // force state sync (calls sync internally).
expect((await hubPool.pooledTokens(weth.address)).liquidReserves).to.equal(consts.amountToLp);

// Counters should move once the root bundle is executed.
await timer.setCurrentTime(Number(await timer.getCurrentTime()) + consts.refundProposalLiveness + 1);
await hubPool.connect(dataWorker).executeRootBundle(leafs[0], tree.getHexProof(leafs[0]));
expect((await hubPool.pooledTokens(weth.address)).liquidReserves).to.equal(consts.amountToLp.sub(tokensSendToL2));
Expand Down
4 changes: 2 additions & 2 deletions test/gas-analytics/HubPool.RefundExecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ describe("Gas Analytics: HubPool Relayer Refund Execution", function () {
1, // poolRebalanceLeafCount. There is exactly one leaf in the bundle.
tree.getHexRoot(), // poolRebalanceRoot. Generated from the merkle tree constructed before.
consts.mockRelayerRefundRoot, // Not relevant for this test.
consts.mockSlowRelayFulfillmentRoot // Not relevant for this test.
consts.mockSlowRelayRoot // Not relevant for this test.
);
console.log(`proposeRootBundle-gasUsed: ${(await initiateTxn.wait()).gasUsed}`);

Expand All @@ -152,7 +152,7 @@ describe("Gas Analytics: HubPool Relayer Refund Execution", function () {
REFUND_CHAIN_COUNT, // poolRebalanceLeafCount. Execute all leaves
tree.getHexRoot(), // poolRebalanceRoot. Generated from the merkle tree constructed before.
consts.mockRelayerRefundRoot, // Not relevant for this test.
consts.mockSlowRelayFulfillmentRoot // Not relevant for this test.
consts.mockSlowRelayRoot // Not relevant for this test.
);
console.log(`proposeRootBundle-gasUsed: ${(await initiateTxn.wait()).gasUsed}`);

Expand Down