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
2 changes: 1 addition & 1 deletion packages/loopring_v3.js/src/exchange_v3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ export class ExchangeV3 {

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

const transaction = await this.web3.eth.getTransaction(
event.transactionHash
Expand Down
28 changes: 24 additions & 4 deletions packages/loopring_v3/circuit/Circuits/SpotTradeCircuit.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,30 @@ class SpotTradeCircuit : public BaseTransactionCircuit
vfills_B_A(pb, orderA.amm.packed, fillS_B.value(), state.constants._0, FMT(prefix, ".vfills_B_A")),
vfills_S_B(pb, orderB.amm.packed, fillS_B.value(), state.constants._0, FMT(prefix, ".vfills_S_B")),
vfills_B_B(pb, orderB.amm.packed, fillS_A.value(), state.constants._0, FMT(prefix, ".vfills_B_B")),
update_vbalanceS_A(pb, state.accountA.balanceS.weightAMM, vfills_S_A.result(), NUM_BITS_AMOUNT, FMT(prefix, ".update_vbalanceS_A")),
update_vbalanceB_A(pb, state.accountA.balanceB.weightAMM, vfills_B_A.result(), NUM_BITS_AMOUNT, FMT(prefix, ".update_vbalanceB_A")),
update_vbalanceS_B(pb, state.accountB.balanceS.weightAMM, vfills_S_B.result(), NUM_BITS_AMOUNT, FMT(prefix, ".update_vbalanceS_B")),
update_vbalanceB_B(pb, state.accountB.balanceB.weightAMM, vfills_B_B.result(), NUM_BITS_AMOUNT, FMT(prefix, ".update_vbalanceB_B")),
update_vbalanceS_A(
pb,
state.accountA.balanceS.weightAMM,
vfills_S_A.result(),
NUM_BITS_AMOUNT,
FMT(prefix, ".update_vbalanceS_A")),
update_vbalanceB_A(
pb,
state.accountA.balanceB.weightAMM,
vfills_B_A.result(),
NUM_BITS_AMOUNT,
FMT(prefix, ".update_vbalanceB_A")),
update_vbalanceS_B(
pb,
state.accountB.balanceS.weightAMM,
vfills_S_B.result(),
NUM_BITS_AMOUNT,
FMT(prefix, ".update_vbalanceS_B")),
update_vbalanceB_B(
pb,
state.accountB.balanceB.weightAMM,
vfills_B_B.result(),
NUM_BITS_AMOUNT,
FMT(prefix, ".update_vbalanceB_B")),

validateAMM(
pb,
Expand Down
1 change: 0 additions & 1 deletion packages/loopring_v3/circuit/Gadgets/AccountGadgets.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,6 @@ class DynamicBalanceGadget : public DynamicVariableGadget
}
};


} // namespace Loopring

#endif
93 changes: 76 additions & 17 deletions packages/loopring_v3/contracts/amm/AmplifiedAmmController.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2017 Loopring Technology Limited.
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;

import "./IAmmController.sol";
import "../amm/LoopringAmmPool.sol";
Expand All @@ -19,7 +20,11 @@ contract AmplifiedAmmController is IAmmController, Claimable

uint public constant AMPLIFICATION_FACTOR_BASE = (10 ** 18);

mapping(address => uint) public amplificationFactors;
uint public constant CURVE_CHANGE_MIN_DELAY = 7 days;
uint public constant CURVE_CHANGE_AUTH_WINDOW = 7 days;

mapping (address => uint) public amplificationFactors;
mapping (address => uint) public curveChangeAuthorization;

function getInitialVirtualBalances(
uint96[] memory joinAmounts
Expand All @@ -37,44 +42,98 @@ contract AmplifiedAmmController is IAmmController, Claimable
return vTokenBalancesL2;
}

function getVirtualBalances(
uint96[] memory tokenBalancesL2,
uint96[] memory /*vTokenBalancesL2*/
function authorizeVirtualBalances(
uint96[] memory balances,
uint96[] memory /*vBalancesOld*/,
uint96[] memory vBalancesNew,
bytes memory /*data*/
)
external
view
override
returns (uint96[] memory)
returns (bool)
{
// Only allow updating the virtual balances if the AF = 1
require(getAmplificationFactor(msg.sender) == AMPLIFICATION_FACTOR_BASE, "INVALID_OPERATION");
address pool = msg.sender;

// Just set the virtual balances to the actual balances
uint96[] memory vTokenBalancesL2 = new uint96[](tokenBalancesL2.length);
for (uint i = 0; i < tokenBalancesL2.length; i++) {
vTokenBalancesL2[i] = tokenBalancesL2[i];
// Check if a curve change was explicitly authorized
if (consumeCurveChangeAuthorized(pool)) {
return true;
}
return vTokenBalancesL2;

if (getAmplificationFactor(pool) != AMPLIFICATION_FACTOR_BASE) {
return false;
}

// Special case: Always allow updating the virtual balances if the AF = 1
for (uint i = 0; i < balances.length; i++) {
if (vBalancesNew[i] != balances[i]) {
return false;
}
}

return true;
}

function authorizeCurveChange(address pool)
external
onlyOwner
{
curveChangeAuthorization[pool] = block.timestamp + CURVE_CHANGE_MIN_DELAY;
}

function setAmplificationFactor(
address amm,
address pool,
uint amplificationFactor
)
external
onlyOwner
{
amplificationFactors[amm] = amplificationFactor;
amplificationFactors[pool] = amplificationFactor;
}

function getAmplificationFactor(address amm)
function getAmplificationFactor(address pool)
public
view
returns (uint amplificationFactor)
{
amplificationFactor = amplificationFactors[amm];
amplificationFactor = amplificationFactors[pool];
if (amplificationFactor == 0) {
amplificationFactor = AMPLIFICATION_FACTOR_BASE;
}
}

function setupPool(
LoopringAmmPool pool,
AmmData.PoolConfig calldata config
)
external
onlyOwner
{
pool.setupPool(config);
}

function enterExitMode(
LoopringAmmPool pool,
bool enabled
)
external
onlyOwner
{
pool.enterExitMode(enabled);
}

// == Internal Functions ==

function consumeCurveChangeAuthorized(address pool)
internal
returns (bool authorized)
{
uint timestamp = curveChangeAuthorization[pool];
authorized = (timestamp <= block.timestamp) &&
(block.timestamp <= timestamp + CURVE_CHANGE_AUTH_WINDOW);

// Remove authorization
if (timestamp > 0) {
delete curveChangeAuthorization[pool];
}
}
}
19 changes: 11 additions & 8 deletions packages/loopring_v3/contracts/amm/IAmmController.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ interface IAmmController

/// @dev Called by the pool contract when a SET_VIRTUAL_BALANCES operation is done
/// on the pool.
/// @param tokenBalancesL2 The balances in the pool
/// @param vTokenBalancesL2 The current virtual balances in the pool
/// @return The new virtual balances in the pool
function getVirtualBalances(
uint96[] memory tokenBalancesL2,
uint96[] memory vTokenBalancesL2
/// @param balances The balances in the pool
/// @param vBalancesOld The current virtual balances in the pool
/// @param vBalancesNew The new virtual balances in the pool
/// @param data Custom data
/// @return True if vBalancesNew can be used, else false
function authorizeVirtualBalances(
uint96[] memory balances,
uint96[] memory vBalancesOld,
uint96[] memory vBalancesNew,
bytes memory data
)
external
view
returns (uint96[] memory);
returns (bool);
}
8 changes: 8 additions & 0 deletions packages/loopring_v3/contracts/amm/IAssetManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2017 Loopring Technology Limited.
pragma solidity ^0.7.0;


/// @author Brecht Devos - <[email protected]>
interface IAssetManager
{}
54 changes: 36 additions & 18 deletions packages/loopring_v3/contracts/amm/LoopringAmmPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import "../aux/access/ITransactionReceiver.sol";
import "../core/iface/IAgentRegistry.sol";
import "../lib/ReentrancyGuard.sol";
import "../lib/TransferUtil.sol";
import "./libamm/AmmTransactionReceiver.sol";
import "./libamm/AmmAssetManagement.sol";
import "./libamm/AmmData.sol";
import "./libamm/AmmExitRequest.sol";
import "./libamm/AmmJoinRequest.sol";
import "./libamm/AmmPoolToken.sol";
import "./libamm/AmmStatus.sol";
import "./libamm/AmmTransactionReceiver.sol";
import "./libamm/AmmWithdrawal.sol";
import "./PoolToken.sol";

Expand All @@ -24,11 +25,12 @@ contract LoopringAmmPool is
ITransactionReceiver,
ReentrancyGuard
{
using AmmTransactionReceiver for AmmData.State;
using AmmAssetManagement for AmmData.State;
using AmmJoinRequest for AmmData.State;
using AmmExitRequest for AmmData.State;
using AmmPoolToken for AmmData.State;
using AmmStatus for AmmData.State;
using AmmTransactionReceiver for AmmData.State;
using AmmWithdrawal for AmmData.State;
using TransferUtil for address;

Expand All @@ -38,7 +40,7 @@ contract LoopringAmmPool is
event Shutdown(uint timestamp);

IAmmController public immutable controller;
address public immutable assetManager;
IAssetManager public immutable assetManager;
bool public immutable joinsDisabled;

modifier onlyFromExchangeOwner()
Expand All @@ -49,7 +51,7 @@ contract LoopringAmmPool is

modifier onlyFromAssetManager()
{
require(msg.sender == assetManager, "UNAUTHORIZED");
require(msg.sender == address(assetManager), "UNAUTHORIZED");
_;
}

Expand All @@ -73,10 +75,11 @@ contract LoopringAmmPool is

constructor(
IAmmController _controller,
address _assetManager,
IAssetManager _assetManager,
bool _joinsDisabled
)
{
require(_controller != IAmmController(0), "ZERO_ADDRESS");
controller = _controller;
assetManager = _assetManager;
joinsDisabled = _joinsDisabled;
Expand All @@ -96,9 +99,18 @@ contract LoopringAmmPool is
external
nonReentrant
{
require(state.accountID == 0 || msg.sender == address(controller), "UNAUTHORIZED");
state.setupPool(config);
}

function enterExitMode(bool enabled)
external
onlyFromController
{
require(state.exitMode != enabled, "INVALID_STATE");
state.exitMode = enabled;
}

// Anyone is able to shut down the pool when requests aren't being processed any more.
function shutdown(address exitOwner)
external
Expand All @@ -111,7 +123,6 @@ contract LoopringAmmPool is

function shutdownByController()
external
payable
onlyWhenOnline
nonReentrant
onlyFromController
Expand Down Expand Up @@ -183,29 +194,36 @@ contract LoopringAmmPool is
state.withdrawWhenOffline();
}

function depositAssetsToL2(
uint96[] memory amounts
function transferOut(
address to,
address token,
uint amount
)
external
nonReentrant
onlyWhenOnline
onlyFromExchangeOwner
onlyFromAssetManager
{
for(uint i = 0; i < state.tokens.length; i++) {
require(amounts[i] != 0, "INVALID_DEPOSIT_AMOUNT");
state.deposit(state.tokens[i].addr, amounts[i]);
}
state.transferOut(to, token, amount);
}

function transferOut(
address to,
function setBalanceL1(
address token,
uint amount
uint96 balance
)
external
nonReentrant
onlyFromAssetManager
{
token.transferOut(to, amount);
state.balancesL1[token] = balance;
}

function getBalanceL1(
address token
)
public
view
returns (uint96)
{
return state.balancesL1[token];
}
}
Loading