feat: add balancer v2 executor

This commit is contained in:
royvardhan
2025-01-27 22:54:56 +05:30
parent 0e0c13b169
commit a700189aaf
98 changed files with 6368 additions and 1 deletions

1
cache/solidity-files-cache.json vendored Normal file
View File

@@ -0,0 +1 @@
{"_format":"","paths":{"artifacts":"out","build_infos":"out/build-info","sources":"src","tests":"test","scripts":"script","libraries":["lib"]},"files":{"test/TychoRouter.t.sol":{"lastModificationDate":1737991455132,"contentHash":"7215ee9c7d9dc229d2921a40e899ec5f","sourceName":"test/TychoRouter.t.sol","imports":[],"versionRequirement":null,"artifacts":{},"seenByCompiler":true}},"builds":[],"profiles":{"default":{"solc":{"optimizer":{"enabled":false,"runs":200},"metadata":{"useLiteralContent":false,"bytecodeHash":"ipfs","appendCBOR":true},"outputSelection":{"*":{"*":["abi","evm.bytecode.object","evm.bytecode.sourceMap","evm.bytecode.linkReferences","evm.deployedBytecode.object","evm.deployedBytecode.sourceMap","evm.deployedBytecode.linkReferences","evm.deployedBytecode.immutableReferences","evm.methodIdentifiers","metadata"]}},"evmVersion":"cancun","viaIR":false,"libraries":{}},"vyper":{"evmVersion":"cancun","outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode"]}}}}}}

View File

@@ -0,0 +1,57 @@
# Changelog
## 0.4.0 (20223-03-15)
- Added `IERC4626`.
- Added `IChildChainGauge`.
- Added `ILMGetters`.
### Breaking changes
- Removed `IBaseGaugeFactory`.
- Refactor: renamed `IBalancerMinter` to `IMainnetBalancerMinter`.
- `IMainnetBalancerMinter` now implements reduced version of previous `IBalancerMinter` and `ILMGetters`.
## 0.3.0 (20223-02-08)
### New Features
- Added `checkpointGaugesOfTypeAboveRelativeWeight` to `IL2GaugeCheckpointer`.
- Added `IComposableStablePoolRates`.
- Added `IProtocolFeeCache`.
- Added `setTargets` and `setSwapFeePercentage` to `ILinearPool`.
### Breaking changes
- `IL2GaugeCheckpointer`: `getGaugeAt` renamed to `getGaugeAtIndex`.
## 0.2.1 (2022-12-12)
### Misc
- Added examples to readme.
## 0.2.0 (2022-12-01)
### New Interfaces
- Added `IProtocolFeeSplitter`.
- Added `IL2GaugeCheckpointer`.
- Added `IAuthorizerAdaptorEntrypoint`.
- Added `IRateProviderPool`.
- Added `IVersion`.
- Added `IFactoryCreatedPoolVersion`.
- Added `IRecoveryModeHelper`.
### New Features
- Extended the valid compiler version range to any of the 0.7.x and 0.8.x line.
### Breaking Changes
- Removed `IAssetManager`, which was unused.
- `IGaugeAdder`: authorizer adaptor getter replaced with authorizer adaptor entrypoint getter.
## 0.1.0 (2022-10-25)
- Initial release.

View File

@@ -0,0 +1,139 @@
# <img src="../../logo.svg" alt="Balancer" height="128px">
# Balancer V2 Interfaces
[![NPM Package](https://img.shields.io/npm/v/@balancer-labs/v2-interfaces.svg)](https://www.npmjs.org/package/@balancer-labs/v2-interfaces)
This package contains interfaces used in dependent packages, which makes building systems that interact with Balancer contracts simpler, as the implementation information is not included.
## Overview
### Installation
```console
$ npm install @balancer-labs/v2-interfaces
```
### Usage
This package can be used in multiple ways, including interacting with already deployed Pools, or performing local testing. It contains all interfaces used in the system, from the foundational [Vault](contracts/vault/IVault.sol) to very specific contracts (e.g., [Optimism Gas Limit Provider](contracts/liquidity-mining/IOptimismGasLimitProvider.sol)).
The following are a couple code samples to help get you started. To get the address of deployed contracts in both production and test networks, see [`v2-deployments`](../deployments).
Sample contract that joins a Balancer Pool:
````solidity
pragma solidity ^0.7.0;
// Import Vault interface, error messages, and library for decoding join/exit data.
import "@balancer-labs/v2-interfaces/contracts/solidity-utils/helpers/BalancerErrors.sol";
import "@balancer-labs/v2-interfaces/contracts/solidity-utils/openzeppelin/IERC20.sol";
import "@balancer-labs/v2-interfaces/contracts/pool-weighted/WeightedPoolUserData.sol";
import "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol";
import "@balancer-labs/v2-interfaces/contracts/vault/IAsset.sol";
// Import ERC20Helpers for `_asIAsset`
import "@balancer-labs/v2-solidity-utils/contracts/helpers/ERC20Helpers.sol";
contract JoinBalancerPool {
IVault private constant vault = "0xBA12222222228d8Ba445958a75a0704d566BF2C8";
function joinBalancerPool(bytes32 poolId, address sender, address recipient, uint256[] memory amountsIn, uint256 minBptAmountOut) external {
(IERC20[] memory tokens, , ) = vault.getPoolTokens(poolId);
// Use BalancerErrors to validate input
_require(amountsIn.length == tokens.length, Errors.INPUT_LENGTH_MISMATCH);
// Encode the userData for a multi-token join
bytes memory userData = abi.encode(WeightedPoolUserData.JoinKind.EXACT_TOKENS_IN_FOR_BPT_OUT, amountsIn, minBptAmountOut);
IVault.JoinPoolRequest memory request = IVault.JoinPoolRequest({
assets: _asIAsset(tokens),
maxAmountsIn: amountsIn,
userData: userData,
fromInternalBalance: false
});
// Call the Vault to join the pool
vault.joinPool(poolId, sender, recipient, request);
}
...
}
```
Sample contract that performs Internal Balance deposits:
```solidity
pragma solidity ^0.7.0;
import "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol";
contract SimpleDepositor {
IVault private constant vault = "0xBA12222222228d8Ba445958a75a0704d566BF2C8";
function depositFunds(
IERC20[] memory tokens,
uint256[] memory amounts,
) external {
IVault.UserBalanceOp[] memory ops = new IVault.UserBalanceOp[](tokens.length);
for (uint256 i = 0; i < tokens.length; ++i) {
ops[i] = IVault.UserBalanceOp({
kind: IVault.UserBalanceOpKind.DEPOSIT_INTERNAL,
asset: IAsset(tokens[i]),
amount: amounts[i],
sender: address(this),
recipient: address(this)
});
}
vault.manageUserBalance(ops);
}
}
````
Sample contract that performs Flash Loans:
```solidity
pragma solidity ^0.7.0;
import "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol";
import "@balancer-labs/v2-interfaces/contracts/vault/IFlashLoanRecipient.sol";
contract FlashLoanRecipient is IFlashLoanRecipient {
IVault private constant vault = "0xBA12222222228d8Ba445958a75a0704d566BF2C8";
function makeFlashLoan(
IERC20[] memory tokens,
uint256[] memory amounts,
bytes memory userData
) external {
vault.flashLoan(this, tokens, amounts, userData);
}
function receiveFlashLoan(
IERC20[] memory tokens,
uint256[] memory amounts,
uint256[] memory feeAmounts,
bytes memory userData
) external override {
require(msg.sender == vault);
...
}
}
```
### Notes
In addition to interfaces, it also includes a small number of libraries that encapsulate enum types for particular pools (e.g., [StablePoolUserData](contracts/pool-stable/StablePoolUserData.sol), and functions for working with encoding and decoding `userData`. (See the `balancer-js` package for TypeScript versions of these utilities.)
One of the most commonly included libraries is [BalancerErrors](contracts/solidity-utils/helpers/BalancerErrors.sol). To save bytecode, Balancer V2 does not use the standard `require(<condition>, 'error string')`. Instead, BalancerErrors defines `_require` and `_revert` functions. These take a numerical constant instead of a string, and return a fixed-length code, which can be converted to plain text using TypeScript utilities.
## Licensing
[GNU General Public License Version 3 (GPL v3)](../../LICENSE).
```
```

View File

@@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
interface IDistributorCallback {
function distributorCallback(bytes calldata callbackData) external;
}

View File

@@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
interface IArbitrumFeeProvider {
function getArbitrumFees()
external
view
returns (
uint256 gasLimit,
uint256 gasPrice,
uint256 maxSubmissionCost
);
function setArbitrumFees(
uint64 gasLimit,
uint64 gasPrice,
uint64 maxSubmissionCost
) external;
}

View File

@@ -0,0 +1,38 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/helpers/IAuthentication.sol";
import "../vault/IVault.sol";
interface IAuthorizerAdaptor is IAuthentication {
/**
* @notice Returns the Balancer Vault
*/
function getVault() external view returns (IVault);
/**
* @notice Returns the Authorizer
*/
function getAuthorizer() external view returns (IAuthorizer);
/**
* @notice Performs an arbitrary function call on a target contract, provided the caller is authorized to do so.
* @param target - Address of the contract to be called
* @param data - Calldata to be sent to the target contract
* @return The bytes encoded return value from the performed function call
*/
function performAction(address target, bytes calldata data) external payable returns (bytes memory);
}

View File

@@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "./IAuthorizerAdaptor.sol";
/**
* @notice Interface for `AuthorizerAdaptorEntrypoint`.
*/
interface IAuthorizerAdaptorEntrypoint is IAuthorizerAdaptor {
/**
* @notice Returns the Authorizer Adaptor
*/
function getAuthorizerAdaptor() external view returns (IAuthorizerAdaptor);
}

View File

@@ -0,0 +1,115 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
/**
* @dev Base minter interface, applicable to Mainnet minter or L2 pseudo minters.
*/
interface IBalancerMinter {
event Minted(address indexed recipient, address gauge, uint256 minted);
/**
* @notice Returns the address of the Balancer Governance Token
*/
function getBalancerToken() external view returns (IERC20);
/**
* @notice Mint everything which belongs to `msg.sender` and send to them
* @param gauge `LiquidityGauge` address to get mintable amount from
*/
function mint(address gauge) external returns (uint256);
/**
* @notice Mint everything which belongs to `msg.sender` across multiple gauges
* @param gauges List of `LiquidityGauge` addresses
*/
function mintMany(address[] calldata gauges) external returns (uint256);
/**
* @notice Mint tokens for `user`
* @dev Only possible when `msg.sender` has been approved by `user` to mint on their behalf
* @param gauge `LiquidityGauge` address to get mintable amount from
* @param user Address to mint to
*/
function mintFor(address gauge, address user) external returns (uint256);
/**
* @notice Mint tokens for `user` across multiple gauges
* @dev Only possible when `msg.sender` has been approved by `user` to mint on their behalf
* @param gauges List of `LiquidityGauge` addresses
* @param user Address to mint to
*/
function mintManyFor(address[] calldata gauges, address user) external returns (uint256);
/**
* @notice The total number of tokens minted for `user` from `gauge`
*/
function minted(address user, address gauge) external view returns (uint256);
/**
* @notice Whether `minter` is approved to mint tokens for `user`
*/
function getMinterApproval(address minter, address user) external view returns (bool);
/**
* @notice Set whether `minter` is approved to mint tokens on your behalf
*/
function setMinterApproval(address minter, bool approval) external;
/**
* @notice Set whether `minter` is approved to mint tokens on behalf of `user`, who has signed a message authorizing
* them.
*/
function setMinterApprovalWithSignature(
address minter,
bool approval,
address user,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
// The below functions are near-duplicates of functions available above.
// They are included for ABI compatibility with snake_casing as used in vyper contracts.
// solhint-disable func-name-mixedcase
/**
* @notice Whether `minter` is approved to mint tokens for `user`
*/
function allowed_to_mint_for(address minter, address user) external view returns (bool);
/**
* @notice Mint everything which belongs to `msg.sender` across multiple gauges
* @dev This function is not recommended as `mintMany()` is more flexible and gas efficient
* @param gauges List of `LiquidityGauge` addresses
*/
function mint_many(address[8] calldata gauges) external;
/**
* @notice Mint tokens for `user`
* @dev Only possible when `msg.sender` has been approved by `user` to mint on their behalf
* @param gauge `LiquidityGauge` address to get mintable amount from
* @param user Address to mint to
*/
function mint_for(address gauge, address user) external;
/**
* @notice Toggle whether `minter` is approved to mint tokens for `user`
*/
function toggle_approve_mint(address minter) external;
}

View File

@@ -0,0 +1,44 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
interface IBalancerToken is IERC20 {
function mint(address to, uint256 amount) external;
function getRoleMemberCount(bytes32 role) external view returns (uint256);
function getRoleMember(bytes32 role, uint256 index) external view returns (address);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
// solhint-disable-next-line func-name-mixedcase
function DEFAULT_ADMIN_ROLE() external view returns (bytes32);
// solhint-disable-next-line func-name-mixedcase
function MINTER_ROLE() external view returns (bytes32);
// solhint-disable-next-line func-name-mixedcase
function SNAPSHOT_ROLE() external view returns (bytes32);
function snapshot() external;
}

View File

@@ -0,0 +1,45 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/helpers/IAuthentication.sol";
import "./IBalancerToken.sol";
interface IBalancerTokenAdmin is IAuthentication {
// solhint-disable func-name-mixedcase
function INITIAL_RATE() external view returns (uint256);
function RATE_REDUCTION_TIME() external view returns (uint256);
function RATE_REDUCTION_COEFFICIENT() external view returns (uint256);
function RATE_DENOMINATOR() external view returns (uint256);
// solhint-enable func-name-mixedcase
/**
* @notice Returns the address of the Balancer Governance Token
*/
function getBalancerToken() external view returns (IBalancerToken);
function activate() external;
function rate() external view returns (uint256);
function startEpochTimeWrite() external returns (uint256);
function mint(address to, uint256 amount) external;
}

View File

@@ -0,0 +1,51 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../pool-utils/IVersion.sol";
import "./ILiquidityGaugeFactory.sol";
// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
// naming convention.
// solhint-disable func-name-mixedcase
// solhint-disable func-param-name-mixedcase
interface IChildChainGauge is IVersion {
/**
* @notice Proxy constructor.
* @param lpToken Pool allowed to stake in this gauge.
* @param version Gauge version string identifier.
*/
function initialize(address lpToken, string memory version) external;
/**
* @notice Returns BAL liquidity emissions calculated during checkpoints for the given user.
* @param user User address.
* @return uint256 BAL amount to issue for the address.
*/
function integrate_fraction(address user) external view returns (uint256);
/**
* @notice Records a checkpoint for a given user.
* @param user User address.
* @return bool Always true.
*/
function user_checkpoint(address user) external returns (bool);
/**
* @notice Returns gauge factory address.
*/
function factory() external view returns (ILiquidityGaugeFactory);
}

View File

@@ -0,0 +1,60 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "./IChildChainStreamer.sol";
import "./ILiquidityGauge.sol";
import "./ILiquidityGaugeFactory.sol";
import "./IRewardsOnlyGauge.sol";
interface IChildChainLiquidityGaugeFactory is ILiquidityGaugeFactory {
event RewardsOnlyGaugeCreated(address indexed gauge, address indexed pool, address streamer);
/**
* @notice Returns the address of the implementation used for gauge deployments.
*/
function getGaugeImplementation() external view returns (ILiquidityGauge);
/**
* @notice Returns the address of the implementation used for streamer deployments.
*/
function getChildChainStreamerImplementation() external view returns (IChildChainStreamer);
/**
* @notice Returns the address of the gauge belonging to `pool`.
*/
function getPoolGauge(address pool) external view returns (ILiquidityGauge);
/**
* @notice Returns the address of the streamer belonging to `gauge`.
*/
function getGaugeStreamer(address gauge) external view returns (address);
/**
* @notice Returns true if `streamer` was created by this factory.
*/
function isStreamerFromFactory(address streamer) external view returns (bool);
/**
* @notice Returns the address of the pool which `gauge` belongs.
*/
function getGaugePool(address gauge) external view returns (IERC20);
/**
* @notice Returns the address of the streamer belonging to `pool`'s gauge.
*/
function getPoolStreamer(address pool) external view returns (address);
}

View File

@@ -0,0 +1,35 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
// naming convention.
// solhint-disable func-name-mixedcase
interface IChildChainStreamer {
function initialize(address gauge) external;
function get_reward() external;
function reward_tokens(uint256 index) external view returns (IERC20);
function add_reward(
IERC20 rewardToken,
address distributor,
uint256 duration
) external;
}

View File

@@ -0,0 +1,168 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "../solidity-utils/openzeppelin/IERC20.sol";
import "./IVotingEscrow.sol";
/**
* @title Fee Distributor
* @notice Distributes any tokens transferred to the contract (e.g. Protocol fees and any BAL emissions) among veBAL
* holders proportionally based on a snapshot of the week at which the tokens are sent to the FeeDistributor contract.
* @dev Supports distributing arbitrarily many different tokens. In order to start distributing a new token to veBAL
* holders simply transfer the tokens to the `FeeDistributor` contract and then call `checkpointToken`.
*/
interface IFeeDistributor {
event TokenCheckpointed(IERC20 token, uint256 amount, uint256 lastCheckpointTimestamp);
event TokensClaimed(address user, IERC20 token, uint256 amount, uint256 userTokenTimeCursor);
/**
* @notice Returns the VotingEscrow (veBAL) token contract
*/
function getVotingEscrow() external view returns (IVotingEscrow);
/**
* @notice Returns the global time cursor representing the most earliest uncheckpointed week.
*/
function getTimeCursor() external view returns (uint256);
/**
* @notice Returns the user-level time cursor representing the most earliest uncheckpointed week.
* @param user - The address of the user to query.
*/
function getUserTimeCursor(address user) external view returns (uint256);
/**
* @notice Returns the token-level time cursor storing the timestamp at up to which tokens have been distributed.
* @param token - The ERC20 token address to query.
*/
function getTokenTimeCursor(IERC20 token) external view returns (uint256);
/**
* @notice Returns the user-level time cursor storing the timestamp of the latest token distribution claimed.
* @param user - The address of the user to query.
* @param token - The ERC20 token address to query.
*/
function getUserTokenTimeCursor(address user, IERC20 token) external view returns (uint256);
/**
* @notice Returns the user's cached balance of veBAL as of the provided timestamp.
* @dev Only timestamps which fall on Thursdays 00:00:00 UTC will return correct values.
* This function requires `user` to have been checkpointed past `timestamp` so that their balance is cached.
* @param user - The address of the user of which to read the cached balance of.
* @param timestamp - The timestamp at which to read the `user`'s cached balance at.
*/
function getUserBalanceAtTimestamp(address user, uint256 timestamp) external view returns (uint256);
/**
* @notice Returns the cached total supply of veBAL as of the provided timestamp.
* @dev Only timestamps which fall on Thursdays 00:00:00 UTC will return correct values.
* This function requires the contract to have been checkpointed past `timestamp` so that the supply is cached.
* @param timestamp - The timestamp at which to read the cached total supply at.
*/
function getTotalSupplyAtTimestamp(uint256 timestamp) external view returns (uint256);
/**
* @notice Returns the FeeDistributor's cached balance of `token`.
*/
function getTokenLastBalance(IERC20 token) external view returns (uint256);
/**
* @notice Returns the amount of `token` which the FeeDistributor received in the week beginning at `timestamp`.
* @param token - The ERC20 token address to query.
* @param timestamp - The timestamp corresponding to the beginning of the week of interest.
*/
function getTokensDistributedInWeek(IERC20 token, uint256 timestamp) external view returns (uint256);
// Depositing
/**
* @notice Deposits tokens to be distributed in the current week.
* @dev Sending tokens directly to the FeeDistributor instead of using `depositTokens` may result in tokens being
* retroactively distributed to past weeks, or for the distribution to carry over to future weeks.
*
* If for some reason `depositTokens` cannot be called, in order to ensure that all tokens are correctly distributed
* manually call `checkpointToken` before and after the token transfer.
* @param token - The ERC20 token address to distribute.
* @param amount - The amount of tokens to deposit.
*/
function depositToken(IERC20 token, uint256 amount) external;
/**
* @notice Deposits tokens to be distributed in the current week.
* @dev A version of `depositToken` which supports depositing multiple `tokens` at once.
* See `depositToken` for more details.
* @param tokens - An array of ERC20 token addresses to distribute.
* @param amounts - An array of token amounts to deposit.
*/
function depositTokens(IERC20[] calldata tokens, uint256[] calldata amounts) external;
// Checkpointing
/**
* @notice Caches the total supply of veBAL at the beginning of each week.
* This function will be called automatically before claiming tokens to ensure the contract is properly updated.
*/
function checkpoint() external;
/**
* @notice Caches the user's balance of veBAL at the beginning of each week.
* This function will be called automatically before claiming tokens to ensure the contract is properly updated.
* @param user - The address of the user to be checkpointed.
*/
function checkpointUser(address user) external;
/**
* @notice Assigns any newly-received tokens held by the FeeDistributor to weekly distributions.
* @dev Any `token` balance held by the FeeDistributor above that which is returned by `getTokenLastBalance`
* will be distributed evenly across the time period since `token` was last checkpointed.
*
* This function will be called automatically before claiming tokens to ensure the contract is properly updated.
* @param token - The ERC20 token address to be checkpointed.
*/
function checkpointToken(IERC20 token) external;
/**
* @notice Assigns any newly-received tokens held by the FeeDistributor to weekly distributions.
* @dev A version of `checkpointToken` which supports checkpointing multiple tokens.
* See `checkpointToken` for more details.
* @param tokens - An array of ERC20 token addresses to be checkpointed.
*/
function checkpointTokens(IERC20[] calldata tokens) external;
// Claiming
/**
* @notice Claims all pending distributions of the provided token for a user.
* @dev It's not necessary to explicitly checkpoint before calling this function, it will ensure the FeeDistributor
* is up to date before calculating the amount of tokens to be claimed.
* @param user - The user on behalf of which to claim.
* @param token - The ERC20 token address to be claimed.
* @return The amount of `token` sent to `user` as a result of claiming.
*/
function claimToken(address user, IERC20 token) external returns (uint256);
/**
* @notice Claims a number of tokens on behalf of a user.
* @dev A version of `claimToken` which supports claiming multiple `tokens` on behalf of `user`.
* See `claimToken` for more details.
* @param user - The user on behalf of which to claim.
* @param tokens - An array of ERC20 token addresses to be claimed.
* @return An array of the amounts of each token in `tokens` sent to `user` as a result of claiming.
*/
function claimTokens(address user, IERC20[] calldata tokens) external returns (uint256[] memory);
}

View File

@@ -0,0 +1,97 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "./IAuthorizerAdaptorEntrypoint.sol";
import "./IGaugeController.sol";
import "./ILiquidityGauge.sol";
import "./ILiquidityGaugeFactory.sol";
import "./IStakingLiquidityGauge.sol";
interface IGaugeAdder is IAuthentication {
enum GaugeType { LiquidityMiningCommittee, veBAL, Ethereum, Polygon, Arbitrum, Optimism, Gnosis, ZKSync }
event GaugeFactoryAdded(GaugeType indexed gaugeType, ILiquidityGaugeFactory gaugeFactory);
/**
* @notice Returns the address of the Authorizer adaptor entrypoint contract.
*/
function getAuthorizerAdaptorEntrypoint() external view returns (IAuthorizerAdaptorEntrypoint);
/**
* @notice Returns the address of the Gauge Controller
*/
function getGaugeController() external view returns (IGaugeController);
/**
* @notice Returns the `index`'th factory for gauge type `gaugeType`
*/
function getFactoryForGaugeType(GaugeType gaugeType, uint256 index) external view returns (address);
/**
* @notice Returns the number of factories for gauge type `gaugeType`
*/
function getFactoryForGaugeTypeCount(GaugeType gaugeType) external view returns (uint256);
/**
* @notice Returns whether `gauge` has been deployed by one of the listed factories for the gauge type `gaugeType`
*/
function isGaugeFromValidFactory(address gauge, GaugeType gaugeType) external view returns (bool);
/**
* @notice Adds a new gauge to the GaugeController for the "Ethereum" type.
*/
function addEthereumGauge(IStakingLiquidityGauge gauge) external;
/**
* @notice Adds a new gauge to the GaugeController for the "Polygon" type.
* This function must be called with the address of the *root* gauge which is deployed on Ethereum mainnet.
* It should not be called with the address of the gauge which is deployed on Polygon
*/
function addPolygonGauge(address rootGauge) external;
/**
* @notice Adds a new gauge to the GaugeController for the "Arbitrum" type.
* This function must be called with the address of the *root* gauge which is deployed on Ethereum mainnet.
* It should not be called with the address of the gauge which is deployed on Arbitrum
*/
function addArbitrumGauge(address rootGauge) external;
/**
* @notice Adds a new gauge to the GaugeController for the "Optimism" type.
* This function must be called with the address of the *root* gauge which is deployed on Ethereum mainnet.
* It should not be called with the address of the gauge which is deployed on Optimism.
*/
function addOptimismGauge(address rootGauge) external;
/**
* @notice Adds a new gauge to the GaugeController for the "Gnosis" type.
* This function must be called with the address of the *root* gauge which is deployed on Ethereum mainnet.
* It should not be called with the address of the gauge which is deployed on Gnosis Chain.
*/
function addGnosisGauge(address rootGauge) external;
/**
* @notice Adds a new gauge to the GaugeController for the "ZKSync" type.
* This function must be called with the address of the *root* gauge which is deployed on Ethereum mainnet.
* It should not be called with the address of the gauge which is deployed on ZKSync.
*/
function addZKSyncGauge(address rootGauge) external;
/**
* @notice Adds `factory` as an allowlisted factory contract for gauges with type `gaugeType`.
*/
function addGaugeFactory(ILiquidityGaugeFactory factory, GaugeType gaugeType) external;
}

View File

@@ -0,0 +1,48 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
import "./IAuthorizerAdaptor.sol";
import "./IVotingEscrow.sol";
// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
// naming convention.
// solhint-disable func-name-mixedcase
interface IGaugeController {
function checkpoint_gauge(address gauge) external;
function gauge_relative_weight(address gauge, uint256 time) external view returns (uint256);
function voting_escrow() external view returns (IVotingEscrow);
function token() external view returns (IERC20);
function add_type(string calldata name, uint256 weight) external;
function change_type_weight(int128 typeId, uint256 weight) external;
function add_gauge(address gauge, int128 gaugeType) external;
function n_gauge_types() external view returns (int128);
function gauge_types(address gauge) external view returns (int128);
function admin() external view returns (IAuthorizerAdaptor);
function gauge_exists(address gauge) external view returns (bool);
}

View File

@@ -0,0 +1,109 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.7.0;
import "./IGaugeAdder.sol";
import "./IStakelessGauge.sol";
/**
* @title L2 Gauge Checkpointer interface
* @notice Manages checkpoints for L2 gauges, allowing to perform mutiple checkpoints in a single call.
* @dev Supports Polygon, Arbitrum, Optimism, Gnosis and ZKSync stakeless root gauges. Gauges to be checkpointed need
* to be added to the controller beforehand.
*/
interface IL2GaugeCheckpointer {
/**
* @dev Emitted when a gauge is added to the checkpointer.
*/
event GaugeAdded(IGaugeAdder.GaugeType indexed gaugeType, IStakelessGauge indexed gauge);
/**
* @dev Emitted when a gauge is removed from the checkpointer.
*/
event GaugeRemoved(IGaugeAdder.GaugeType indexed gaugeType, IStakelessGauge indexed gauge);
/**
* @dev Adds an array of gauges from the given type.
* Gauges added will be considered when performing checkpoints.
* The gauges to add should meet the following preconditions:
* - They must have been created in a valid GaugeFactory, according to GaugeAdder#isGaugeFromValidFactory.
* - They must exist in the GaugeController, according to GaugeController#gauge_exists.
* - They must not be killed.
* - They must not have been previously added to the checkpointer.
* @param gaugeType - Type of the gauge.
* @param gauges - Gauges to add.
*/
function addGauges(IGaugeAdder.GaugeType gaugeType, IStakelessGauge[] calldata gauges) external;
/**
* @dev Removes an array of gauges from the given type.
* Removed gauges will not be considered when performing checkpoints. To remove gauges:
* - They must be killed.
* - They must have been previously added to the checkpointer.
* @param gaugeType - Type of the gauge.
* @param gauges - Gauges to remove.
*/
function removeGauges(IGaugeAdder.GaugeType gaugeType, IStakelessGauge[] calldata gauges) external;
/**
* @dev Returns true if the given gauge was added for the given type; false otherwise.
* @param gaugeType - Type of the gauge.
* @param gauge - Gauge to check.
*/
function hasGauge(IGaugeAdder.GaugeType gaugeType, IStakelessGauge gauge) external view returns (bool);
/**
* @dev Returns the amount of added gauges for a given type.
* @param gaugeType - Type of the gauge.
*/
function getTotalGauges(IGaugeAdder.GaugeType gaugeType) external view returns (uint256);
/**
* @dev Returns the gauge of a given type at the given index.
* Reverts if the index is greater than or equal to the amount of added gauges for the given type.
* @param gaugeType - Type of the gauge.
* @param index - Index of the added gauge.
*/
function getGaugeAtIndex(IGaugeAdder.GaugeType gaugeType, uint256 index) external view returns (IStakelessGauge);
/**
* @dev Performs a checkpoint for all added gauges above the given relative weight threshold.
* Reverts if the ETH sent in the call is not enough to cover bridge costs.
* @param minRelativeWeight - Threshold to filter out gauges below it.
*/
function checkpointGaugesAboveRelativeWeight(uint256 minRelativeWeight) external payable;
/**
* @dev Performs a checkpoint for all added gauges of a given type above the given relative weight threshold.
* Reverts if the ETH sent in the call is not enough to cover bridge costs.
* @param gaugeType - Type of the gauge.
* @param minRelativeWeight - Threshold to filter out gauges below it.
*/
function checkpointGaugesOfTypeAboveRelativeWeight(IGaugeAdder.GaugeType gaugeType, uint256 minRelativeWeight)
external
payable;
/**
* @dev Returns the ETH cost to checkpoint all gauges for a given minimum relative weight.
* A lower minimum relative weight might return higher costs, since more gauges could potentially be included
* in the checkpoint.
*/
function getTotalBridgeCost(uint256 minRelativeWeight) external view returns (uint256);
/**
* @dev Returns true if gauge type is Polygon, Arbitrum, Optimism, Gnosis or ZKSync; false otherwise.
*/
function isSupportedGaugeType(IGaugeAdder.GaugeType gaugeType) external pure returns (bool);
}

View File

@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "./IBalancerTokenAdmin.sol";
import "./IGaugeController.sol";
interface ILMGetters {
/**
* @notice Returns the address of the Balancer Token Admin contract
*/
function getBalancerTokenAdmin() external view returns (IBalancerTokenAdmin);
/**
* @notice Returns the address of the Gauge Controller
*/
function getGaugeController() external view returns (IGaugeController);
}

View File

@@ -0,0 +1,72 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
// naming convention.
// solhint-disable func-name-mixedcase
// solhint-disable func-param-name-mixedcase
interface ILiquidityGauge {
// solhint-disable-next-line var-name-mixedcase
event RelativeWeightCapChanged(uint256 new_relative_weight_cap);
/**
* @notice Returns BAL liquidity emissions calculated during checkpoints for the given user.
* @param user User address.
* @return uint256 BAL amount to issue for the address.
*/
function integrate_fraction(address user) external view returns (uint256);
/**
* @notice Record a checkpoint for a given user.
* @param user User address.
* @return bool Always true.
*/
function user_checkpoint(address user) external returns (bool);
/**
* @notice Returns true if gauge is killed; false otherwise.
*/
function is_killed() external view returns (bool);
/**
* @notice Kills the gauge so it cannot mint BAL.
*/
function killGauge() external;
/**
* @notice Unkills the gauge so it can mint BAL again.
*/
function unkillGauge() external;
/**
* @notice Sets a new relative weight cap for the gauge.
* The value shall be normalized to 1e18, and not greater than MAX_RELATIVE_WEIGHT_CAP.
* @param relativeWeightCap New relative weight cap.
*/
function setRelativeWeightCap(uint256 relativeWeightCap) external;
/**
* @notice Gets the relative weight cap for the gauge.
*/
function getRelativeWeightCap() external view returns (uint256);
/**
* @notice Returns the gauge's relative weight for a given time, capped to its relative weight cap attribute.
* @param time Timestamp in the past or present.
*/
function getCappedRelativeWeight(uint256 time) external view returns (uint256);
}

View File

@@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "./ILiquidityGauge.sol";
interface ILiquidityGaugeFactory {
/**
* @notice Returns true if `gauge` was created by this factory.
*/
function isGaugeFromFactory(address gauge) external view returns (bool);
}

View File

@@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "./IBalancerMinter.sol";
import "./ILMGetters.sol";
/**
* @dev Full L1 Balancer minter interface with singleton getters.
*/
interface IMainnetBalancerMinter is IBalancerMinter, ILMGetters {
// solhint-disable-previous-line no-empty-blocks
}

View File

@@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
interface IOptimismGasLimitProvider {
function getOptimismGasLimit() external view returns (uint32 gasLimit);
function setOptimismGasLimit(uint32 gasLimit) external;
}

View File

@@ -0,0 +1,49 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "../solidity-utils/openzeppelin/IERC20.sol";
// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
// naming convention.
// solhint-disable func-name-mixedcase, var-name-mixedcase
interface IRewardTokenDistributor {
struct Reward {
IERC20 token;
address distributor;
uint256 period_finish;
uint256 rate;
uint256 last_update;
uint256 integral;
}
function reward_tokens(uint256 index) external view returns (IERC20);
function reward_data(IERC20 token) external view returns (Reward memory);
function claim_rewards(address user) external;
function add_reward(IERC20 rewardToken, address distributor) external;
function set_reward_distributor(IERC20 rewardToken, address distributor) external;
function deposit_reward_token(IERC20 rewardToken, uint256 amount) external;
function claimable_reward(address rewardToken, address user) external view returns (uint256);
function claimable_reward_write(address rewardToken, address user) external returns (uint256);
}

View File

@@ -0,0 +1,43 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "./IChildChainStreamer.sol";
import "./IRewardTokenDistributor.sol";
// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
// naming convention.
// solhint-disable func-name-mixedcase
interface IRewardsOnlyGauge is IRewardTokenDistributor {
function initialize(
address pool,
address streamer,
bytes32 claimSignature
) external;
// solhint-disable-next-line func-name-mixedcase
function lp_token() external view returns (IERC20);
function reward_contract() external view returns (IChildChainStreamer);
function set_rewards(
address childChainStreamer,
bytes32 claimSig,
address[8] calldata rewardTokens
) external;
function last_claim() external view returns (uint256);
}

View File

@@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
interface ISmartWalletChecker {
function check(address contractAddress) external view returns (bool);
}

View File

@@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "./ILiquidityGauge.sol";
interface IStakelessGauge is ILiquidityGauge {
function checkpoint() external payable returns (bool);
function getRecipient() external view returns (address);
}

View File

@@ -0,0 +1,35 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "../solidity-utils/openzeppelin/IERC20.sol";
import "./ILiquidityGauge.sol";
import "./IRewardTokenDistributor.sol";
// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
// naming convention.
// solhint-disable func-name-mixedcase, var-name-mixedcase
interface IStakingLiquidityGauge is IRewardTokenDistributor, ILiquidityGauge, IERC20 {
function initialize(address lpToken, uint256 relativeWeightCap) external;
function lp_token() external view returns (IERC20);
function deposit(uint256 value, address recipient) external;
function withdraw(uint256 value) external;
}

View File

@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
// naming convention.
// solhint-disable func-name-mixedcase
interface IVeDelegation {
// solhint-disable-next-line func-name-mixedcase
function adjusted_balance_of(address user) external view returns (uint256);
function totalSupply() external view returns (uint256);
}

View File

@@ -0,0 +1,51 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "./IAuthorizerAdaptor.sol";
// For compatibility, we're keeping the same function names as in the original Curve code, including the mixed-case
// naming convention.
// solhint-disable func-name-mixedcase
interface IVotingEscrow {
struct Point {
int128 bias;
int128 slope; // - dweight / dt
uint256 ts;
uint256 blk; // block
}
function epoch() external view returns (uint256);
function totalSupply(uint256 timestamp) external view returns (uint256);
function user_point_epoch(address user) external view returns (uint256);
function point_history(uint256 timestamp) external view returns (Point memory);
function user_point_history(address user, uint256 timestamp) external view returns (Point memory);
function checkpoint() external;
function admin() external view returns (IAuthorizerAdaptor);
function smart_wallet_checker() external view returns (address);
function commit_smart_wallet_checker(address newSmartWalletChecker) external;
function apply_smart_wallet_checker() external;
}

View File

@@ -0,0 +1,67 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
/**
* @title IERC4626, to support the yield-bearing token standard.
* @notice Used for ERC4626-derived Linear Pools.
* @dev There is another version of this in /solidity-utils/misc, used in standalone-utils tests.
* This version has an additional `previewMint` function, and is used in tests of derived Linear Pools.
*/
interface IERC4626 {
/**
* @dev Mints `shares` Vault shares to `receiver` by depositing exactly `amount` of underlying tokens.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Burns exactly `shares` from `owner` and sends `assets` of underlying tokens to `receiver`.
*/
function redeem(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
/**
* @dev The address of the underlying token that the Vault uses for accounting, depositing, and withdrawing.
*/
function asset() external view returns (address);
/**
* @dev Total amount of the underlying asset that is “managed” by Vault.
*/
function totalAssets() external view returns (uint256);
/**
* @dev The amount of `assets` that the Vault would exchange for the amount
* of `shares` provided, in an ideal scenario where all the conditions are met.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev The amount of `shares` that the Vault would exchange for the amount
* of `assets` provided, in an ideal scenario where all the conditions are met.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block,
* given current on-chain conditions. MUST return as close to and no fewer than the exact amount of assets that
* would be deposited in a mint call in the same transaction. I.e. mint should return the same or fewer assets
* as previewMint if called in the same transaction.
*/
function previewMint(uint256 shares) external view returns (uint256 assets);
}

View File

@@ -0,0 +1,84 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "../solidity-utils/openzeppelin/IERC20.sol";
import "../vault/IBasePool.sol";
interface ILinearPool is IBasePool {
/**
* @dev Returns the Pool's main token.
*/
function getMainToken() external view returns (IERC20);
/**
* @dev Returns the Pool's wrapped token.
*/
function getWrappedToken() external view returns (IERC20);
/**
* @dev Returns the index of the Pool's BPT in the Pool tokens array (as returned by IVault.getPoolTokens).
*/
function getBptIndex() external view returns (uint256);
/**
* @dev Returns the index of the Pool's main token in the Pool tokens array (as returned by IVault.getPoolTokens).
*/
function getMainIndex() external view returns (uint256);
/**
* @dev Returns the index of the Pool's wrapped token in the Pool tokens array (as returned by
* IVault.getPoolTokens).
*/
function getWrappedIndex() external view returns (uint256);
/**
* @dev Returns the Pool's targets for the main token balance. These values have had the main token's scaling
* factor applied to them.
*/
function getTargets() external view returns (uint256 lowerTarget, uint256 upperTarget);
/**
* @notice Set the lower and upper bounds of the zero-fee trading range for the main token balance.
* @dev For a new target range to be valid:
* - the current balance must be between the current targets (meaning no fees are currently pending)
* - the current balance must be between the new targets (meaning setting them does not create pending fees)
*
* The first requirement could be relaxed, as the LPs actually benefit from the pending fees not being paid out,
* but being stricter makes analysis easier at little expense.
*
* This is a permissioned function, reserved for the pool owner. It will revert when called within a Vault context
* (i.e. in the middle of a join or an exit).
*
* Correct behavior depends on the token balances from the Vault, which may be out of sync with the state of
* the pool during execution of a Vault hook.
*
* See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
*/
function setTargets(uint256 newLowerTarget, uint256 newUpperTarget) external;
/**
* @notice Set the swap fee percentage.
* @dev This is a permissioned function, reserved for the pool owner. It will revert when called within a Vault
* context (i.e. in the middle of a join or an exit).
*
* Correct behavior depends on the token balances from the Vault, which may be out of sync with the state of
* the pool during execution of a Vault hook.
*
* See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
*/
function setSwapFeePercentage(uint256 swapFeePercentage) external;
}

View File

@@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
interface IComposableStablePoolRates {
/**
* @dev Forces a rate cache hit for a token.
* It will revert if the requested token does not have an associated rate provider.
*/
function updateTokenRateCache(IERC20 token) external;
/**
* @dev Sets a new duration for a token rate cache. It reverts if there was no rate provider set initially.
* Note this function also updates the current cached value.
* @param duration Number of seconds until the current token rate is fetched again.
*/
function setTokenRateCacheDuration(IERC20 token, uint256 duration) external;
}

View File

@@ -0,0 +1,68 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
library StablePoolUserData {
enum JoinKind { INIT, EXACT_TOKENS_IN_FOR_BPT_OUT, TOKEN_IN_FOR_EXACT_BPT_OUT, ALL_TOKENS_IN_FOR_EXACT_BPT_OUT }
enum ExitKind { EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, BPT_IN_FOR_EXACT_TOKENS_OUT, EXACT_BPT_IN_FOR_ALL_TOKENS_OUT }
function joinKind(bytes memory self) internal pure returns (JoinKind) {
return abi.decode(self, (JoinKind));
}
function exitKind(bytes memory self) internal pure returns (ExitKind) {
return abi.decode(self, (ExitKind));
}
// Joins
function initialAmountsIn(bytes memory self) internal pure returns (uint256[] memory amountsIn) {
(, amountsIn) = abi.decode(self, (JoinKind, uint256[]));
}
function exactTokensInForBptOut(bytes memory self)
internal
pure
returns (uint256[] memory amountsIn, uint256 minBPTAmountOut)
{
(, amountsIn, minBPTAmountOut) = abi.decode(self, (JoinKind, uint256[], uint256));
}
function tokenInForExactBptOut(bytes memory self) internal pure returns (uint256 bptAmountOut, uint256 tokenIndex) {
(, bptAmountOut, tokenIndex) = abi.decode(self, (JoinKind, uint256, uint256));
}
function allTokensInForExactBptOut(bytes memory self) internal pure returns (uint256 bptAmountOut) {
(, bptAmountOut) = abi.decode(self, (JoinKind, uint256));
}
// Exits
function exactBptInForTokenOut(bytes memory self) internal pure returns (uint256 bptAmountIn, uint256 tokenIndex) {
(, bptAmountIn, tokenIndex) = abi.decode(self, (ExitKind, uint256, uint256));
}
function exactBptInForTokensOut(bytes memory self) internal pure returns (uint256 bptAmountIn) {
(, bptAmountIn) = abi.decode(self, (ExitKind, uint256));
}
function bptInForExactTokensOut(bytes memory self)
internal
pure
returns (uint256[] memory amountsOut, uint256 maxBPTAmountIn)
{
(, amountsOut, maxBPTAmountIn) = abi.decode(self, (ExitKind, uint256[], uint256));
}
}

View File

@@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
library BasePoolUserData {
// Special ExitKind for all pools, used in Recovery Mode. Use the max 8-bit value to prevent conflicts
// with future additions to the ExitKind enums (or any front-end code that maps to existing values)
uint8 public constant RECOVERY_MODE_EXIT_KIND = 255;
// Return true if this is the special exit kind.
function isRecoveryModeExitKind(bytes memory self) internal pure returns (bool) {
// Check for the "no data" case, or abi.decode would revert
return self.length > 0 && abi.decode(self, (uint8)) == RECOVERY_MODE_EXIT_KIND;
}
// Parse the bptAmountIn out of the userData
function recoveryModeExit(bytes memory self) internal pure returns (uint256 bptAmountIn) {
(, bptAmountIn) = abi.decode(self, (uint8, uint256));
}
}

View File

@@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
interface IBasePoolController {
function initialize(address poolAddress) external;
}

View File

@@ -0,0 +1,36 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "../solidity-utils/helpers/IAuthentication.sol";
interface IBasePoolFactory is IAuthentication {
/**
* @dev Returns true if `pool` was created by this factory.
*/
function isPoolFromFactory(address pool) external view returns (bool);
/**
* @dev Check whether the derived factory has been disabled.
*/
function isDisabled() external view returns (bool);
/**
* @dev Disable the factory, preventing the creation of more pools. Already existing pools are unaffected.
* Once a factory is disabled, it cannot be re-enabled.
*/
function disable() external;
}

View File

@@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
interface IControlledPool {
function setSwapFeePercentage(uint256 swapFeePercentage) external;
}

View File

@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
/**
* @notice Simple interface to retrieve the version of pools deployed by a pool factory.
*/
interface IFactoryCreatedPoolVersion {
/**
* @dev Returns a JSON representation of the deployed pool version containing name, version number and task ID.
*
* This is typically only useful in complex Pool deployment schemes, where multiple subsystems need to know about
* each other. Note that this value will only be updated at factory creation time.
*/
function getPoolVersion() external view returns (string memory);
}

View File

@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "./IBasePoolFactory.sol";
interface ILastCreatedPoolFactory is IBasePoolFactory {
/**
* @dev Returns the address of the last Pool created by this factory.
*
* This is typically only useful in complex Pool deployment schemes, where multiple subsystems need to know about
* each other. Note that this value will only be updated once construction of the last created Pool finishes.
*/
function getLastCreatedPool() external view returns (address);
}

View File

@@ -0,0 +1,363 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
import "../vault/IBasePool.sol";
interface IManagedPool is IBasePool {
event GradualSwapFeeUpdateScheduled(
uint256 startTime,
uint256 endTime,
uint256 startSwapFeePercentage,
uint256 endSwapFeePercentage
);
event GradualWeightUpdateScheduled(
uint256 startTime,
uint256 endTime,
uint256[] startWeights,
uint256[] endWeights
);
event SwapEnabledSet(bool swapEnabled);
event JoinExitEnabledSet(bool joinExitEnabled);
event MustAllowlistLPsSet(bool mustAllowlistLPs);
event AllowlistAddressAdded(address indexed member);
event AllowlistAddressRemoved(address indexed member);
event ManagementAumFeePercentageChanged(uint256 managementAumFeePercentage);
event ManagementAumFeeCollected(uint256 bptAmount);
event CircuitBreakerSet(
IERC20 indexed token,
uint256 bptPrice,
uint256 lowerBoundPercentage,
uint256 upperBoundPercentage
);
event TokenAdded(IERC20 indexed token, uint256 normalizedWeight);
event TokenRemoved(IERC20 indexed token);
/**
* @notice Returns the effective BPT supply.
*
* @dev The Pool owes debt to the Protocol and the Pool's owner in the form of unminted BPT, which will be minted
* immediately before the next join or exit. We need to take these into account since, even if they don't yet exist,
* they will effectively be included in any Pool operation that involves BPT.
*
* In the vast majority of cases, this function should be used instead of `totalSupply()`.
*
* WARNING: since this function reads balances directly from the Vault, it is potentially subject to manipulation
* via reentrancy. See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
*
* To call this function safely, attempt to trigger the reentrancy guard in the Vault by calling a non-reentrant
* function before calling `getActualSupply`. That will make the transaction revert in an unsafe context.
* (See `whenNotInVaultContext` in `ManagedPoolSettings`).
*/
function getActualSupply() external view returns (uint256);
// Swap fee percentage
/**
* @notice Schedule a gradual swap fee update.
* @dev The swap fee will change from the given starting value (which may or may not be the current
* value) to the given ending fee percentage, over startTime to endTime.
*
* Note that calling this with a starting swap fee different from the current value will immediately change the
* current swap fee to `startSwapFeePercentage`, before commencing the gradual change at `startTime`.
* Emits the GradualSwapFeeUpdateScheduled event.
* This is a permissioned function.
*
* @param startTime - The timestamp when the swap fee change will begin.
* @param endTime - The timestamp when the swap fee change will end (must be >= startTime).
* @param startSwapFeePercentage - The starting value for the swap fee change.
* @param endSwapFeePercentage - The ending value for the swap fee change. If the current timestamp >= endTime,
* `getSwapFeePercentage()` will return this value.
*/
function updateSwapFeeGradually(
uint256 startTime,
uint256 endTime,
uint256 startSwapFeePercentage,
uint256 endSwapFeePercentage
) external;
/**
* @notice Returns the current gradual swap fee update parameters.
* @dev The current swap fee can be retrieved via `getSwapFeePercentage()`.
* @return startTime - The timestamp when the swap fee update will begin.
* @return endTime - The timestamp when the swap fee update will end.
* @return startSwapFeePercentage - The starting swap fee percentage (could be different from the current value).
* @return endSwapFeePercentage - The final swap fee percentage, when the current timestamp >= endTime.
*/
function getGradualSwapFeeUpdateParams()
external
view
returns (
uint256 startTime,
uint256 endTime,
uint256 startSwapFeePercentage,
uint256 endSwapFeePercentage
);
// Token weights
/**
* @notice Schedule a gradual weight change.
* @dev The weights will change from their current values to the given endWeights, over startTime to endTime.
* This is a permissioned function.
*
* Since, unlike with swap fee updates, we generally do not want to allow instantaneous weight changes,
* the weights always start from their current values. This also guarantees a smooth transition when
* updateWeightsGradually is called during an ongoing weight change.
* @param startTime - The timestamp when the weight change will begin.
* @param endTime - The timestamp when the weight change will end (can be >= startTime).
* @param tokens - The tokens associated with the target weights (must match the current pool tokens).
* @param endWeights - The target weights. If the current timestamp >= endTime, `getNormalizedWeights()`
* will return these values.
*/
function updateWeightsGradually(
uint256 startTime,
uint256 endTime,
IERC20[] memory tokens,
uint256[] memory endWeights
) external;
/**
* @notice Returns all normalized weights, in the same order as the Pool's tokens.
*/
function getNormalizedWeights() external view returns (uint256[] memory);
/**
* @notice Returns the current gradual weight change update parameters.
* @dev The current weights can be retrieved via `getNormalizedWeights()`.
* @return startTime - The timestamp when the weight update will begin.
* @return endTime - The timestamp when the weight update will end.
* @return startWeights - The starting weights, when the weight change was initiated.
* @return endWeights - The final weights, when the current timestamp >= endTime.
*/
function getGradualWeightUpdateParams()
external
view
returns (
uint256 startTime,
uint256 endTime,
uint256[] memory startWeights,
uint256[] memory endWeights
);
// Join and Exit enable/disable
/**
* @notice Enable or disable joins and exits. Note that this does not affect Recovery Mode exits.
* @dev Emits the JoinExitEnabledSet event. This is a permissioned function.
* @param joinExitEnabled - The new value of the join/exit enabled flag.
*/
function setJoinExitEnabled(bool joinExitEnabled) external;
/**
* @notice Returns whether joins and exits are enabled.
*/
function getJoinExitEnabled() external view returns (bool);
// Swap enable/disable
/**
* @notice Enable or disable trading.
* @dev Emits the SwapEnabledSet event. This is a permissioned function.
* @param swapEnabled - The new value of the swap enabled flag.
*/
function setSwapEnabled(bool swapEnabled) external;
/**
* @notice Returns whether swaps are enabled.
*/
function getSwapEnabled() external view returns (bool);
// LP Allowlist
/**
* @notice Enable or disable the LP allowlist.
* @dev Note that any addresses added to the allowlist will be retained if the allowlist is toggled off and
* back on again, because this action does not affect the list of LP addresses.
* Emits the MustAllowlistLPsSet event. This is a permissioned function.
* @param mustAllowlistLPs - The new value of the mustAllowlistLPs flag.
*/
function setMustAllowlistLPs(bool mustAllowlistLPs) external;
/**
* @notice Adds an address to the LP allowlist.
* @dev Will fail if the address is already allowlisted.
* Emits the AllowlistAddressAdded event. This is a permissioned function.
* @param member - The address to be added to the allowlist.
*/
function addAllowedAddress(address member) external;
/**
* @notice Removes an address from the LP allowlist.
* @dev Will fail if the address was not previously allowlisted.
* Emits the AllowlistAddressRemoved event. This is a permissioned function.
* @param member - The address to be removed from the allowlist.
*/
function removeAllowedAddress(address member) external;
/**
* @notice Returns whether the allowlist for LPs is enabled.
*/
function getMustAllowlistLPs() external view returns (bool);
/**
* @notice Check whether an LP address is on the allowlist.
* @dev This simply checks the list, regardless of whether the allowlist feature is enabled.
* @param member - The address to check against the allowlist.
* @return true if the given address is on the allowlist.
*/
function isAddressOnAllowlist(address member) external view returns (bool);
// Management fees
/**
* @notice Collect any accrued AUM fees and send them to the pool manager.
* @dev This can be called by anyone to collect accrued AUM fees - and will be called automatically
* whenever the supply changes (e.g., joins and exits, add and remove token), and before the fee
* percentage is changed by the manager, to prevent fees from being applied retroactively.
*
* Correct behavior depends on the current supply, which is potentially manipulable if the pool
* is reentered during execution of a Vault hook. This is protected where overridden in ManagedPoolSettings,
* and so is safe to call on ManagedPool.
*
* See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
*
* @return The amount of BPT minted to the manager.
*/
function collectAumManagementFees() external returns (uint256);
/**
* @notice Setter for the yearly percentage AUM management fee, which is payable to the pool manager.
* @dev Attempting to collect AUM fees in excess of the maximum permitted percentage will revert.
* To avoid retroactive fee increases, we force collection at the current fee percentage before processing
* the update. Emits the ManagementAumFeePercentageChanged event. This is a permissioned function.
*
* To prevent changing management fees retroactively, this triggers payment of protocol fees before applying
* the change. Correct behavior depends on the current supply, which is potentially manipulable if the pool
* is reentered during execution of a Vault hook. This is protected where overridden in ManagedPoolSettings,
* and so is safe to call on ManagedPool.
*
* See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
*
* @param managementAumFeePercentage - The new management AUM fee percentage.
* @return amount - The amount of BPT minted to the manager before the update, if any.
*/
function setManagementAumFeePercentage(uint256 managementAumFeePercentage) external returns (uint256);
/**
* @notice Returns the management AUM fee percentage as an 18-decimal fixed point number and the timestamp of the
* last collection of AUM fees.
*/
function getManagementAumFeeParams()
external
view
returns (uint256 aumFeePercentage, uint256 lastCollectionTimestamp);
// Circuit Breakers
/**
* @notice Set a circuit breaker for one or more tokens.
* @dev This is a permissioned function. The lower and upper bounds are percentages, corresponding to a
* relative change in the token's spot price: e.g., a lower bound of 0.8 means the breaker should prevent
* trades that result in the value of the token dropping 20% or more relative to the rest of the pool.
*/
function setCircuitBreakers(
IERC20[] memory tokens,
uint256[] memory bptPrices,
uint256[] memory lowerBoundPercentages,
uint256[] memory upperBoundPercentages
) external;
/**
* @notice Return the full circuit breaker state for the given token.
* @dev These are the reference values (BPT price and reference weight) passed in when the breaker was set,
* along with the percentage bounds. It also returns the current BPT price bounds, needed to check whether
* the circuit breaker should trip.
*/
function getCircuitBreakerState(IERC20 token)
external
view
returns (
uint256 bptPrice,
uint256 referenceWeight,
uint256 lowerBound,
uint256 upperBound,
uint256 lowerBptPriceBound,
uint256 upperBptPriceBound
);
// Add/remove tokens
/**
* @notice Adds a token to the Pool's list of tradeable tokens. This is a permissioned function.
*
* @dev By adding a token to the Pool's composition, the weights of all other tokens will be decreased. The new
* token will have no balance - it is up to the owner to provide some immediately after calling this function.
* Note however that regular join functions will not work while the new token has no balance: the only way to
* deposit an initial amount is by using an Asset Manager.
*
* Token addition is forbidden during a weight change, or if one is scheduled to happen in the future.
*
* The caller may additionally pass a non-zero `mintAmount` to have some BPT be minted for them, which might be
* useful in some scenarios to account for the fact that the Pool will have more tokens.
*
* Emits the TokenAdded event. This is a permissioned function.
*
* Correct behavior depends on the token balances from the Vault, which may be out of sync with the state of
* the pool during execution of a Vault hook. This is protected where overridden in ManagedPoolSettings,
* and so is safe to call on ManagedPool.
*
* See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
*
* @param tokenToAdd - The ERC20 token to be added to the Pool.
* @param assetManager - The Asset Manager for the token.
* @param tokenToAddNormalizedWeight - The normalized weight of `token` relative to the other tokens in the Pool.
* @param mintAmount - The amount of BPT to be minted as a result of adding `token` to the Pool.
* @param recipient - The address to receive the BPT minted by the Pool.
*/
function addToken(
IERC20 tokenToAdd,
address assetManager,
uint256 tokenToAddNormalizedWeight,
uint256 mintAmount,
address recipient
) external;
/**
* @notice Removes a token from the Pool's list of tradeable tokens.
* @dev Tokens can only be removed if the Pool has more than 2 tokens, as it can never have fewer than 2 (not
* including BPT). Token removal is also forbidden during a weight change, or if one is scheduled to happen in
* the future.
*
* Emits the TokenRemoved event. This is a permissioned function.
* Correct behavior depends on the token balances from the Vault, which may be out of sync with the state of
* the pool during execution of a Vault hook. This is protected where overridden in ManagedPoolSettings,
* and so is safe to call on ManagedPool.
*
* See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
*
* The caller may additionally pass a non-zero `burnAmount` to burn some of their BPT, which might be useful
* in some scenarios to account for the fact that the Pool now has fewer tokens. This is a permissioned function.
* @param tokenToRemove - The ERC20 token to be removed from the Pool.
* @param burnAmount - The amount of BPT to be burned after removing `token` from the Pool.
* @param sender - The address to burn BPT from.
*/
function removeToken(
IERC20 tokenToRemove,
uint256 burnAmount,
address sender
) external;
}

View File

@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
/**
* @notice Simple interface to retrieve the version of pools deployed by a pool factory.
*/
interface IPoolVersion {
/**
* @dev Returns a JSON representation of the deployed pool version containing name, version number and task ID.
*
* This is typically only useful in complex Pool deployment schemes, where multiple subsystems need to know about
* each other. Note that this value will only be updated at factory creation time.
*/
function getPoolVersion() external view returns (string memory);
}

View File

@@ -0,0 +1,29 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
interface IProtocolFeeCache {
/**
* @notice Updates the cache to the latest value set by governance.
* @dev Can be called by anyone to update the cached fee percentages.
*
* Correct behavior depends on the token balances from the Vault, which may be out of sync with the state of
* the pool during execution of a Vault hook. This is protected by a call to `ensureNotInVaultContext` in
* VaultReentrancyLib where overridden in `ProtocolFeeCache`, and so is safe to call on ManagedPool.
*
* See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
*/
function updateProtocolFeePercentageCache() external;
}

View File

@@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
interface IRateProvider {
/**
* @dev Returns an 18 decimal fixed point number that is the exchange rate of the token to some other underlying
* token. The meaning of this rate depends on the context.
*/
function getRate() external view returns (uint256);
}

View File

@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "./IRateProvider.sol";
/**
* @dev Interface for Pools that assign rate providers to their tokens.
*/
interface IRateProviderPool {
/**
* @dev Returns the rate provider for each of the Pool's tokens. A zero-address entry means there's no rate provider
* for that token.
*/
function getRateProviders() external view returns (IRateProvider[] memory);
}

View File

@@ -0,0 +1,41 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
/**
* @dev Interface for the RecoveryMode module.
*/
interface IRecoveryMode {
/**
* @dev Emitted when the Recovery Mode status changes.
*/
event RecoveryModeStateChanged(bool enabled);
/**
* @notice Enables Recovery Mode in the Pool, disabling protocol fee collection and allowing for safe proportional
* exits with low computational complexity and no dependencies.
*/
function enableRecoveryMode() external;
/**
* @notice Disables Recovery Mode in the Pool, restoring protocol fee collection and disallowing proportional exits.
*/
function disableRecoveryMode() external;
/**
* @notice Returns true if the Pool is in Recovery Mode.
*/
function inRecoveryMode() external view returns (bool);
}

View File

@@ -0,0 +1,52 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../vault/IVault.sol";
/**
* Interface for an auxiliary contract that computes Recovery Mode exits, removing logic from the core Pool contract
* that would otherwise take up a lot of bytecode size at the cost of some slight gas overhead. Since Recovery Mode
* exits are expected to be highly infrequent (and ideally never occur), this tradeoff makes sense.
*/
interface IRecoveryModeHelper {
/**
* @notice Returns the Balancer Vault
*/
function getVault() external view returns (IVault);
/**
* @dev Computes a Recovery Mode Exit BPT and token amounts for a Pool. Only 'cash' balances are considered, to
* avoid scenarios where the last LPs to attempt to exit the Pool cannot do it because only 'managed' balance
* remains.
*
* The Pool is assumed to be a Composable Pool that uses ComposablePoolLib, meaning BPT will be its first token. It
* is also assumed that there is no 'managed' balance for BPT.
* WARNING: since this function reads balances directly from the Vault, it is potentially subject to manipulation
* via reentrancy. See https://forum.balancer.fi/t/reentrancy-vulnerability-scope-expanded/4345 for reference.
*
* To call this function safely, attempt to trigger the reentrancy guard in the Vault by calling a non-reentrant
* function before calling `calcComposableRecoveryAmountsOut`. That will make the transaction revert in an unsafe
* context.
*
* (See `VaultReentrancyLib.ensureNotInVaultContext`).
*/
function calcComposableRecoveryAmountsOut(
bytes32 poolId,
bytes memory userData,
uint256 totalSupply
) external view returns (uint256 bptAmountIn, uint256[] memory amountsOut);
}

View File

@@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
/**
* @notice Simple interface to retrieve the version of a deployed contract.
*/
interface IVersion {
/**
* @dev Returns a JSON representation of the contract version containing name, version number and task ID.
*/
function version() external view returns (string memory);
}

View File

@@ -0,0 +1,203 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
/**
* @notice Interface for ExternalWeightedMath, a contract-wrapper for Weighted Math, Joins and Exits.
*/
interface IExternalWeightedMath {
/**
* @dev See `WeightedMath._calculateInvariant`.
*/
function calculateInvariant(uint256[] memory normalizedWeights, uint256[] memory balances)
external
pure
returns (uint256);
/**
* @dev See `WeightedMath._calcOutGivenIn`.
*/
function calcOutGivenIn(
uint256 balanceIn,
uint256 weightIn,
uint256 balanceOut,
uint256 weightOut,
uint256 amountIn
) external pure returns (uint256);
/**
* @dev See `WeightedMath._calcInGivenOut`.
*/
function calcInGivenOut(
uint256 balanceIn,
uint256 weightIn,
uint256 balanceOut,
uint256 weightOut,
uint256 amountOut
) external pure returns (uint256);
/**
* @dev See `WeightedMath._calcBptOutGivenExactTokensIn`.
*/
function calcBptOutGivenExactTokensIn(
uint256[] memory balances,
uint256[] memory normalizedWeights,
uint256[] memory amountsIn,
uint256 bptTotalSupply,
uint256 swapFeePercentage
) external pure returns (uint256);
/**
* @dev See `WeightedMath._calcBptOutGivenExactTokenIn`.
*/
function calcBptOutGivenExactTokenIn(
uint256 balance,
uint256 normalizedWeight,
uint256 amountIn,
uint256 bptTotalSupply,
uint256 swapFeePercentage
) external pure returns (uint256);
/**
* @dev See `WeightedMath._calcTokenInGivenExactBptOut`.
*/
function calcTokenInGivenExactBptOut(
uint256 balance,
uint256 normalizedWeight,
uint256 bptAmountOut,
uint256 bptTotalSupply,
uint256 swapFeePercentage
) external pure returns (uint256);
/**
* @dev See `WeightedMath._calcAllTokensInGivenExactBptOut`.
*/
function calcAllTokensInGivenExactBptOut(
uint256[] memory balances,
uint256 bptAmountOut,
uint256 totalBPT
) external pure returns (uint256[] memory);
/**
* @dev See `WeightedMath._calcBptInGivenExactTokensOut`.
*/
function calcBptInGivenExactTokensOut(
uint256[] memory balances,
uint256[] memory normalizedWeights,
uint256[] memory amountsOut,
uint256 bptTotalSupply,
uint256 swapFeePercentage
) external pure returns (uint256);
/**
* @dev See `WeightedMath._calcBptInGivenExactTokenOut`.
*/
function calcBptInGivenExactTokenOut(
uint256 balance,
uint256 normalizedWeight,
uint256 amountOut,
uint256 bptTotalSupply,
uint256 swapFeePercentage
) external pure returns (uint256);
/**
* @dev See `WeightedMath._calcTokenOutGivenExactBptIn`.
*/
function calcTokenOutGivenExactBptIn(
uint256 balance,
uint256 normalizedWeight,
uint256 bptAmountIn,
uint256 bptTotalSupply,
uint256 swapFeePercentage
) external pure returns (uint256);
/**
* @dev See `WeightedMath._calcTokensOutGivenExactBptIn`.
*/
function calcTokensOutGivenExactBptIn(
uint256[] memory balances,
uint256 bptAmountIn,
uint256 totalBPT
) external pure returns (uint256[] memory);
/**
* @dev See `WeightedMath._calcBptOutAddToken`.
*/
function calcBptOutAddToken(uint256 totalSupply, uint256 normalizedWeight) external pure returns (uint256);
/**
* @dev See `WeightedJoinsLib.joinExactTokensInForBPTOut`.
*/
function joinExactTokensInForBPTOut(
uint256[] memory balances,
uint256[] memory normalizedWeights,
uint256[] memory scalingFactors,
uint256 totalSupply,
uint256 swapFeePercentage,
bytes memory userData
) external pure returns (uint256, uint256[] memory);
/**
* @dev See `WeightedJoinsLib.joinTokenInForExactBPTOut`.
*/
function joinTokenInForExactBPTOut(
uint256[] memory balances,
uint256[] memory normalizedWeights,
uint256 totalSupply,
uint256 swapFeePercentage,
bytes memory userData
) external pure returns (uint256, uint256[] memory);
/**
* @dev See `WeightedJoinsLib.joinAllTokensInForExactBPTOut`.
*/
function joinAllTokensInForExactBPTOut(
uint256[] memory balances,
uint256 totalSupply,
bytes memory userData
) external pure returns (uint256 bptAmountOut, uint256[] memory amountsIn);
/**
* @dev See `WeightedExitsLib.exitExactBPTInForTokenOut`.
*/
function exitExactBPTInForTokenOut(
uint256[] memory balances,
uint256[] memory normalizedWeights,
uint256 totalSupply,
uint256 swapFeePercentage,
bytes memory userData
) external pure returns (uint256, uint256[] memory);
/**
* @dev See `WeightedExitsLib.exitExactBPTInForTokensOut`.
*/
function exitExactBPTInForTokensOut(
uint256[] memory balances,
uint256 totalSupply,
bytes memory userData
) external pure returns (uint256 bptAmountIn, uint256[] memory amountsOut);
/**
* @dev See `WeightedExitsLib.exitBPTInForExactTokensOut`.
*/
function exitBPTInForExactTokensOut(
uint256[] memory balances,
uint256[] memory normalizedWeights,
uint256[] memory scalingFactors,
uint256 totalSupply,
uint256 swapFeePercentage,
bytes memory userData
) external pure returns (uint256, uint256[] memory);
}

View File

@@ -0,0 +1,71 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
library WeightedPoolUserData {
// In order to preserve backwards compatibility, make sure new join and exit kinds are added at the end of the enum.
enum JoinKind { INIT, EXACT_TOKENS_IN_FOR_BPT_OUT, TOKEN_IN_FOR_EXACT_BPT_OUT, ALL_TOKENS_IN_FOR_EXACT_BPT_OUT }
enum ExitKind { EXACT_BPT_IN_FOR_ONE_TOKEN_OUT, EXACT_BPT_IN_FOR_TOKENS_OUT, BPT_IN_FOR_EXACT_TOKENS_OUT }
function joinKind(bytes memory self) internal pure returns (JoinKind) {
return abi.decode(self, (JoinKind));
}
function exitKind(bytes memory self) internal pure returns (ExitKind) {
return abi.decode(self, (ExitKind));
}
// Joins
function initialAmountsIn(bytes memory self) internal pure returns (uint256[] memory amountsIn) {
(, amountsIn) = abi.decode(self, (JoinKind, uint256[]));
}
function exactTokensInForBptOut(bytes memory self)
internal
pure
returns (uint256[] memory amountsIn, uint256 minBPTAmountOut)
{
(, amountsIn, minBPTAmountOut) = abi.decode(self, (JoinKind, uint256[], uint256));
}
function tokenInForExactBptOut(bytes memory self) internal pure returns (uint256 bptAmountOut, uint256 tokenIndex) {
(, bptAmountOut, tokenIndex) = abi.decode(self, (JoinKind, uint256, uint256));
}
function allTokensInForExactBptOut(bytes memory self) internal pure returns (uint256 bptAmountOut) {
(, bptAmountOut) = abi.decode(self, (JoinKind, uint256));
}
// Exits
function exactBptInForTokenOut(bytes memory self) internal pure returns (uint256 bptAmountIn, uint256 tokenIndex) {
(, bptAmountIn, tokenIndex) = abi.decode(self, (ExitKind, uint256, uint256));
}
function exactBptInForTokensOut(bytes memory self) internal pure returns (uint256 bptAmountIn) {
(, bptAmountIn) = abi.decode(self, (ExitKind, uint256));
}
function bptInForExactTokensOut(bytes memory self)
internal
pure
returns (uint256[] memory amountsOut, uint256 maxBPTAmountIn)
{
(, amountsOut, maxBPTAmountIn) = abi.decode(self, (ExitKind, uint256[], uint256));
}
}

View File

@@ -0,0 +1,293 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
// solhint-disable
/**
* @dev Reverts if `condition` is false, with a revert reason containing `errorCode`. Only codes up to 999 are
* supported.
* Uses the default 'BAL' prefix for the error code
*/
function _require(bool condition, uint256 errorCode) pure {
if (!condition) _revert(errorCode);
}
/**
* @dev Reverts if `condition` is false, with a revert reason containing `errorCode`. Only codes up to 999 are
* supported.
*/
function _require(
bool condition,
uint256 errorCode,
bytes3 prefix
) pure {
if (!condition) _revert(errorCode, prefix);
}
/**
* @dev Reverts with a revert reason containing `errorCode`. Only codes up to 999 are supported.
* Uses the default 'BAL' prefix for the error code
*/
function _revert(uint256 errorCode) pure {
_revert(errorCode, 0x42414c); // This is the raw byte representation of "BAL"
}
/**
* @dev Reverts with a revert reason containing `errorCode`. Only codes up to 999 are supported.
*/
function _revert(uint256 errorCode, bytes3 prefix) pure {
uint256 prefixUint = uint256(uint24(prefix));
// We're going to dynamically create a revert string based on the error code, with the following format:
// 'BAL#{errorCode}'
// where the code is left-padded with zeroes to three digits (so they range from 000 to 999).
//
// We don't have revert strings embedded in the contract to save bytecode size: it takes much less space to store a
// number (8 to 16 bits) than the individual string characters.
//
// The dynamic string creation algorithm that follows could be implemented in Solidity, but assembly allows for a
// much denser implementation, again saving bytecode size. Given this function unconditionally reverts, this is a
// safe place to rely on it without worrying about how its usage might affect e.g. memory contents.
assembly {
// First, we need to compute the ASCII representation of the error code. We assume that it is in the 0-999
// range, so we only need to convert three digits. To convert the digits to ASCII, we add 0x30, the value for
// the '0' character.
let units := add(mod(errorCode, 10), 0x30)
errorCode := div(errorCode, 10)
let tenths := add(mod(errorCode, 10), 0x30)
errorCode := div(errorCode, 10)
let hundreds := add(mod(errorCode, 10), 0x30)
// With the individual characters, we can now construct the full string.
// We first append the '#' character (0x23) to the prefix. In the case of 'BAL', it results in 0x42414c23 ('BAL#')
// Then, we shift this by 24 (to provide space for the 3 bytes of the error code), and add the
// characters to it, each shifted by a multiple of 8.
// The revert reason is then shifted left by 200 bits (256 minus the length of the string, 7 characters * 8 bits
// per character = 56) to locate it in the most significant part of the 256 slot (the beginning of a byte
// array).
let formattedPrefix := shl(24, add(0x23, shl(8, prefixUint)))
let revertReason := shl(200, add(formattedPrefix, add(add(units, shl(8, tenths)), shl(16, hundreds))))
// We can now encode the reason in memory, which can be safely overwritten as we're about to revert. The encoded
// message will have the following layout:
// [ revert reason identifier ] [ string location offset ] [ string length ] [ string contents ]
// The Solidity revert reason identifier is 0x08c739a0, the function selector of the Error(string) function. We
// also write zeroes to the next 28 bytes of memory, but those are about to be overwritten.
mstore(0x0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
// Next is the offset to the location of the string, which will be placed immediately after (20 bytes away).
mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)
// The string length is fixed: 7 characters.
mstore(0x24, 7)
// Finally, the string itself is stored.
mstore(0x44, revertReason)
// Even if the string is only 7 bytes long, we need to return a full 32 byte slot containing it. The length of
// the encoded message is therefore 4 + 32 + 32 + 32 = 100.
revert(0, 100)
}
}
library Errors {
// Math
uint256 internal constant ADD_OVERFLOW = 0;
uint256 internal constant SUB_OVERFLOW = 1;
uint256 internal constant SUB_UNDERFLOW = 2;
uint256 internal constant MUL_OVERFLOW = 3;
uint256 internal constant ZERO_DIVISION = 4;
uint256 internal constant DIV_INTERNAL = 5;
uint256 internal constant X_OUT_OF_BOUNDS = 6;
uint256 internal constant Y_OUT_OF_BOUNDS = 7;
uint256 internal constant PRODUCT_OUT_OF_BOUNDS = 8;
uint256 internal constant INVALID_EXPONENT = 9;
// Input
uint256 internal constant OUT_OF_BOUNDS = 100;
uint256 internal constant UNSORTED_ARRAY = 101;
uint256 internal constant UNSORTED_TOKENS = 102;
uint256 internal constant INPUT_LENGTH_MISMATCH = 103;
uint256 internal constant ZERO_TOKEN = 104;
uint256 internal constant INSUFFICIENT_DATA = 105;
// Shared pools
uint256 internal constant MIN_TOKENS = 200;
uint256 internal constant MAX_TOKENS = 201;
uint256 internal constant MAX_SWAP_FEE_PERCENTAGE = 202;
uint256 internal constant MIN_SWAP_FEE_PERCENTAGE = 203;
uint256 internal constant MINIMUM_BPT = 204;
uint256 internal constant CALLER_NOT_VAULT = 205;
uint256 internal constant UNINITIALIZED = 206;
uint256 internal constant BPT_IN_MAX_AMOUNT = 207;
uint256 internal constant BPT_OUT_MIN_AMOUNT = 208;
uint256 internal constant EXPIRED_PERMIT = 209;
uint256 internal constant NOT_TWO_TOKENS = 210;
uint256 internal constant DISABLED = 211;
// Pools
uint256 internal constant MIN_AMP = 300;
uint256 internal constant MAX_AMP = 301;
uint256 internal constant MIN_WEIGHT = 302;
uint256 internal constant MAX_STABLE_TOKENS = 303;
uint256 internal constant MAX_IN_RATIO = 304;
uint256 internal constant MAX_OUT_RATIO = 305;
uint256 internal constant MIN_BPT_IN_FOR_TOKEN_OUT = 306;
uint256 internal constant MAX_OUT_BPT_FOR_TOKEN_IN = 307;
uint256 internal constant NORMALIZED_WEIGHT_INVARIANT = 308;
uint256 internal constant INVALID_TOKEN = 309;
uint256 internal constant UNHANDLED_JOIN_KIND = 310;
uint256 internal constant ZERO_INVARIANT = 311;
uint256 internal constant ORACLE_INVALID_SECONDS_QUERY = 312;
uint256 internal constant ORACLE_NOT_INITIALIZED = 313;
uint256 internal constant ORACLE_QUERY_TOO_OLD = 314;
uint256 internal constant ORACLE_INVALID_INDEX = 315;
uint256 internal constant ORACLE_BAD_SECS = 316;
uint256 internal constant AMP_END_TIME_TOO_CLOSE = 317;
uint256 internal constant AMP_ONGOING_UPDATE = 318;
uint256 internal constant AMP_RATE_TOO_HIGH = 319;
uint256 internal constant AMP_NO_ONGOING_UPDATE = 320;
uint256 internal constant STABLE_INVARIANT_DIDNT_CONVERGE = 321;
uint256 internal constant STABLE_GET_BALANCE_DIDNT_CONVERGE = 322;
uint256 internal constant RELAYER_NOT_CONTRACT = 323;
uint256 internal constant BASE_POOL_RELAYER_NOT_CALLED = 324;
uint256 internal constant REBALANCING_RELAYER_REENTERED = 325;
uint256 internal constant GRADUAL_UPDATE_TIME_TRAVEL = 326;
uint256 internal constant SWAPS_DISABLED = 327;
uint256 internal constant CALLER_IS_NOT_LBP_OWNER = 328;
uint256 internal constant PRICE_RATE_OVERFLOW = 329;
uint256 internal constant INVALID_JOIN_EXIT_KIND_WHILE_SWAPS_DISABLED = 330;
uint256 internal constant WEIGHT_CHANGE_TOO_FAST = 331;
uint256 internal constant LOWER_GREATER_THAN_UPPER_TARGET = 332;
uint256 internal constant UPPER_TARGET_TOO_HIGH = 333;
uint256 internal constant UNHANDLED_BY_LINEAR_POOL = 334;
uint256 internal constant OUT_OF_TARGET_RANGE = 335;
uint256 internal constant UNHANDLED_EXIT_KIND = 336;
uint256 internal constant UNAUTHORIZED_EXIT = 337;
uint256 internal constant MAX_MANAGEMENT_SWAP_FEE_PERCENTAGE = 338;
uint256 internal constant UNHANDLED_BY_MANAGED_POOL = 339;
uint256 internal constant UNHANDLED_BY_PHANTOM_POOL = 340;
uint256 internal constant TOKEN_DOES_NOT_HAVE_RATE_PROVIDER = 341;
uint256 internal constant INVALID_INITIALIZATION = 342;
uint256 internal constant OUT_OF_NEW_TARGET_RANGE = 343;
uint256 internal constant FEATURE_DISABLED = 344;
uint256 internal constant UNINITIALIZED_POOL_CONTROLLER = 345;
uint256 internal constant SET_SWAP_FEE_DURING_FEE_CHANGE = 346;
uint256 internal constant SET_SWAP_FEE_PENDING_FEE_CHANGE = 347;
uint256 internal constant CHANGE_TOKENS_DURING_WEIGHT_CHANGE = 348;
uint256 internal constant CHANGE_TOKENS_PENDING_WEIGHT_CHANGE = 349;
uint256 internal constant MAX_WEIGHT = 350;
uint256 internal constant UNAUTHORIZED_JOIN = 351;
uint256 internal constant MAX_MANAGEMENT_AUM_FEE_PERCENTAGE = 352;
uint256 internal constant FRACTIONAL_TARGET = 353;
uint256 internal constant ADD_OR_REMOVE_BPT = 354;
uint256 internal constant INVALID_CIRCUIT_BREAKER_BOUNDS = 355;
uint256 internal constant CIRCUIT_BREAKER_TRIPPED = 356;
uint256 internal constant MALICIOUS_QUERY_REVERT = 357;
uint256 internal constant JOINS_EXITS_DISABLED = 358;
// Lib
uint256 internal constant REENTRANCY = 400;
uint256 internal constant SENDER_NOT_ALLOWED = 401;
uint256 internal constant PAUSED = 402;
uint256 internal constant PAUSE_WINDOW_EXPIRED = 403;
uint256 internal constant MAX_PAUSE_WINDOW_DURATION = 404;
uint256 internal constant MAX_BUFFER_PERIOD_DURATION = 405;
uint256 internal constant INSUFFICIENT_BALANCE = 406;
uint256 internal constant INSUFFICIENT_ALLOWANCE = 407;
uint256 internal constant ERC20_TRANSFER_FROM_ZERO_ADDRESS = 408;
uint256 internal constant ERC20_TRANSFER_TO_ZERO_ADDRESS = 409;
uint256 internal constant ERC20_MINT_TO_ZERO_ADDRESS = 410;
uint256 internal constant ERC20_BURN_FROM_ZERO_ADDRESS = 411;
uint256 internal constant ERC20_APPROVE_FROM_ZERO_ADDRESS = 412;
uint256 internal constant ERC20_APPROVE_TO_ZERO_ADDRESS = 413;
uint256 internal constant ERC20_TRANSFER_EXCEEDS_ALLOWANCE = 414;
uint256 internal constant ERC20_DECREASED_ALLOWANCE_BELOW_ZERO = 415;
uint256 internal constant ERC20_TRANSFER_EXCEEDS_BALANCE = 416;
uint256 internal constant ERC20_BURN_EXCEEDS_ALLOWANCE = 417;
uint256 internal constant SAFE_ERC20_CALL_FAILED = 418;
uint256 internal constant ADDRESS_INSUFFICIENT_BALANCE = 419;
uint256 internal constant ADDRESS_CANNOT_SEND_VALUE = 420;
uint256 internal constant SAFE_CAST_VALUE_CANT_FIT_INT256 = 421;
uint256 internal constant GRANT_SENDER_NOT_ADMIN = 422;
uint256 internal constant REVOKE_SENDER_NOT_ADMIN = 423;
uint256 internal constant RENOUNCE_SENDER_NOT_ALLOWED = 424;
uint256 internal constant BUFFER_PERIOD_EXPIRED = 425;
uint256 internal constant CALLER_IS_NOT_OWNER = 426;
uint256 internal constant NEW_OWNER_IS_ZERO = 427;
uint256 internal constant CODE_DEPLOYMENT_FAILED = 428;
uint256 internal constant CALL_TO_NON_CONTRACT = 429;
uint256 internal constant LOW_LEVEL_CALL_FAILED = 430;
uint256 internal constant NOT_PAUSED = 431;
uint256 internal constant ADDRESS_ALREADY_ALLOWLISTED = 432;
uint256 internal constant ADDRESS_NOT_ALLOWLISTED = 433;
uint256 internal constant ERC20_BURN_EXCEEDS_BALANCE = 434;
uint256 internal constant INVALID_OPERATION = 435;
uint256 internal constant CODEC_OVERFLOW = 436;
uint256 internal constant IN_RECOVERY_MODE = 437;
uint256 internal constant NOT_IN_RECOVERY_MODE = 438;
uint256 internal constant INDUCED_FAILURE = 439;
uint256 internal constant EXPIRED_SIGNATURE = 440;
uint256 internal constant MALFORMED_SIGNATURE = 441;
uint256 internal constant SAFE_CAST_VALUE_CANT_FIT_UINT64 = 442;
uint256 internal constant UNHANDLED_FEE_TYPE = 443;
uint256 internal constant BURN_FROM_ZERO = 444;
// Vault
uint256 internal constant INVALID_POOL_ID = 500;
uint256 internal constant CALLER_NOT_POOL = 501;
uint256 internal constant SENDER_NOT_ASSET_MANAGER = 502;
uint256 internal constant USER_DOESNT_ALLOW_RELAYER = 503;
uint256 internal constant INVALID_SIGNATURE = 504;
uint256 internal constant EXIT_BELOW_MIN = 505;
uint256 internal constant JOIN_ABOVE_MAX = 506;
uint256 internal constant SWAP_LIMIT = 507;
uint256 internal constant SWAP_DEADLINE = 508;
uint256 internal constant CANNOT_SWAP_SAME_TOKEN = 509;
uint256 internal constant UNKNOWN_AMOUNT_IN_FIRST_SWAP = 510;
uint256 internal constant MALCONSTRUCTED_MULTIHOP_SWAP = 511;
uint256 internal constant INTERNAL_BALANCE_OVERFLOW = 512;
uint256 internal constant INSUFFICIENT_INTERNAL_BALANCE = 513;
uint256 internal constant INVALID_ETH_INTERNAL_BALANCE = 514;
uint256 internal constant INVALID_POST_LOAN_BALANCE = 515;
uint256 internal constant INSUFFICIENT_ETH = 516;
uint256 internal constant UNALLOCATED_ETH = 517;
uint256 internal constant ETH_TRANSFER = 518;
uint256 internal constant CANNOT_USE_ETH_SENTINEL = 519;
uint256 internal constant TOKENS_MISMATCH = 520;
uint256 internal constant TOKEN_NOT_REGISTERED = 521;
uint256 internal constant TOKEN_ALREADY_REGISTERED = 522;
uint256 internal constant TOKENS_ALREADY_SET = 523;
uint256 internal constant TOKENS_LENGTH_MUST_BE_2 = 524;
uint256 internal constant NONZERO_TOKEN_BALANCE = 525;
uint256 internal constant BALANCE_TOTAL_OVERFLOW = 526;
uint256 internal constant POOL_NO_TOKENS = 527;
uint256 internal constant INSUFFICIENT_FLASH_LOAN_BALANCE = 528;
// Fees
uint256 internal constant SWAP_FEE_PERCENTAGE_TOO_HIGH = 600;
uint256 internal constant FLASH_LOAN_FEE_PERCENTAGE_TOO_HIGH = 601;
uint256 internal constant INSUFFICIENT_FLASH_LOAN_FEE_AMOUNT = 602;
uint256 internal constant AUM_FEE_PERCENTAGE_TOO_HIGH = 603;
// FeeSplitter
uint256 internal constant SPLITTER_FEE_PERCENTAGE_TOO_HIGH = 700;
// Misc
uint256 internal constant UNIMPLEMENTED = 998;
uint256 internal constant SHOULD_NOT_HAPPEN = 999;
}

View File

@@ -0,0 +1,22 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
interface IAuthentication {
/**
* @dev Returns the action identifier associated with the external function described by `selector`.
*/
function getActionId(bytes4 selector) external view returns (bytes32);
}

View File

@@ -0,0 +1,43 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
/**
* @dev Interface for the OptionalOnlyCaller helper, used to opt in to a caller
* verification for a given address to methods that are otherwise callable by any address.
*/
interface IOptionalOnlyCaller {
/**
* @dev Emitted every time setOnlyCallerCheck is called.
*/
event OnlyCallerOptIn(address user, bool enabled);
/**
* @dev Enables / disables verification mechanism for caller.
* @param enabled - True if caller verification shall be enabled, false otherwise.
*/
function setOnlyCallerCheck(bool enabled) external;
function setOnlyCallerCheckWithSignature(
address user,
bool enabled,
bytes memory signature
) external;
/**
* @dev Returns true if caller verification is enabled for the given user, false otherwise.
*/
function isOnlyCallerEnabled(address user) external view returns (bool);
}

View File

@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
/**
* @dev Interface for the SignatureValidator helper, used to support meta-transactions.
*/
interface ISignaturesValidator {
/**
* @dev Returns the EIP712 domain separator.
*/
function getDomainSeparator() external view returns (bytes32);
/**
* @dev Returns the next nonce used by an address to sign messages.
*/
function getNextNonce(address user) external view returns (uint256);
}

View File

@@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
/**
* @dev Interface for the TemporarilyPausable helper.
*/
interface ITemporarilyPausable {
/**
* @dev Emitted every time the pause state changes by `_setPaused`.
*/
event PausedStateChanged(bool paused);
/**
* @dev Returns the current paused state.
*/
function getPausedState()
external
view
returns (
bool paused,
uint256 pauseWindowEndTime,
uint256 bufferPeriodEndTime
);
}

View File

@@ -0,0 +1,72 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../openzeppelin/IERC20.sol";
interface IERC4626 is IERC20 {
/**
* @dev `caller` has exchanged `assets` for `shares`, and transferred those `shares` to `owner`.
*/
event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares);
/**
* @dev `caller` has exchanged `shares`, owned by `owner`, for `assets`,
* and transferred those `assets` to `receiver`.
*/
event Withdraw(
address indexed caller,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
/**
* @dev Mints `shares` Vault shares to `receiver` by depositing exactly `amount` of underlying tokens.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Burns exactly `shares` from `owner` and sends `assets` of underlying tokens to `receiver`.
*/
function redeem(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
/**
* @dev The address of the underlying token that the Vault uses for accounting, depositing, and withdrawing.
*/
function asset() external view returns (address);
/**
* @dev Total amount of the underlying asset that is “managed” by Vault.
*/
function totalAssets() external view returns (uint256);
/**
* @dev The amount of `assets` that the Vault would exchange for the amount
* of `shares` provided, in an ideal scenario where all the conditions are met.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev The amount of `shares` that the Vault would exchange for the amount
* of `assets` provided, in an ideal scenario where all the conditions are met.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
}

View File

@@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../openzeppelin/IERC20.sol";
/**
* @dev Interface for WETH9.
* See https://github.com/gnosis/canonical-weth/blob/0dd1ea3e295eef916d0c6223ec63141137d22d67/contracts/WETH9.sol
*/
interface IWETH is IERC20 {
function deposit() external payable;
function withdraw(uint256 amount) external;
}

View File

@@ -0,0 +1,19 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)
pragma solidity >=0.7.0 <0.9.0;
/**
* @dev Interface of the ERC1271 standard signature validation method for
* contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
*
* _Available since v4.1._
*/
interface IERC1271 {
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param hash Hash of the data to be signed
* @param signature Signature byte array associated with _data
*/
function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}

View File

@@ -0,0 +1,81 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}

View File

@@ -0,0 +1,59 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over `owner`'s tokens,
* given `owner`'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}

View File

@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
interface IERC20PermitDAI {
/**
* @notice update allowance with a signed permit
* @param holder Token owner's address (Authorizer)
* @param spender Spender's address
* @param nonce The permit nonce
* @param expiry The time at which this expires (unix time)
* @param allowed Whether the spender is allowed or disallowed from spending
* @param v v of the signature
* @param r r of the signature
* @param s s of the signature
*/
function permit(
address holder,
address spender,
uint256 nonce,
uint256 expiry,
bool allowed,
uint8 v,
bytes32 r,
bytes32 s
) external;
}

View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2016-2020 zOS Global Limited
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,11 @@
## Ports from OpenZeppelin Contracts
Files in this directory are based on the [OpenZeppelin Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts) library, and as such are licensed under the MIT License: see [LICENSE](./LICENSE).
Most of the modifications fall under one of these categories:
- removal of functions unused in Balancer V2 source code
- replacement of `require` statements with the `_require` function from the `BalancerErrors.sol` contract
- modification or addition of functionality to reduce bytecode size (see `ReentrancyGuard.sol`) or gas usage (see `EnumerableSet`, `EnumerableMap` or `SafeERC20`)
Non-trivial modifications in this last category have associated source code comments that explain the changes and motivation.

View File

@@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
interface IAToken {
/**
* @dev returns the address of the aToken's underlying asset
*/
// solhint-disable-next-line func-name-mixedcase
function UNDERLYING_ASSET_ADDRESS() external view returns (address);
}

View File

@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/helpers/IAuthentication.sol";
import "../solidity-utils/openzeppelin/IERC20.sol";
interface IBALTokenHolder is IAuthentication {
function getName() external view returns (string memory);
function withdrawFunds(address recipient, uint256 amount) external;
function sweepTokens(
IERC20 token,
address recipient,
uint256 amount
) external;
}

View File

@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../vault/IVault.sol";
import "../liquidity-mining/IBalancerToken.sol";
import "./IBALTokenHolder.sol";
interface IBALTokenHolderFactory {
function getBalancerToken() external view returns (IBalancerToken);
function getVault() external view returns (IVault);
function isHolderFromFactory(address holder) external view returns (bool);
function create(string memory name) external returns (IBALTokenHolder);
}

View File

@@ -0,0 +1,62 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "../vault/IVault.sol";
/**
* @dev Provides a way to perform queries on swaps, joins and exits, simulating these operations and returning the exact
* result they would have if called on the Vault given the current state. Note that the results will be affected by
* other transactions interacting with the Pools involved.
*
* All query functions can be called both on-chain and off-chain.
*
* If calling them from a contract, note that all query functions are not `view`. Despite this, these functions produce
* no net state change, and for all intents and purposes can be thought of as if they were indeed `view`. However,
* calling them via STATICCALL will fail.
*
* If calling them from an off-chain client, make sure to use eth_call: most clients default to eth_sendTransaction for
* non-view functions.
*
* In all cases, the `fromInternalBalance` and `toInternalBalance` fields are entirely ignored: we just use the same
* structs for simplicity.
*/
interface IBalancerQueries {
function querySwap(IVault.SingleSwap memory singleSwap, IVault.FundManagement memory funds)
external
returns (uint256);
function queryBatchSwap(
IVault.SwapKind kind,
IVault.BatchSwapStep[] memory swaps,
IAsset[] memory assets,
IVault.FundManagement memory funds
) external returns (int256[] memory assetDeltas);
function queryJoin(
bytes32 poolId,
address sender,
address recipient,
IVault.JoinPoolRequest memory request
) external returns (uint256 bptOut, uint256[] memory amountsIn);
function queryExit(
bytes32 poolId,
address sender,
address recipient,
IVault.ExitPoolRequest memory request
) external returns (uint256 bptIn, uint256[] memory amountsOut);
}

View File

@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "../vault/IVault.sol";
/**
* @title IBalancerRelayer
* @notice Allows safe multicall execution of a relayer's functions
*/
interface IBalancerRelayer {
function getLibrary() external view returns (address);
function getVault() external view returns (IVault);
function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);
}

View File

@@ -0,0 +1,120 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
// Source: https://github.com/buttonwood-protocol/button-wrappers/blob/main/contracts/interfaces/IButtonWrapper.sol
// Interface definition for ButtonWrapper contract, which wraps an
// underlying ERC20 token into a new ERC20 with different characteristics.
// NOTE: "uAmount" => underlying token (wrapped) amount and
// "amount" => wrapper token amount
interface IButtonWrapper {
//--------------------------------------------------------------------------
// ButtonWrapper write methods
/// @notice Transfers underlying tokens from {msg.sender} to the contract and
/// mints wrapper tokens.
/// @param amount The amount of wrapper tokens to mint.
/// @return The amount of underlying tokens deposited.
function mint(uint256 amount) external returns (uint256);
/// @notice Transfers underlying tokens from {msg.sender} to the contract and
/// mints wrapper tokens to the specified beneficiary.
/// @param to The beneficiary account.
/// @param amount The amount of wrapper tokens to mint.
/// @return The amount of underlying tokens deposited.
function mintFor(address to, uint256 amount) external returns (uint256);
/// @notice Burns wrapper tokens from {msg.sender} and transfers
/// the underlying tokens back.
/// @param amount The amount of wrapper tokens to burn.
/// @return The amount of underlying tokens withdrawn.
function burn(uint256 amount) external returns (uint256);
/// @notice Burns wrapper tokens from {msg.sender} and transfers
/// the underlying tokens to the specified beneficiary.
/// @param to The beneficiary account.
/// @param amount The amount of wrapper tokens to burn.
/// @return The amount of underlying tokens withdrawn.
function burnTo(address to, uint256 amount) external returns (uint256);
/// @notice Burns all wrapper tokens from {msg.sender} and transfers
/// the underlying tokens back.
/// @return The amount of underlying tokens withdrawn.
function burnAll() external returns (uint256);
/// @notice Burns all wrapper tokens from {msg.sender} and transfers
/// the underlying tokens back.
/// @param to The beneficiary account.
/// @return The amount of underlying tokens withdrawn.
function burnAllTo(address to) external returns (uint256);
/// @notice Transfers underlying tokens from {msg.sender} to the contract and
/// mints wrapper tokens to the specified beneficiary.
/// @param uAmount The amount of underlying tokens to deposit.
/// @return The amount of wrapper tokens mint.
function deposit(uint256 uAmount) external returns (uint256);
/// @notice Transfers underlying tokens from {msg.sender} to the contract and
/// mints wrapper tokens to the specified beneficiary.
/// @param to The beneficiary account.
/// @param uAmount The amount of underlying tokens to deposit.
/// @return The amount of wrapper tokens mint.
function depositFor(address to, uint256 uAmount) external returns (uint256);
/// @notice Burns wrapper tokens from {msg.sender} and transfers
/// the underlying tokens back.
/// @param uAmount The amount of underlying tokens to withdraw.
/// @return The amount of wrapper tokens burnt.
function withdraw(uint256 uAmount) external returns (uint256);
/// @notice Burns wrapper tokens from {msg.sender} and transfers
/// the underlying tokens back to the specified beneficiary.
/// @param to The beneficiary account.
/// @param uAmount The amount of underlying tokens to withdraw.
/// @return The amount of wrapper tokens burnt.
function withdrawTo(address to, uint256 uAmount) external returns (uint256);
/// @notice Burns all wrapper tokens from {msg.sender} and transfers
/// the underlying tokens back.
/// @return The amount of wrapper tokens burnt.
function withdrawAll() external returns (uint256);
/// @notice Burns all wrapper tokens from {msg.sender} and transfers
/// the underlying tokens back.
/// @param to The beneficiary account.
/// @return The amount of wrapper tokens burnt.
function withdrawAllTo(address to) external returns (uint256);
//--------------------------------------------------------------------------
// ButtonWrapper view methods
/// @return The address of the underlying token.
function underlying() external view returns (address);
/// @return The total underlying tokens held by the wrapper contract.
function totalUnderlying() external view returns (uint256);
/// @param who The account address.
/// @return The underlying token balance of the account.
function balanceOfUnderlying(address who) external view returns (uint256);
/// @param uAmount The amount of underlying tokens.
/// @return The amount of wrapper tokens exchangeable.
function underlyingToWrapper(uint256 uAmount) external view returns (uint256);
/// @param amount The amount of wrapper tokens.
/// @return The amount of underlying tokens exchangeable.
function wrapperToUnderlying(uint256 amount) external view returns (uint256);
}

View File

@@ -0,0 +1,48 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.7.0;
// Interface for MidasCapital. An open interest protocol based on
// modified Fuse contracts. Anyone can create an deploy isolated
// lending and borrowing pools with custom parameters.
import "../solidity-utils/openzeppelin/IERC20.sol";
interface ICToken is IERC20 {
// Error codes referenced in this file can be found here:
// https://github.com/compound-finance/compound-protocol/blob/a3214f67b73310d547e00fc578e8355911c9d376/contracts/ErrorReporter.sol
// solhint-disable-previous-line max-line-length
/**
* @dev Underlying asset for this CToken
*/
function underlying() external view returns (address);
/**
* @notice Sender supplies assets into the market and receives cTokens in exchange
* @dev Accrues interest whether or not the operation succeeds, unless reverted
* @param mintAmount The amount of the underlying asset to supply
* @return uint 0=success, otherwise an error code (see ErrorReporter.sol link above for details)
*/
function mint(uint256 mintAmount) external returns (uint256);
/**
* @notice Sender redeems cTokens in exchange for the underlying asset
* @dev Accrues interest whether or not the operation succeeds, unless reverted
* @param redeemTokens The number of cTokens to redeem into underlying
* @return uint 0=success, otherwise an error code (see ErrorReporter.sol link above for details)
*/
function redeem(uint256 redeemTokens) external returns (uint256);
}

View File

@@ -0,0 +1,52 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.7.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
interface IEulerToken is IERC20 {
/**
* @dev Convert an eToken balance to an underlying amount, taking into account current exchange rate
* @param balance eToken balance, in internal book-keeping units (18 decimals)
* @return Amount in underlying units, (same decimals as underlying token)
*/
// https://github.com/euler-xyz/euler-contracts/blob/b1ee3265853628d5a529081d7908c38404201b4e/contracts/modules/EToken.sol#L104
// solhint-disable-previous-line max-line-length
function convertBalanceToUnderlying(uint256 balance) external view returns (uint256);
/**
* @dev Convert an underlying amount to an eToken balance, taking into account current exchange rate
* @param underlyingAmount Amount in underlying units (same decimals as underlying token)
* @return eToken balance, in internal book-keeping units (18 decimals)
*/
// https://github.com/euler-xyz/euler-contracts/blob/b1ee3265853628d5a529081d7908c38404201b4e/contracts/modules/EToken.sol#L114
// solhint-disable-previous-line max-line-length
function convertUnderlyingToBalance(uint256 underlyingAmount) external view returns (uint256);
/**
* @dev Transfer underlying tokens from sender to the Euler pool, and increase account's eTokens
*/
function deposit(uint256 subAccountId, uint256 amount) external;
/**
* @dev Transfer underlying tokens from Euler pool to sender, and decrease account's eTokens
*/
function withdraw(uint256 subAccountId, uint256 amount) external;
/**
* @dev Address of underlying asset
*/
function underlyingAsset() external view returns (address);
}

View File

@@ -0,0 +1,62 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
interface IGearboxDieselToken is IERC20 {
/**
* @dev returns the address of the vault
*/
function owner() external view returns (address);
}
interface IGearboxVault {
/**
* @dev returns the address of the underlying asset
*/
function underlyingToken() external view returns (address);
/**
* @dev returns a 27 decimal fixed point 'ray' value so a rate of 1 is represented as 1e27
*/
// solhint-disable-next-line func-name-mixedcase
function getDieselRate_RAY() external view returns (uint256);
/**
* @dev converts diesel token amount to main token amount
*/
function fromDiesel(uint256) external view returns (uint256);
/**
* @dev converts main token amount to diesel token amount
*/
function toDiesel(uint256) external view returns (uint256);
/**
* @dev Adds liquidity to pool and sends diesel (LP) tokens back to the liquidity provider
* The Referral code can be 0
*/
function addLiquidity(
uint256 underlyingAmount,
address onBehalfOf,
uint256 referralCode
) external;
/**
* @dev Removes liquidity from the pool and sends the underlying tokens to the `to` address
*/
function removeLiquidity(uint256 dieselAmount, address to) external;
}

View File

@@ -0,0 +1,100 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
/**
* @dev Source of truth for all Protocol Fee percentages, that is, how much the protocol charges certain actions. Some
* of these values may also be retrievable from other places (such as the swap fee percentage), but this is the
* preferred source nonetheless.
*/
interface IProtocolFeePercentagesProvider {
// All fee percentages are 18-decimal fixed point numbers, so e.g. 1e18 = 100% and 1e16 = 1%.
// Emitted when a new fee type is registered.
event ProtocolFeeTypeRegistered(uint256 indexed feeType, string name, uint256 maximumPercentage);
// Emitted when the value of a fee type changes.
// IMPORTANT: it is possible for a third party to modify the SWAP and FLASH_LOAN fee type values directly in the
// ProtocolFeesCollector, which will result in this event not being emitted despite their value changing. Such usage
// of the ProtocolFeesCollector is however discouraged: all state-changing interactions with it should originate in
// this contract.
event ProtocolFeePercentageChanged(uint256 indexed feeType, uint256 percentage);
/**
* @dev Registers a new fee type in the system, making it queryable via `getFeeTypePercentage` and `getFeeTypeName`,
* as well as configurable via `setFeeTypePercentage`.
*
* `feeType` can be any arbitrary value (that is not in use).
*
* It is not possible to de-register fee types, nor change their name or maximum value.
*/
function registerFeeType(
uint256 feeType,
string memory name,
uint256 maximumValue,
uint256 initialValue
) external;
/**
* @dev Returns true if `feeType` has been registered and can be queried.
*/
function isValidFeeType(uint256 feeType) external view returns (bool);
/**
* @dev Returns true if `value` is a valid percentage value for `feeType`.
*/
function isValidFeeTypePercentage(uint256 feeType, uint256 value) external view returns (bool);
/**
* @dev Sets the percentage value for `feeType` to `newValue`.
*
* IMPORTANT: it is possible for a third party to modify the SWAP and FLASH_LOAN fee type values directly in the
* ProtocolFeesCollector, without invoking this function. This will result in the `ProtocolFeePercentageChanged`
* event not being emitted despite their value changing. Such usage of the ProtocolFeesCollector is however
* discouraged: only this contract should be granted permission to call `setSwapFeePercentage` and
* `setFlashLoanFeePercentage`.
*/
function setFeeTypePercentage(uint256 feeType, uint256 newValue) external;
/**
* @dev Returns the current percentage value for `feeType`. This is the preferred mechanism for querying these -
* whenever possible, use this fucntion instead of e.g. querying the ProtocolFeesCollector.
*/
function getFeeTypePercentage(uint256 feeType) external view returns (uint256);
/**
* @dev Returns `feeType`'s maximum value.
*/
function getFeeTypeMaximumPercentage(uint256 feeType) external view returns (uint256);
/**
* @dev Returns `feeType`'s name.
*/
function getFeeTypeName(uint256 feeType) external view returns (string memory);
}
library ProtocolFeeType {
// This list is not exhaustive - more fee types can be added to the system. It is expected for this list to be
// extended with new fee types as they are registered, to keep them all in one place and reduce
// likelihood of user error.
// solhint-disable private-vars-leading-underscore
uint256 internal constant SWAP = 0;
uint256 internal constant FLASH_LOAN = 1;
uint256 internal constant YIELD = 2;
uint256 internal constant AUM = 3;
// solhint-enable private-vars-leading-underscore
}

View File

@@ -0,0 +1,136 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../vault/IVault.sol";
import "./IProtocolFeesWithdrawer.sol";
/**
* @title ProtocolFeeSplitter
* @author Daoism Systems
* @notice Distributes protocol fees collected from a particular pool between a DAO fund recipient
* (e.g., the Balancer DAO treasury), and a beneficiary designated by the pool owner.
* @dev By default, all funds go to the DAO. To claim a share of the protocol fees, pool owners
* may call `setPoolBeneficiary`.
*/
interface IProtocolFeeSplitter {
event FeesCollected(
bytes32 indexed poolId,
address indexed beneficiary,
uint256 poolEarned,
address indexed daoFundsRecipient,
uint256 daoEarned
);
event PoolRevenueShareChanged(bytes32 indexed poolId, uint256 revenueSharePercentage);
event PoolRevenueShareCleared(bytes32 indexed poolId);
event PoolBeneficiaryChanged(bytes32 indexed poolId, address newBeneficiary);
event DefaultRevenueSharePercentageChanged(uint256 revenueSharePercentage);
event DAOFundsRecipientChanged(address newDaoFundsRecipient);
// Fund recipients
/**
* @notice Returns the DAO funds recipient that will receive any balance not due to the pool beneficiary.
*/
function getDaoFundsRecipient() external view returns (address);
/**
* @notice Allows a authorized user to change the DAO funds recipient.
* @dev This is a permissioned function.
* @param newDaoFundsRecipient - address of the new DAO funds recipient.
*/
function setDaoFundsRecipient(address newDaoFundsRecipient) external;
/**
* @notice Allows a pool owner to change the revenue share beneficiary for a given pool.
* @dev This is a permissioned function.
* @param poolId - the poolId of the pool where the beneficiary will change.
* @param newBeneficiary - address of the new beneficiary.
*/
function setPoolBeneficiary(bytes32 poolId, address newBeneficiary) external;
// Revenue share settings
/**
* @dev Returns the current protocol fee split configuration for a given pool.
* @param poolId - the poolId of a pool with accrued protocol fees.
* @return revenueSharePercentageOverride - the percentage of the split sent to the pool beneficiary.
* @return beneficiary - the address of the pool beneficiary.
*/
function getRevenueShareSettings(bytes32 poolId)
external
view
returns (
uint256 revenueSharePercentageOverride,
address beneficiary,
bool overrideSet
);
/**
* @dev Returns the default revenue share percentage a pool will receive, unless overridden by a call
* to `setRevenueSharePercentage`.
*/
function getDefaultRevenueSharePercentage() external view returns (uint256);
/**
* @notice Allows an authorized user to change the default revenue share percentage.
* @dev Set the default revenue share percentage, applied to pools where no override has been set
* through `setRevenueSharePercentage`. Must be below the maximum allowed split.
* This is a permissioned function.
* @param defaultRevenueSharePercentage - new default revenue share percentage
*/
function setDefaultRevenueSharePercentage(uint256 defaultRevenueSharePercentage) external;
/**
* @notice Allows an authorized user to change the revenueShare for a given pool.
* @dev This is a permissioned function.
* @param poolId - the poolId of the pool where the revenue share will change.
* @param revenueSharePercentage - the new revenue share percentage.
*/
function setRevenueSharePercentage(bytes32 poolId, uint256 revenueSharePercentage) external;
/**
* @notice Allows an authorized user to change the revenueShare for a given pool.
* @dev This is a permissioned function.
* @param poolId - the poolId of the pool where the revenue share will change.
*/
function clearRevenueSharePercentage(bytes32 poolId) external;
// Permissionless fee collection functions
/**
* @dev Returns the amount of fees that would be sent to each beneficiary in a call to `collectFees`.
* @param poolId - the poolId of a pool with accrued protocol fees.
* @return beneficiaryAmount - the BPT amount that would be sent to the pool beneficiary.
* @return daoAmount - the BPT amount that would be sent to the DAO funds recipient.
*/
function getAmounts(bytes32 poolId) external view returns (uint256 beneficiaryAmount, uint256 daoAmount);
/**
* @dev Permissionless function to collect and distribute any accrued protocol fees for the given pool.
* @param poolId - the poolId of a pool with accrued protocol fees.
* @return beneficiaryAmount - the BPT amount sent to the pool beneficiary.
* @return daoAmount - the BPT amount sent to the DAO funds recipient.
*/
function collectFees(bytes32 poolId) external returns (uint256 beneficiaryAmount, uint256 daoAmount);
// Misc getters
/**
* @notice Returns the `ProtocolFeesWithdrawer`, used to withdraw funds from the `ProtocolFeesCollector`.
*/
function getProtocolFeesWithdrawer() external view returns (IProtocolFeesWithdrawer);
}

View File

@@ -0,0 +1,78 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../vault/IProtocolFeesCollector.sol";
/**
* @author Balancer Labs
* @title Protocol Fees Withdrawer
* @notice Safety layer around the Protocol Fees Collector which allows withdrawals of specific tokens to be blocked.
* This is useful for the case in where tokens that shouldn't be distributed are unexpectedly paid into the Protocol
* Fees Collector.
*/
interface IProtocolFeesWithdrawer {
event TokenAllowlisted(IERC20 token);
event TokenDenylisted(IERC20 token);
/**
* @notice Returns the address of the Protocol Fee Collector.
*/
function getProtocolFeesCollector() external view returns (IProtocolFeesCollector);
/**
* @notice Returns whether the provided token may be withdrawn from the Protocol Fee Collector
*/
function isWithdrawableToken(IERC20 token) external view returns (bool);
/**
* @notice Returns whether the provided array of tokens may be withdrawn from the Protocol Fee Collector
* @dev Returns false if any token is denylisted.
*/
function isWithdrawableTokens(IERC20[] calldata tokens) external view returns (bool);
/**
* @notice Returns the denylisted token at the given `index`.
*/
function getDenylistedToken(uint256 index) external view returns (IERC20);
/**
* @notice Returns the number of denylisted tokens.
*/
function getDenylistedTokensLength() external view returns (uint256);
/**
* @notice Withdraws fees from the Protocol Fee Collector.
* @dev Reverts if attempting to withdraw a denylisted token.
* @param tokens - an array of token addresses to withdraw.
* @param amounts - an array of the amounts of each token to withdraw.
* @param recipient - the address to which to send the withdrawn tokens.
*/
function withdrawCollectedFees(
IERC20[] calldata tokens,
uint256[] calldata amounts,
address recipient
) external;
/**
* @notice Marks the provided token as ineligible for withdrawal from the Protocol Fee Collector
*/
function denylistToken(IERC20 token) external;
/**
* @notice Marks the provided token as eligible for withdrawal from the Protocol Fee Collector
*/
function allowlistToken(IERC20 token) external;
}

View File

@@ -0,0 +1,74 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.7.0;
/**
* @dev Registry of protocol IDs for external integrations with Balancer. The IDs chosen are arbitrary and do not affect
* behavior of any Balancer contracts. They are used only to tag specific contracts (usually pools) at the data layer.
*/
interface IProtocolIdRegistry {
// Emitted when a new protocol ID is registered.
event ProtocolIdRegistered(uint256 indexed protocolId, string name);
// Emitted when a protocol IDs name has been updated.
event ProtocolIdRenamed(uint256 indexed protocolId, string name);
/**
* @dev Registers an ID (and name) to differentiate among protocols. Protocol IDs cannot be deregistered.
*/
function registerProtocolId(uint256 protocolId, string memory name) external;
/**
* @dev Changes the name of an existing protocol ID. Should only be used to update in the case of mistakes.
*/
function renameProtocolId(uint256 protocolId, string memory newName) external;
/**
* @dev Returns true if `protocolId` has been registered and can be queried.
*/
function isValidProtocolId(uint256 protocolId) external view returns (bool);
/**
* @dev Returns the name associated with a given `protocolId`.
*/
function getProtocolName(uint256 protocolId) external view returns (string memory);
}
library ProtocolId {
// This list is not exhaustive - more protocol IDs can be added to the system. It is expected for this list to be
// extended with new protocol IDs as they are registered, to keep them all in one place and reduce
// likelihood of user error.
// solhint-disable private-vars-leading-underscore
uint256 internal constant AAVE_V1 = 0;
uint256 internal constant AAVE_V2 = 1;
uint256 internal constant AAVE_V3 = 2;
uint256 internal constant AMPLEFORTH = 3;
uint256 internal constant BEEFY = 4;
uint256 internal constant EULER = 5;
uint256 internal constant GEARBOX = 6;
uint256 internal constant IDLE = 7;
uint256 internal constant MORPHO = 8;
uint256 internal constant RADIANT = 9;
uint256 internal constant REAPER = 10;
uint256 internal constant SILO = 11;
uint256 internal constant STARGATE = 12;
uint256 internal constant STURDY = 13;
uint256 internal constant TESSERA = 14;
uint256 internal constant TETU = 15;
uint256 internal constant YEARN = 16;
uint256 internal constant MIDAS = 17;
uint256 internal constant AGAVE = 18;
// solhint-enable private-vars-leading-underscore
}

View File

@@ -0,0 +1,54 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
// Source: https://github.com/Byte-Masons/beet-strat/blob/master/contracts/ReaperVaultv1_4.sol
// Interface definition for the ReaperTokenVault contract, a single strategy vault
// for Reaper Farm crypts. The pricePerFullShare is always represented with 18 decimals,
// regardless of the underlying token decimals.
// ie: If ppfs === 1e18, 1 USDC === 0.000_000_000_001_000_000 rfUSDC
// ie: If ppfs === 1e18, 1 DAI === 1 rfDAI
interface IReaperTokenVault is IERC20 {
/**
* @dev returns the address of the vault's underlying asset (mainToken)
*/
function token() external view returns (address);
/**
* @dev returns the price for a single Vault share (ie rf-scfUSDT). The getPricePerFullShare is always in 1e18
*/
function getPricePerFullShare() external view returns (uint256);
/**
* @notice Deposits `_amount` `token`, issuing shares to the caller.
* If Panic is activated, deposits will not be accepted and this call will fail.
* @param _amount The quantity of tokens to deposit.
**/
function deposit(uint256 _amount) external;
/**
* @notice Withdraws the calling account's tokens from this Vault,
* redeeming amount `_shares` for an appropriate amount of tokens.
**/
function withdraw(uint256 _shares) external;
/**
* @dev returns the number of decimals for this vault token.
* For reaper single-strat vaults, the decimals are fixed to 18.
*/
function decimals() external view returns (uint8);
}

View File

@@ -0,0 +1,31 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
import "./ISilo.sol";
interface IShareToken is IERC20 {
/**
* @dev returns the underlying asset
*/
function asset() external view returns (address);
/**
* @dev returns the address of the silo
*/
function silo() external view returns (ISilo);
}

View File

@@ -0,0 +1,76 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "./IShareToken.sol";
interface IBaseSilo {
/// Storage struct that holds all required data for a single token market
struct AssetStorage {
// Token that represents a share in totalDeposits of Silo
IShareToken collateralToken;
// Token that represents a share in collateralOnlyDeposits of Silo
IShareToken collateralOnlyToken;
// Token that represents a share in totalBorrowAmount of Silo
IShareToken debtToken;
// COLLATERAL: Amount of asset token that has been deposited to Silo with interest earned by depositors.
// It also includes token amount that has been borrowed.
uint256 totalDeposits;
// COLLATERAL ONLY: Amount of asset token that has been deposited to Silo that can ONLY be used
// as collateral. These deposits do NOT earn interest and CANNOT be borrowed.
uint256 collateralOnlyDeposits;
// DEBT: Amount of asset token that has been borrowed with accrued interest.
uint256 totalBorrowAmount;
}
/**
* @dev returns the asset storage struct
* @dev AssetStorage struct contains necessary information for calculating shareToken exchange rates
*/
function assetStorage(address _asset) external view returns (AssetStorage memory);
}
interface ISilo is IBaseSilo {
/**
* @dev Deposits funds into the Silo
* @param _asset The address of the token to deposit
* @param _depositor The address of the recipient of collateral tokens
* @param _amount The amount of the token to deposit
* @param _collateralOnly: True means your shareToken is protected (cannot be swapped for interest)
* @return collateralAmount deposited amount
* @return collateralShare user collateral shares based on deposited amount
*/
function depositFor(
address _asset,
address _depositor,
uint256 _amount,
bool _collateralOnly
) external returns (uint256 collateralAmount, uint256 collateralShare);
/**
* @dev Withdraw `_amount` of `_asset` tokens from the Silo to `msg.sender`
* @param _asset The address of the token to withdraw
* @param _amount The amount of the token to withdraw
* @param _collateralOnly True if withdrawing collateral only deposit
* @return withdrawnAmount withdrawn amount that was transferred to user
* @return withdrawnShare burned share based on `withdrawnAmount`
*/
function withdraw(
address _asset,
uint256 _amount,
bool _collateralOnly
) external returns (uint256 withdrawnAmount, uint256 withdrawnShare);
}

View File

@@ -0,0 +1,247 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "../solidity-utils/openzeppelin/IERC20.sol";
// solhint-disable-next-line max-line-length
// Based on https://github.com/aave/protocol-v2/blob/ac58fea62bb8afee23f66197e8bce6d79ecda292/contracts/interfaces/IStaticATokenLM.sol
interface IStaticATokenLM is IERC20 {
struct SignatureParams {
uint8 v;
bytes32 r;
bytes32 s;
}
/**
* @notice Deposits `ASSET` in the Aave protocol and mints static aTokens to msg.sender
* @param recipient The address that will receive the static aTokens
* @param amount The amount of underlying `ASSET` to deposit (e.g. deposit of 100 USDC)
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
* @param fromUnderlying bool
* - `true` if the msg.sender comes with underlying tokens (e.g. USDC)
* - `false` if the msg.sender comes already with aTokens (e.g. aUSDC)
* @return uint256 The amount of StaticAToken minted, static balance
**/
function deposit(
address recipient,
uint256 amount,
uint16 referralCode,
bool fromUnderlying
) external returns (uint256);
/**
* @notice Burns `amount` of static aToken, with recipient receiving the corresponding amount of `ASSET`
* @param recipient The address that will receive the amount of `ASSET` withdrawn from the Aave protocol
* @param amount The amount to withdraw, in static balance of StaticAToken
* @param toUnderlying bool
* - `true` for the recipient to get underlying tokens (e.g. USDC)
* - `false` for the recipient to get aTokens (e.g. aUSDC)
* @return amountToBurn: StaticATokens burnt, static balance
* @return amountToWithdraw: underlying/aToken send to `recipient`, dynamic balance
**/
function withdraw(
address recipient,
uint256 amount,
bool toUnderlying
) external returns (uint256, uint256);
/**
* @notice Burns `amount` of static aToken, with recipient receiving the corresponding amount of `ASSET`
* @param recipient The address that will receive the amount of `ASSET` withdrawn from the Aave protocol
* @param amount The amount to withdraw, in dynamic balance of aToken/underlying asset
* @param toUnderlying bool
* - `true` for the recipient to get underlying tokens (e.g. USDC)
* - `false` for the recipient to get aTokens (e.g. aUSDC)
* @return amountToBurn: StaticATokens burnt, static balance
* @return amountToWithdraw: underlying/aToken send to `recipient`, dynamic balance
**/
function withdrawDynamicAmount(
address recipient,
uint256 amount,
bool toUnderlying
) external returns (uint256, uint256);
/**
* @notice Implements the permit function as for
* https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md
* @param owner The owner of the funds
* @param spender The spender
* @param value The amount
* @param deadline The deadline timestamp, type(uint256).max for max deadline
* @param v Signature param
* @param s Signature param
* @param r Signature param
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @notice Allows to deposit on Aave via meta-transaction
* https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md
* @param depositor Address from which the funds to deposit are going to be pulled
* @param recipient Address that will receive the staticATokens, in the average case, same as the `depositor`
* @param value The amount to deposit
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
* @param fromUnderlying bool
* - `true` if the msg.sender comes with underlying tokens (e.g. USDC)
* - `false` if the msg.sender comes already with aTokens (e.g. aUSDC)
* @param deadline The deadline timestamp, type(uint256).max for max deadline
* @param sigParams Signature params: v,r,s
* @return uint256 The amount of StaticAToken minted, static balance
*/
function metaDeposit(
address depositor,
address recipient,
uint256 value,
uint16 referralCode,
bool fromUnderlying,
uint256 deadline,
SignatureParams calldata sigParams
) external returns (uint256);
/**
* @notice Allows to withdraw from Aave via meta-transaction
* https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md
* @param owner Address owning the staticATokens
* @param recipient Address that will receive the underlying withdrawn from Aave
* @param staticAmount The amount of staticAToken to withdraw. If > 0, `dynamicAmount` needs to be 0
* @param dynamicAmount The amount of underlying/aToken to withdraw. If > 0, `staticAmount` needs to be 0
* @param toUnderlying bool
* - `true` for the recipient to get underlying tokens (e.g. USDC)
* - `false` for the recipient to get aTokens (e.g. aUSDC)
* @param deadline The deadline timestamp, type(uint256).max for max deadline
* @param sigParams Signature params: v,r,s
* @return amountToBurn: StaticATokens burnt, static balance
* @return amountToWithdraw: underlying/aToken send to `recipient`, dynamic balance
*/
function metaWithdraw(
address owner,
address recipient,
uint256 staticAmount,
uint256 dynamicAmount,
bool toUnderlying,
uint256 deadline,
SignatureParams calldata sigParams
) external returns (uint256, uint256);
/**
* @notice Utility method to get the current aToken balance of an user, from his staticAToken balance
* @param account The address of the user
* @return uint256 The aToken balance
**/
function dynamicBalanceOf(address account) external view returns (uint256);
/**
* @notice Converts a static amount (scaled balance on aToken) to the aToken/underlying value,
* using the current liquidity index on Aave
* @param amount The amount to convert from
* @return uint256 The dynamic amount
**/
function staticToDynamicAmount(uint256 amount) external view returns (uint256);
/**
* @notice Converts an aToken or underlying amount to the what it is denominated on the aToken as
* scaled balance, function of the principal and the liquidity index
* @param amount The amount to convert from
* @return uint256 The static (scaled) amount
**/
function dynamicToStaticAmount(uint256 amount) external view returns (uint256);
/**
* @notice Returns the Aave liquidity index of the underlying aToken, denominated rate here
* as it can be considered as an ever-increasing exchange rate
* @return The liquidity index
**/
function rate() external view returns (uint256);
/**
* @notice Function to return a dynamic domain separator, in order to be compatible with forks changing chainId
* @return bytes32 The domain separator
**/
function getDomainSeparator() external view returns (bytes32);
/**
* @notice Claims rewards from `INCENTIVES_CONTROLLER` and updates internal accounting of rewards.
*/
function collectAndUpdateRewards() external;
/**
* @notice Claim rewards on behalf of a user and send them to a receiver
* @dev Only callable by if sender is onBehalfOf or sender is approved claimer
* @param onBehalfOf The address to claim on behalf of
* @param receiver The address to receive the rewards
* @param forceUpdate Flag to retrieve latest rewards from `INCENTIVES_CONTROLLER`
*/
function claimRewardsOnBehalf(
address onBehalfOf,
address receiver,
bool forceUpdate
) external;
/**
* @notice Claim rewards and send them to a receiver
* @param receiver The address to receive the rewards
* @param forceUpdate Flag to retrieve latest rewards from `INCENTIVES_CONTROLLER`
*/
function claimRewards(address receiver, bool forceUpdate) external;
/**
* @notice Claim rewards
* @param forceUpdate Flag to retrieve latest rewards from `INCENTIVES_CONTROLLER`
*/
function claimRewardsToSelf(bool forceUpdate) external;
/**
* @notice Get the total claimable rewards of the contract.
* @return The current balance + pending rewards from the `_incentivesController`
*/
function getTotalClaimableRewards() external view returns (uint256);
/**
* @notice Get the total claimable rewards for a user in WAD
* @param user The address of the user
* @return The claimable amount of rewards in WAD
*/
function getClaimableRewards(address user) external view returns (uint256);
/**
* @notice The unclaimed rewards for a user in WAD
* @param user The address of the user
* @return The unclaimed amount of rewards in WAD
*/
function getUnclaimedRewards(address user) external view returns (uint256);
function getAccRewardsPerToken() external view returns (uint256);
function getLifetimeRewardsClaimed() external view returns (uint256);
function getLifetimeRewards() external view returns (uint256);
function getLastRewardBlock() external view returns (uint256);
// solhint-disable-next-line func-name-mixedcase
function LENDING_POOL() external returns (address);
// solhint-disable-next-line func-name-mixedcase
function INCENTIVES_CONTROLLER() external returns (address);
// solhint-disable-next-line func-name-mixedcase
function ATOKEN() external returns (IERC20);
// solhint-disable-next-line func-name-mixedcase
function ASSET() external returns (IERC20);
// solhint-disable-next-line func-name-mixedcase
function REWARD_TOKEN() external returns (IERC20);
}

View File

@@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
interface ITetuSmartVault is IERC20 {
function deposit(uint256 amount) external;
function depositFor(uint256 amount, address holder) external;
function underlyingBalanceInVault() external view returns (uint256);
function withdraw(uint256 numberOfShares) external;
function underlyingBalanceWithInvestmentForHolder(address holder) external view returns (uint256);
function underlying() external view returns (address);
function underlyingUnit() external view returns (uint256);
function getPricePerFullShare() external view returns (uint256);
function strategy() external view returns (address);
}

View File

@@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
interface ITetuStrategy {
function investedUnderlyingBalance() external view returns (uint256);
}

View File

@@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
import "./IButtonWrapper.sol";
// Balancer only supports ERC20 tokens, so we use this intermediate interface
// to enforce ERC20-ness of UnbuttonTokens.
interface IUnbuttonToken is IButtonWrapper, IERC20 {
// solhint-disable-previous-line no-empty-blocks
}

View File

@@ -0,0 +1,49 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity ^0.7.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
interface IYearnTokenVault is IERC20 {
/**
* @dev returns the address of the vault's underlying asset (mainToken)
*/
function token() external view returns (address);
/**
* @dev returns the price for a single Vault share (ie yvDAI). The pricePerShare is represented
* in the same decimals as the underlying asset (ie: 6 decimals for USDC)
*/
function pricePerShare() external view returns (uint256);
/**
* @notice Deposits `_amount` `token`, issuing shares to `recipient`.
* If the Vault is in Emergency Shutdown, deposits will not be accepted and this call will fail.
* @param _amount The quantity of tokens to deposit, defaults to all.
* @param recipient The address to issue the shares in this Vault to. Defaults to the caller's address.
* @return The issued Vault shares.
*/
function deposit(uint256 _amount, address recipient) external returns (uint256);
/**
* @notice Withdraws the calling account's tokens from this Vault,
* redeeming amount `_shares` for an appropriate amount of tokens.
* See note on `setWithdrawalQueue` for further details of withdrawal ordering and behavior.
* @param maxShares How many shares to try and redeem for tokens, defaults to all.
* @param recipient The address to issue the shares in this Vault to. Defaults to the caller's address.
* @return redeemed: The quantity of tokens redeemed for `_shares`.
*/
function withdraw(uint256 maxShares, address recipient) external returns (uint256);
}

View File

@@ -0,0 +1,24 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
// solhint-disable-next-line max-line-length
// Based on https://github.com/lidofinance/lido-dao/blob/816bf1d0995ba5cfdfc264de4acda34a7fe93eba/contracts/0.4.24/Lido.sol
interface IstETH is IERC20 {
function submit(address referral) external payable returns (uint256);
}

View File

@@ -0,0 +1,92 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../solidity-utils/openzeppelin/IERC20.sol";
import "./IstETH.sol";
// solhint-disable-next-line max-line-length
// Based on https://github.com/lidofinance/lido-dao/blob/2b46615a11dee77d4d22066f942f6c6afab9b87a/contracts/0.6.12/WstETH.sol
/**
* @title StETH token wrapper with static balances.
* @dev It's an ERC20 token that represents the account's share of the total
* supply of stETH tokens. WstETH token's balance only changes on transfers,
* unlike StETH that is also changed when oracles report staking rewards and
* penalties. It's a "power user" token for DeFi protocols which don't
* support rebasable tokens.
*
* The contract is also a trustless wrapper that accepts stETH tokens and mints
* wstETH in return. Then the user unwraps, the contract burns user's wstETH
* and sends user locked stETH in return.
*
* The contract provides the staking shortcut: user can send ETH with regular
* transfer and get wstETH in return. The contract will send ETH to Lido submit
* method, staking it and wrapping the received stETH.
*
*/
interface IwstETH is IERC20 {
function stETH() external returns (IstETH);
/**
* @notice Exchanges stETH to wstETH
* @param _stETHAmount amount of stETH to wrap in exchange for wstETH
* @dev Requirements:
* - `_stETHAmount` must be non-zero
* - msg.sender must approve at least `_stETHAmount` stETH to this
* contract.
* - msg.sender must have at least `_stETHAmount` of stETH.
* User should first approve _stETHAmount to the WstETH contract
* @return Amount of wstETH user receives after wrap
*/
function wrap(uint256 _stETHAmount) external returns (uint256);
/**
* @notice Exchanges wstETH to stETH
* @param _wstETHAmount amount of wstETH to uwrap in exchange for stETH
* @dev Requirements:
* - `_wstETHAmount` must be non-zero
* - msg.sender must have at least `_wstETHAmount` wstETH.
* @return Amount of stETH user receives after unwrap
*/
function unwrap(uint256 _wstETHAmount) external returns (uint256);
/**
* @notice Get amount of wstETH for a given amount of stETH
* @param _stETHAmount amount of stETH
* @return Amount of wstETH for a given stETH amount
*/
function getWstETHByStETH(uint256 _stETHAmount) external view returns (uint256);
/**
* @notice Get amount of stETH for a given amount of wstETH
* @param _wstETHAmount amount of wstETH
* @return Amount of stETH for a given wstETH amount
*/
function getStETHByWstETH(uint256 _wstETHAmount) external view returns (uint256);
/**
* @notice Get amount of wstETH for a one stETH
* @return Amount of stETH for 1 wstETH
*/
function stEthPerToken() external view returns (uint256);
/**
* @notice Get amount of stETH for a one wstETH
* @return Amount of wstETH for a 1 stETH
*/
function tokensPerStEth() external view returns (uint256);
}

View File

@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
/**
* @dev This is an empty interface used to represent either ERC20-conforming token contracts or ETH (using the zero
* address sentinel value). We're just relying on the fact that `interface` can be used to declare new address-like
* types.
*
* This concept is unrelated to a Pool's Asset Managers.
*/
interface IAsset {
// solhint-disable-previous-line no-empty-blocks
}

View File

@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
interface IAuthorizer {
/**
* @dev Returns true if `account` can perform the action described by `actionId` in the contract `where`.
*/
function canPerform(
bytes32 actionId,
address account,
address where
) external view returns (bool);
}

View File

@@ -0,0 +1,126 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "./IVault.sol";
import "./IPoolSwapStructs.sol";
/**
* @dev Interface for adding and removing liquidity that all Pool contracts should implement. Note that this is not
* the complete Pool contract interface, as it is missing the swap hooks. Pool contracts should also inherit from
* either IGeneralPool or IMinimalSwapInfoPool
*/
interface IBasePool is IPoolSwapStructs {
/**
* @dev Called by the Vault when a user calls `IVault.joinPool` to add liquidity to this Pool. Returns how many of
* each registered token the user should provide, as well as the amount of protocol fees the Pool owes to the Vault.
* The Vault will then take tokens from `sender` and add them to the Pool's balances, as well as collect
* the reported amount in protocol fees, which the pool should calculate based on `protocolSwapFeePercentage`.
*
* Protocol fees are reported and charged on join events so that the Pool is free of debt whenever new users join.
*
* `sender` is the account performing the join (from which tokens will be withdrawn), and `recipient` is the account
* designated to receive any benefits (typically pool shares). `balances` contains the total balances
* for each token the Pool registered in the Vault, in the same order that `IVault.getPoolTokens` would return.
*
* `lastChangeBlock` is the last block in which *any* of the Pool's registered tokens last changed its total
* balance.
*
* `userData` contains any pool-specific instructions needed to perform the calculations, such as the type of
* join (e.g., proportional given an amount of pool shares, single-asset, multi-asset, etc.)
*
* Contracts implementing this function should check that the caller is indeed the Vault before performing any
* state-changing operations, such as minting pool shares.
*/
function onJoinPool(
bytes32 poolId,
address sender,
address recipient,
uint256[] memory balances,
uint256 lastChangeBlock,
uint256 protocolSwapFeePercentage,
bytes memory userData
) external returns (uint256[] memory amountsIn, uint256[] memory dueProtocolFeeAmounts);
/**
* @dev Called by the Vault when a user calls `IVault.exitPool` to remove liquidity from this Pool. Returns how many
* tokens the Vault should deduct from the Pool's balances, as well as the amount of protocol fees the Pool owes
* to the Vault. The Vault will then take tokens from the Pool's balances and send them to `recipient`,
* as well as collect the reported amount in protocol fees, which the Pool should calculate based on
* `protocolSwapFeePercentage`.
*
* Protocol fees are charged on exit events to guarantee that users exiting the Pool have paid their share.
*
* `sender` is the account performing the exit (typically the pool shareholder), and `recipient` is the account
* to which the Vault will send the proceeds. `balances` contains the total token balances for each token
* the Pool registered in the Vault, in the same order that `IVault.getPoolTokens` would return.
*
* `lastChangeBlock` is the last block in which *any* of the Pool's registered tokens last changed its total
* balance.
*
* `userData` contains any pool-specific instructions needed to perform the calculations, such as the type of
* exit (e.g., proportional given an amount of pool shares, single-asset, multi-asset, etc.)
*
* Contracts implementing this function should check that the caller is indeed the Vault before performing any
* state-changing operations, such as burning pool shares.
*/
function onExitPool(
bytes32 poolId,
address sender,
address recipient,
uint256[] memory balances,
uint256 lastChangeBlock,
uint256 protocolSwapFeePercentage,
bytes memory userData
) external returns (uint256[] memory amountsOut, uint256[] memory dueProtocolFeeAmounts);
/**
* @dev Returns this Pool's ID, used when interacting with the Vault (to e.g. join the Pool or swap with it).
*/
function getPoolId() external view returns (bytes32);
/**
* @dev Returns the current swap fee percentage as a 18 decimal fixed point number, so e.g. 1e17 corresponds to a
* 10% swap fee.
*/
function getSwapFeePercentage() external view returns (uint256);
/**
* @dev Returns the scaling factors of each of the Pool's tokens. This is an implementation detail that is typically
* not relevant for outside parties, but which might be useful for some types of Pools.
*/
function getScalingFactors() external view returns (uint256[] memory);
function queryJoin(
bytes32 poolId,
address sender,
address recipient,
uint256[] memory balances,
uint256 lastChangeBlock,
uint256 protocolSwapFeePercentage,
bytes memory userData
) external returns (uint256 bptOut, uint256[] memory amountsIn);
function queryExit(
bytes32 poolId,
address sender,
address recipient,
uint256[] memory balances,
uint256 lastChangeBlock,
uint256 protocolSwapFeePercentage,
bytes memory userData
) external returns (uint256 bptIn, uint256[] memory amountsOut);
}

View File

@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "./IAuthorizer.sol";
interface IBasicAuthorizer is IAuthorizer {
// solhint-disable-next-line func-name-mixedcase
function DEFAULT_ADMIN_ROLE() external returns (bytes32);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function getRoleMember(bytes32 role, uint256 index) external view returns (address);
function getRoleMemberCount(bytes32 role) external view returns (uint256);
}

View File

@@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
// Inspired by Aave Protocol's IFlashLoanReceiver.
import "../solidity-utils/openzeppelin/IERC20.sol";
interface IFlashLoanRecipient {
/**
* @dev When `flashLoan` is called on the Vault, it invokes the `receiveFlashLoan` hook on the recipient.
*
* At the time of the call, the Vault will have transferred `amounts` for `tokens` to the recipient. Before this
* call returns, the recipient must have transferred `amounts` plus `feeAmounts` for each token back to the
* Vault, or else the entire flash loan will revert.
*
* `userData` is the same value passed in the `IVault.flashLoan` call.
*/
function receiveFlashLoan(
IERC20[] memory tokens,
uint256[] memory amounts,
uint256[] memory feeAmounts,
bytes memory userData
) external;
}

View File

@@ -0,0 +1,38 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "./IBasePool.sol";
/**
* @dev IPools with the General specialization setting should implement this interface.
*
* This is called by the Vault when a user calls `IVault.swap` or `IVault.batchSwap` to swap with this Pool.
* Returns the number of tokens the Pool will grant to the user in a 'given in' swap, or that the user will
* grant to the pool in a 'given out' swap.
*
* This can often be implemented by a `view` function, since many pricing algorithms don't need to track state
* changes in swaps. However, contracts implementing this in non-view functions should check that the caller is
* indeed the Vault.
*/
interface IGeneralPool is IBasePool {
function onSwap(
SwapRequest memory swapRequest,
uint256[] memory balances,
uint256 indexIn,
uint256 indexOut
) external returns (uint256 amount);
}

View File

@@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "./IBasePool.sol";
/**
* @dev Pool contracts with the MinimalSwapInfo or TwoToken specialization settings should implement this interface.
*
* This is called by the Vault when a user calls `IVault.swap` or `IVault.batchSwap` to swap with this Pool.
* Returns the number of tokens the Pool will grant to the user in a 'given in' swap, or that the user will grant
* to the pool in a 'given out' swap.
*
* This can often be implemented by a `view` function, since many pricing algorithms don't need to track state
* changes in swaps. However, contracts implementing this in non-view functions should check that the caller is
* indeed the Vault.
*/
interface IMinimalSwapInfoPool is IBasePool {
function onSwap(
SwapRequest memory swapRequest,
uint256 currentBalanceTokenIn,
uint256 currentBalanceTokenOut
) external returns (uint256 amount);
}

View File

@@ -0,0 +1,59 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "../solidity-utils/openzeppelin/IERC20.sol";
import "./IVault.sol";
interface IPoolSwapStructs {
// This is not really an interface - it just defines common structs used by other interfaces: IGeneralPool and
// IMinimalSwapInfoPool.
//
// This data structure represents a request for a token swap, where `kind` indicates the swap type ('given in' or
// 'given out') which indicates whether or not the amount sent by the pool is known.
//
// The pool receives `tokenIn` and sends `tokenOut`. `amount` is the number of `tokenIn` tokens the pool will take
// in, or the number of `tokenOut` tokens the Pool will send out, depending on the given swap `kind`.
//
// All other fields are not strictly necessary for most swaps, but are provided to support advanced scenarios in
// some Pools.
//
// `poolId` is the ID of the Pool involved in the swap - this is useful for Pool contracts that implement more than
// one Pool.
//
// The meaning of `lastChangeBlock` depends on the Pool specialization:
// - Two Token or Minimal Swap Info: the last block in which either `tokenIn` or `tokenOut` changed its total
// balance.
// - General: the last block in which *any* of the Pool's registered tokens changed its total balance.
//
// `from` is the origin address for the funds the Pool receives, and `to` is the destination address
// where the Pool sends the outgoing tokens.
//
// `userData` is extra data provided by the caller - typically a signature from a trusted party.
struct SwapRequest {
IVault.SwapKind kind;
IERC20 tokenIn;
IERC20 tokenOut;
uint256 amount;
// Misc data
bytes32 poolId;
uint256 lastChangeBlock;
address from;
address to;
bytes userData;
}
}

View File

@@ -0,0 +1,46 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "../solidity-utils/openzeppelin/IERC20.sol";
import "./IVault.sol";
import "./IAuthorizer.sol";
interface IProtocolFeesCollector {
event SwapFeePercentageChanged(uint256 newSwapFeePercentage);
event FlashLoanFeePercentageChanged(uint256 newFlashLoanFeePercentage);
function withdrawCollectedFees(
IERC20[] calldata tokens,
uint256[] calldata amounts,
address recipient
) external;
function setSwapFeePercentage(uint256 newSwapFeePercentage) external;
function setFlashLoanFeePercentage(uint256 newFlashLoanFeePercentage) external;
function getSwapFeePercentage() external view returns (uint256);
function getFlashLoanFeePercentage() external view returns (uint256);
function getCollectedFeeAmounts(IERC20[] memory tokens) external view returns (uint256[] memory feeAmounts);
function getAuthorizer() external view returns (IAuthorizer);
function vault() external view returns (IVault);
}

View File

@@ -0,0 +1,772 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma experimental ABIEncoderV2;
import "../solidity-utils/openzeppelin/IERC20.sol";
import "../solidity-utils/helpers/IAuthentication.sol";
import "../solidity-utils/helpers/ISignaturesValidator.sol";
import "../solidity-utils/helpers/ITemporarilyPausable.sol";
import "../solidity-utils/misc/IWETH.sol";
import "./IAsset.sol";
import "./IAuthorizer.sol";
import "./IFlashLoanRecipient.sol";
import "./IProtocolFeesCollector.sol";
pragma solidity >=0.7.0 <0.9.0;
/**
* @dev Full external interface for the Vault core contract - no external or public methods exist in the contract that
* don't override one of these declarations.
*/
interface IVault is ISignaturesValidator, ITemporarilyPausable, IAuthentication {
// Generalities about the Vault:
//
// - Whenever documentation refers to 'tokens', it strictly refers to ERC20-compliant token contracts. Tokens are
// transferred out of the Vault by calling the `IERC20.transfer` function, and transferred in by calling
// `IERC20.transferFrom`. In these cases, the sender must have previously allowed the Vault to use their tokens by
// calling `IERC20.approve`. The only deviation from the ERC20 standard that is supported is functions not returning
// a boolean value: in these scenarios, a non-reverting call is assumed to be successful.
//
// - All non-view functions in the Vault are non-reentrant: calling them while another one is mid-execution (e.g.
// while execution control is transferred to a token contract during a swap) will result in a revert. View
// functions can be called in a re-reentrant way, but doing so might cause them to return inconsistent results.
// Contracts calling view functions in the Vault must make sure the Vault has not already been entered.
//
// - View functions revert if referring to either unregistered Pools, or unregistered tokens for registered Pools.
// Authorizer
//
// Some system actions are permissioned, like setting and collecting protocol fees. This permissioning system exists
// outside of the Vault in the Authorizer contract: the Vault simply calls the Authorizer to check if the caller
// can perform a given action.
/**
* @dev Returns the Vault's Authorizer.
*/
function getAuthorizer() external view returns (IAuthorizer);
/**
* @dev Sets a new Authorizer for the Vault. The caller must be allowed by the current Authorizer to do this.
*
* Emits an `AuthorizerChanged` event.
*/
function setAuthorizer(IAuthorizer newAuthorizer) external;
/**
* @dev Emitted when a new authorizer is set by `setAuthorizer`.
*/
event AuthorizerChanged(IAuthorizer indexed newAuthorizer);
// Relayers
//
// Additionally, it is possible for an account to perform certain actions on behalf of another one, using their
// Vault ERC20 allowance and Internal Balance. These accounts are said to be 'relayers' for these Vault functions,
// and are expected to be smart contracts with sound authentication mechanisms. For an account to be able to wield
// this power, two things must occur:
// - The Authorizer must grant the account the permission to be a relayer for the relevant Vault function. This
// means that Balancer governance must approve each individual contract to act as a relayer for the intended
// functions.
// - Each user must approve the relayer to act on their behalf.
// This double protection means users cannot be tricked into approving malicious relayers (because they will not
// have been allowed by the Authorizer via governance), nor can malicious relayers approved by a compromised
// Authorizer or governance drain user funds, since they would also need to be approved by each individual user.
/**
* @dev Returns true if `user` has approved `relayer` to act as a relayer for them.
*/
function hasApprovedRelayer(address user, address relayer) external view returns (bool);
/**
* @dev Allows `relayer` to act as a relayer for `sender` if `approved` is true, and disallows it otherwise.
*
* Emits a `RelayerApprovalChanged` event.
*/
function setRelayerApproval(
address sender,
address relayer,
bool approved
) external;
/**
* @dev Emitted every time a relayer is approved or disapproved by `setRelayerApproval`.
*/
event RelayerApprovalChanged(address indexed relayer, address indexed sender, bool approved);
// Internal Balance
//
// Users can deposit tokens into the Vault, where they are allocated to their Internal Balance, and later
// transferred or withdrawn. It can also be used as a source of tokens when joining Pools, as a destination
// when exiting them, and as either when performing swaps. This usage of Internal Balance results in greatly reduced
// gas costs when compared to relying on plain ERC20 transfers, leading to large savings for frequent users.
//
// Internal Balance management features batching, which means a single contract call can be used to perform multiple
// operations of different kinds, with different senders and recipients, at once.
/**
* @dev Returns `user`'s Internal Balance for a set of tokens.
*/
function getInternalBalance(address user, IERC20[] memory tokens) external view returns (uint256[] memory);
/**
* @dev Performs a set of user balance operations, which involve Internal Balance (deposit, withdraw or transfer)
* and plain ERC20 transfers using the Vault's allowance. This last feature is particularly useful for relayers, as
* it lets integrators reuse a user's Vault allowance.
*
* For each operation, if the caller is not `sender`, it must be an authorized relayer for them.
*/
function manageUserBalance(UserBalanceOp[] memory ops) external payable;
/**
* @dev Data for `manageUserBalance` operations, which include the possibility for ETH to be sent and received
without manual WETH wrapping or unwrapping.
*/
struct UserBalanceOp {
UserBalanceOpKind kind;
IAsset asset;
uint256 amount;
address sender;
address payable recipient;
}
// There are four possible operations in `manageUserBalance`:
//
// - DEPOSIT_INTERNAL
// Increases the Internal Balance of the `recipient` account by transferring tokens from the corresponding
// `sender`. The sender must have allowed the Vault to use their tokens via `IERC20.approve()`.
//
// ETH can be used by passing the ETH sentinel value as the asset and forwarding ETH in the call: it will be wrapped
// and deposited as WETH. Any ETH amount remaining will be sent back to the caller (not the sender, which is
// relevant for relayers).
//
// Emits an `InternalBalanceChanged` event.
//
//
// - WITHDRAW_INTERNAL
// Decreases the Internal Balance of the `sender` account by transferring tokens to the `recipient`.
//
// ETH can be used by passing the ETH sentinel value as the asset. This will deduct WETH instead, unwrap it and send
// it to the recipient as ETH.
//
// Emits an `InternalBalanceChanged` event.
//
//
// - TRANSFER_INTERNAL
// Transfers tokens from the Internal Balance of the `sender` account to the Internal Balance of `recipient`.
//
// Reverts if the ETH sentinel value is passed.
//
// Emits an `InternalBalanceChanged` event.
//
//
// - TRANSFER_EXTERNAL
// Transfers tokens from `sender` to `recipient`, using the Vault's ERC20 allowance. This is typically used by
// relayers, as it lets them reuse a user's Vault allowance.
//
// Reverts if the ETH sentinel value is passed.
//
// Emits an `ExternalBalanceTransfer` event.
enum UserBalanceOpKind { DEPOSIT_INTERNAL, WITHDRAW_INTERNAL, TRANSFER_INTERNAL, TRANSFER_EXTERNAL }
/**
* @dev Emitted when a user's Internal Balance changes, either from calls to `manageUserBalance`, or through
* interacting with Pools using Internal Balance.
*
* Because Internal Balance works exclusively with ERC20 tokens, ETH deposits and withdrawals will use the WETH
* address.
*/
event InternalBalanceChanged(address indexed user, IERC20 indexed token, int256 delta);
/**
* @dev Emitted when a user's Vault ERC20 allowance is used by the Vault to transfer tokens to an external account.
*/
event ExternalBalanceTransfer(IERC20 indexed token, address indexed sender, address recipient, uint256 amount);
// Pools
//
// There are three specialization settings for Pools, which allow for cheaper swaps at the cost of reduced
// functionality:
//
// - General: no specialization, suited for all Pools. IGeneralPool is used for swap request callbacks, passing the
// balance of all tokens in the Pool. These Pools have the largest swap costs (because of the extra storage reads),
// which increase with the number of registered tokens.
//
// - Minimal Swap Info: IMinimalSwapInfoPool is used instead of IGeneralPool, which saves gas by only passing the
// balance of the two tokens involved in the swap. This is suitable for some pricing algorithms, like the weighted
// constant product one popularized by Balancer V1. Swap costs are smaller compared to general Pools, and are
// independent of the number of registered tokens.
//
// - Two Token: only allows two tokens to be registered. This achieves the lowest possible swap gas cost. Like
// minimal swap info Pools, these are called via IMinimalSwapInfoPool.
enum PoolSpecialization { GENERAL, MINIMAL_SWAP_INFO, TWO_TOKEN }
/**
* @dev Registers the caller account as a Pool with a given specialization setting. Returns the Pool's ID, which
* is used in all Pool-related functions. Pools cannot be deregistered, nor can the Pool's specialization be
* changed.
*
* The caller is expected to be a smart contract that implements either `IGeneralPool` or `IMinimalSwapInfoPool`,
* depending on the chosen specialization setting. This contract is known as the Pool's contract.
*
* Note that the same contract may register itself as multiple Pools with unique Pool IDs, or in other words,
* multiple Pools may share the same contract.
*
* Emits a `PoolRegistered` event.
*/
function registerPool(PoolSpecialization specialization) external returns (bytes32);
/**
* @dev Emitted when a Pool is registered by calling `registerPool`.
*/
event PoolRegistered(bytes32 indexed poolId, address indexed poolAddress, PoolSpecialization specialization);
/**
* @dev Returns a Pool's contract address and specialization setting.
*/
function getPool(bytes32 poolId) external view returns (address, PoolSpecialization);
/**
* @dev Registers `tokens` for the `poolId` Pool. Must be called by the Pool's contract.
*
* Pools can only interact with tokens they have registered. Users join a Pool by transferring registered tokens,
* exit by receiving registered tokens, and can only swap registered tokens.
*
* Each token can only be registered once. For Pools with the Two Token specialization, `tokens` must have a length
* of two, that is, both tokens must be registered in the same `registerTokens` call, and they must be sorted in
* ascending order.
*
* The `tokens` and `assetManagers` arrays must have the same length, and each entry in these indicates the Asset
* Manager for the corresponding token. Asset Managers can manage a Pool's tokens via `managePoolBalance`,
* depositing and withdrawing them directly, and can even set their balance to arbitrary amounts. They are therefore
* expected to be highly secured smart contracts with sound design principles, and the decision to register an
* Asset Manager should not be made lightly.
*
* Pools can choose not to assign an Asset Manager to a given token by passing in the zero address. Once an Asset
* Manager is set, it cannot be changed except by deregistering the associated token and registering again with a
* different Asset Manager.
*
* Emits a `TokensRegistered` event.
*/
function registerTokens(
bytes32 poolId,
IERC20[] memory tokens,
address[] memory assetManagers
) external;
/**
* @dev Emitted when a Pool registers tokens by calling `registerTokens`.
*/
event TokensRegistered(bytes32 indexed poolId, IERC20[] tokens, address[] assetManagers);
/**
* @dev Deregisters `tokens` for the `poolId` Pool. Must be called by the Pool's contract.
*
* Only registered tokens (via `registerTokens`) can be deregistered. Additionally, they must have zero total
* balance. For Pools with the Two Token specialization, `tokens` must have a length of two, that is, both tokens
* must be deregistered in the same `deregisterTokens` call.
*
* A deregistered token can be re-registered later on, possibly with a different Asset Manager.
*
* Emits a `TokensDeregistered` event.
*/
function deregisterTokens(bytes32 poolId, IERC20[] memory tokens) external;
/**
* @dev Emitted when a Pool deregisters tokens by calling `deregisterTokens`.
*/
event TokensDeregistered(bytes32 indexed poolId, IERC20[] tokens);
/**
* @dev Returns detailed information for a Pool's registered token.
*
* `cash` is the number of tokens the Vault currently holds for the Pool. `managed` is the number of tokens
* withdrawn and held outside the Vault by the Pool's token Asset Manager. The Pool's total balance for `token`
* equals the sum of `cash` and `managed`.
*
* Internally, `cash` and `managed` are stored using 112 bits. No action can ever cause a Pool's token `cash`,
* `managed` or `total` balance to be greater than 2^112 - 1.
*
* `lastChangeBlock` is the number of the block in which `token`'s total balance was last modified (via either a
* join, exit, swap, or Asset Manager update). This value is useful to avoid so-called 'sandwich attacks', for
* example when developing price oracles. A change of zero (e.g. caused by a swap with amount zero) is considered a
* change for this purpose, and will update `lastChangeBlock`.
*
* `assetManager` is the Pool's token Asset Manager.
*/
function getPoolTokenInfo(bytes32 poolId, IERC20 token)
external
view
returns (
uint256 cash,
uint256 managed,
uint256 lastChangeBlock,
address assetManager
);
/**
* @dev Returns a Pool's registered tokens, the total balance for each, and the latest block when *any* of
* the tokens' `balances` changed.
*
* The order of the `tokens` array is the same order that will be used in `joinPool`, `exitPool`, as well as in all
* Pool hooks (where applicable). Calls to `registerTokens` and `deregisterTokens` may change this order.
*
* If a Pool only registers tokens once, and these are sorted in ascending order, they will be stored in the same
* order as passed to `registerTokens`.
*
* Total balances include both tokens held by the Vault and those withdrawn by the Pool's Asset Managers. These are
* the amounts used by joins, exits and swaps. For a detailed breakdown of token balances, use `getPoolTokenInfo`
* instead.
*/
function getPoolTokens(bytes32 poolId)
external
view
returns (
IERC20[] memory tokens,
uint256[] memory balances,
uint256 lastChangeBlock
);
/**
* @dev Called by users to join a Pool, which transfers tokens from `sender` into the Pool's balance. This will
* trigger custom Pool behavior, which will typically grant something in return to `recipient` - often tokenized
* Pool shares.
*
* If the caller is not `sender`, it must be an authorized relayer for them.
*
* The `assets` and `maxAmountsIn` arrays must have the same length, and each entry indicates the maximum amount
* to send for each asset. The amounts to send are decided by the Pool and not the Vault: it just enforces
* these maximums.
*
* If joining a Pool that holds WETH, it is possible to send ETH directly: the Vault will do the wrapping. To enable
* this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead of the
* WETH address. Note that it is not possible to combine ETH and WETH in the same join. Any excess ETH will be sent
* back to the caller (not the sender, which is important for relayers).
*
* `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when
* interacting with Pools that register and deregister tokens frequently. If sending ETH however, the array must be
* sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the final
* `assets` array might not be sorted. Pools with no registered tokens cannot be joined.
*
* If `fromInternalBalance` is true, the caller's Internal Balance will be preferred: ERC20 transfers will only
* be made for the difference between the requested amount and Internal Balance (if any). Note that ETH cannot be
* withdrawn from Internal Balance: attempting to do so will trigger a revert.
*
* This causes the Vault to call the `IBasePool.onJoinPool` hook on the Pool's contract, where Pools implement
* their own custom logic. This typically requires additional information from the user (such as the expected number
* of Pool shares). This can be encoded in the `userData` argument, which is ignored by the Vault and passed
* directly to the Pool's contract, as is `recipient`.
*
* Emits a `PoolBalanceChanged` event.
*/
function joinPool(
bytes32 poolId,
address sender,
address recipient,
JoinPoolRequest memory request
) external payable;
struct JoinPoolRequest {
IAsset[] assets;
uint256[] maxAmountsIn;
bytes userData;
bool fromInternalBalance;
}
/**
* @dev Called by users to exit a Pool, which transfers tokens from the Pool's balance to `recipient`. This will
* trigger custom Pool behavior, which will typically ask for something in return from `sender` - often tokenized
* Pool shares. The amount of tokens that can be withdrawn is limited by the Pool's `cash` balance (see
* `getPoolTokenInfo`).
*
* If the caller is not `sender`, it must be an authorized relayer for them.
*
* The `tokens` and `minAmountsOut` arrays must have the same length, and each entry in these indicates the minimum
* token amount to receive for each token contract. The amounts to send are decided by the Pool and not the Vault:
* it just enforces these minimums.
*
* If exiting a Pool that holds WETH, it is possible to receive ETH directly: the Vault will do the unwrapping. To
* enable this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead
* of the WETH address. Note that it is not possible to combine ETH and WETH in the same exit.
*
* `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when
* interacting with Pools that register and deregister tokens frequently. If receiving ETH however, the array must
* be sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the
* final `assets` array might not be sorted. Pools with no registered tokens cannot be exited.
*
* If `toInternalBalance` is true, the tokens will be deposited to `recipient`'s Internal Balance. Otherwise,
* an ERC20 transfer will be performed. Note that ETH cannot be deposited to Internal Balance: attempting to
* do so will trigger a revert.
*
* `minAmountsOut` is the minimum amount of tokens the user expects to get out of the Pool, for each token in the
* `tokens` array. This array must match the Pool's registered tokens.
*
* This causes the Vault to call the `IBasePool.onExitPool` hook on the Pool's contract, where Pools implement
* their own custom logic. This typically requires additional information from the user (such as the expected number
* of Pool shares to return). This can be encoded in the `userData` argument, which is ignored by the Vault and
* passed directly to the Pool's contract.
*
* Emits a `PoolBalanceChanged` event.
*/
function exitPool(
bytes32 poolId,
address sender,
address payable recipient,
ExitPoolRequest memory request
) external;
struct ExitPoolRequest {
IAsset[] assets;
uint256[] minAmountsOut;
bytes userData;
bool toInternalBalance;
}
/**
* @dev Emitted when a user joins or exits a Pool by calling `joinPool` or `exitPool`, respectively.
*/
event PoolBalanceChanged(
bytes32 indexed poolId,
address indexed liquidityProvider,
IERC20[] tokens,
int256[] deltas,
uint256[] protocolFeeAmounts
);
enum PoolBalanceChangeKind { JOIN, EXIT }
// Swaps
//
// Users can swap tokens with Pools by calling the `swap` and `batchSwap` functions. To do this,
// they need not trust Pool contracts in any way: all security checks are made by the Vault. They must however be
// aware of the Pools' pricing algorithms in order to estimate the prices Pools will quote.
//
// The `swap` function executes a single swap, while `batchSwap` can perform multiple swaps in sequence.
// In each individual swap, tokens of one kind are sent from the sender to the Pool (this is the 'token in'),
// and tokens of another kind are sent from the Pool to the recipient in exchange (this is the 'token out').
// More complex swaps, such as one token in to multiple tokens out can be achieved by batching together
// individual swaps.
//
// There are two swap kinds:
// - 'given in' swaps, where the amount of tokens in (sent to the Pool) is known, and the Pool determines (via the
// `onSwap` hook) the amount of tokens out (to send to the recipient).
// - 'given out' swaps, where the amount of tokens out (received from the Pool) is known, and the Pool determines
// (via the `onSwap` hook) the amount of tokens in (to receive from the sender).
//
// Additionally, it is possible to chain swaps using a placeholder input amount, which the Vault replaces with
// the calculated output of the previous swap. If the previous swap was 'given in', this will be the calculated
// tokenOut amount. If the previous swap was 'given out', it will use the calculated tokenIn amount. These extended
// swaps are known as 'multihop' swaps, since they 'hop' through a number of intermediate tokens before arriving at
// the final intended token.
//
// In all cases, tokens are only transferred in and out of the Vault (or withdrawn from and deposited into Internal
// Balance) after all individual swaps have been completed, and the net token balance change computed. This makes
// certain swap patterns, such as multihops, or swaps that interact with the same token pair in multiple Pools, cost
// much less gas than they would otherwise.
//
// It also means that under certain conditions it is possible to perform arbitrage by swapping with multiple
// Pools in a way that results in net token movement out of the Vault (profit), with no tokens being sent in (only
// updating the Pool's internal accounting).
//
// To protect users from front-running or the market changing rapidly, they supply a list of 'limits' for each token
// involved in the swap, where either the maximum number of tokens to send (by passing a positive value) or the
// minimum amount of tokens to receive (by passing a negative value) is specified.
//
// Additionally, a 'deadline' timestamp can also be provided, forcing the swap to fail if it occurs after
// this point in time (e.g. if the transaction failed to be included in a block promptly).
//
// If interacting with Pools that hold WETH, it is possible to both send and receive ETH directly: the Vault will do
// the wrapping and unwrapping. To enable this mechanism, the IAsset sentinel value (the zero address) must be
// passed in the `assets` array instead of the WETH address. Note that it is possible to combine ETH and WETH in the
// same swap. Any excess ETH will be sent back to the caller (not the sender, which is relevant for relayers).
//
// Finally, Internal Balance can be used when either sending or receiving tokens.
enum SwapKind { GIVEN_IN, GIVEN_OUT }
/**
* @dev Performs a swap with a single Pool.
*
* If the swap is 'given in' (the number of tokens to send to the Pool is known), it returns the amount of tokens
* taken from the Pool, which must be greater than or equal to `limit`.
*
* If the swap is 'given out' (the number of tokens to take from the Pool is known), it returns the amount of tokens
* sent to the Pool, which must be less than or equal to `limit`.
*
* Internal Balance usage and the recipient are determined by the `funds` struct.
*
* Emits a `Swap` event.
*/
function swap(
SingleSwap memory singleSwap,
FundManagement memory funds,
uint256 limit,
uint256 deadline
) external payable returns (uint256);
/**
* @dev Data for a single swap executed by `swap`. `amount` is either `amountIn` or `amountOut` depending on
* the `kind` value.
*
* `assetIn` and `assetOut` are either token addresses, or the IAsset sentinel value for ETH (the zero address).
* Note that Pools never interact with ETH directly: it will be wrapped to or unwrapped from WETH by the Vault.
*
* The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be
* used to extend swap behavior.
*/
struct SingleSwap {
bytes32 poolId;
SwapKind kind;
IAsset assetIn;
IAsset assetOut;
uint256 amount;
bytes userData;
}
/**
* @dev Performs a series of swaps with one or multiple Pools. In each individual swap, the caller determines either
* the amount of tokens sent to or received from the Pool, depending on the `kind` value.
*
* Returns an array with the net Vault asset balance deltas. Positive amounts represent tokens (or ETH) sent to the
* Vault, and negative amounts represent tokens (or ETH) sent by the Vault. Each delta corresponds to the asset at
* the same index in the `assets` array.
*
* Swaps are executed sequentially, in the order specified by the `swaps` array. Each array element describes a
* Pool, the token to be sent to this Pool, the token to receive from it, and an amount that is either `amountIn` or
* `amountOut` depending on the swap kind.
*
* Multihop swaps can be executed by passing an `amount` value of zero for a swap. This will cause the amount in/out
* of the previous swap to be used as the amount in for the current one. In a 'given in' swap, 'tokenIn' must equal
* the previous swap's `tokenOut`. For a 'given out' swap, `tokenOut` must equal the previous swap's `tokenIn`.
*
* The `assets` array contains the addresses of all assets involved in the swaps. These are either token addresses,
* or the IAsset sentinel value for ETH (the zero address). Each entry in the `swaps` array specifies tokens in and
* out by referencing an index in `assets`. Note that Pools never interact with ETH directly: it will be wrapped to
* or unwrapped from WETH by the Vault.
*
* Internal Balance usage, sender, and recipient are determined by the `funds` struct. The `limits` array specifies
* the minimum or maximum amount of each token the vault is allowed to transfer.
*
* `batchSwap` can be used to make a single swap, like `swap` does, but doing so requires more gas than the
* equivalent `swap` call.
*
* Emits `Swap` events.
*/
function batchSwap(
SwapKind kind,
BatchSwapStep[] memory swaps,
IAsset[] memory assets,
FundManagement memory funds,
int256[] memory limits,
uint256 deadline
) external payable returns (int256[] memory);
/**
* @dev Data for each individual swap executed by `batchSwap`. The asset in and out fields are indexes into the
* `assets` array passed to that function, and ETH assets are converted to WETH.
*
* If `amount` is zero, the multihop mechanism is used to determine the actual amount based on the amount in/out
* from the previous swap, depending on the swap kind.
*
* The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be
* used to extend swap behavior.
*/
struct BatchSwapStep {
bytes32 poolId;
uint256 assetInIndex;
uint256 assetOutIndex;
uint256 amount;
bytes userData;
}
/**
* @dev Emitted for each individual swap performed by `swap` or `batchSwap`.
*/
event Swap(
bytes32 indexed poolId,
IERC20 indexed tokenIn,
IERC20 indexed tokenOut,
uint256 amountIn,
uint256 amountOut
);
/**
* @dev All tokens in a swap are either sent from the `sender` account to the Vault, or from the Vault to the
* `recipient` account.
*
* If the caller is not `sender`, it must be an authorized relayer for them.
*
* If `fromInternalBalance` is true, the `sender`'s Internal Balance will be preferred, performing an ERC20
* transfer for the difference between the requested amount and the User's Internal Balance (if any). The `sender`
* must have allowed the Vault to use their tokens via `IERC20.approve()`. This matches the behavior of
* `joinPool`.
*
* If `toInternalBalance` is true, tokens will be deposited to `recipient`'s internal balance instead of
* transferred. This matches the behavior of `exitPool`.
*
* Note that ETH cannot be deposited to or withdrawn from Internal Balance: attempting to do so will trigger a
* revert.
*/
struct FundManagement {
address sender;
bool fromInternalBalance;
address payable recipient;
bool toInternalBalance;
}
/**
* @dev Simulates a call to `batchSwap`, returning an array of Vault asset deltas. Calls to `swap` cannot be
* simulated directly, but an equivalent `batchSwap` call can and will yield the exact same result.
*
* Each element in the array corresponds to the asset at the same index, and indicates the number of tokens (or ETH)
* the Vault would take from the sender (if positive) or send to the recipient (if negative). The arguments it
* receives are the same that an equivalent `batchSwap` call would receive.
*
* Unlike `batchSwap`, this function performs no checks on the sender or recipient field in the `funds` struct.
* This makes it suitable to be called by off-chain applications via eth_call without needing to hold tokens,
* approve them for the Vault, or even know a user's address.
*
* Note that this function is not 'view' (due to implementation details): the client code must explicitly execute
* eth_call instead of eth_sendTransaction.
*/
function queryBatchSwap(
SwapKind kind,
BatchSwapStep[] memory swaps,
IAsset[] memory assets,
FundManagement memory funds
) external returns (int256[] memory assetDeltas);
// Flash Loans
/**
* @dev Performs a 'flash loan', sending tokens to `recipient`, executing the `receiveFlashLoan` hook on it,
* and then reverting unless the tokens plus a proportional protocol fee have been returned.
*
* The `tokens` and `amounts` arrays must have the same length, and each entry in these indicates the loan amount
* for each token contract. `tokens` must be sorted in ascending order.
*
* The 'userData' field is ignored by the Vault, and forwarded as-is to `recipient` as part of the
* `receiveFlashLoan` call.
*
* Emits `FlashLoan` events.
*/
function flashLoan(
IFlashLoanRecipient recipient,
IERC20[] memory tokens,
uint256[] memory amounts,
bytes memory userData
) external;
/**
* @dev Emitted for each individual flash loan performed by `flashLoan`.
*/
event FlashLoan(IFlashLoanRecipient indexed recipient, IERC20 indexed token, uint256 amount, uint256 feeAmount);
// Asset Management
//
// Each token registered for a Pool can be assigned an Asset Manager, which is able to freely withdraw the Pool's
// tokens from the Vault, deposit them, or assign arbitrary values to its `managed` balance (see
// `getPoolTokenInfo`). This makes them extremely powerful and dangerous. Even if an Asset Manager only directly
// controls one of the tokens in a Pool, a malicious manager could set that token's balance to manipulate the
// prices of the other tokens, and then drain the Pool with swaps. The risk of using Asset Managers is therefore
// not constrained to the tokens they are managing, but extends to the entire Pool's holdings.
//
// However, a properly designed Asset Manager smart contract can be safely used for the Pool's benefit,
// for example by lending unused tokens out for interest, or using them to participate in voting protocols.
//
// This concept is unrelated to the IAsset interface.
/**
* @dev Performs a set of Pool balance operations, which may be either withdrawals, deposits or updates.
*
* Pool Balance management features batching, which means a single contract call can be used to perform multiple
* operations of different kinds, with different Pools and tokens, at once.
*
* For each operation, the caller must be registered as the Asset Manager for `token` in `poolId`.
*/
function managePoolBalance(PoolBalanceOp[] memory ops) external;
struct PoolBalanceOp {
PoolBalanceOpKind kind;
bytes32 poolId;
IERC20 token;
uint256 amount;
}
/**
* Withdrawals decrease the Pool's cash, but increase its managed balance, leaving the total balance unchanged.
*
* Deposits increase the Pool's cash, but decrease its managed balance, leaving the total balance unchanged.
*
* Updates don't affect the Pool's cash balance, but because the managed balance changes, it does alter the total.
* The external amount can be either increased or decreased by this call (i.e., reporting a gain or a loss).
*/
enum PoolBalanceOpKind { WITHDRAW, DEPOSIT, UPDATE }
/**
* @dev Emitted when a Pool's token Asset Manager alters its balance via `managePoolBalance`.
*/
event PoolBalanceManaged(
bytes32 indexed poolId,
address indexed assetManager,
IERC20 indexed token,
int256 cashDelta,
int256 managedDelta
);
// Protocol Fees
//
// Some operations cause the Vault to collect tokens in the form of protocol fees, which can then be withdrawn by
// permissioned accounts.
//
// There are two kinds of protocol fees:
//
// - flash loan fees: charged on all flash loans, as a percentage of the amounts lent.
//
// - swap fees: a percentage of the fees charged by Pools when performing swaps. For a number of reasons, including
// swap gas costs and interface simplicity, protocol swap fees are not charged on each individual swap. Rather,
// Pools are expected to keep track of how much they have charged in swap fees, and pay any outstanding debts to the
// Vault when they are joined or exited. This prevents users from joining a Pool with unpaid debt, as well as
// exiting a Pool in debt without first paying their share.
/**
* @dev Returns the current protocol fee module.
*/
function getProtocolFeesCollector() external view returns (IProtocolFeesCollector);
/**
* @dev Safety mechanism to pause most Vault operations in the event of an emergency - typically detection of an
* error in some part of the system.
*
* The Vault can only be paused during an initial time period, after which pausing is forever disabled.
*
* While the contract is paused, the following features are disabled:
* - depositing and transferring internal balance
* - transferring external balance (using the Vault's allowance)
* - swaps
* - joining Pools
* - Asset Manager interactions
*
* Internal Balance can still be withdrawn, and Pools exited.
*/
function setPaused(bool paused) external;
/**
* @dev Returns the Vault's WETH instance.
*/
function WETH() external view returns (IWETH);
// solhint-disable-previous-line func-name-mixedcase
}

View File

@@ -0,0 +1,58 @@
{
"name": "@balancer-labs/v2-interfaces",
"version": "0.4.0",
"description": "V2 Interfaces",
"license": "GPL-3.0-only",
"homepage": "https://github.com/balancer-labs/balancer-v2-monorepo/tree/master/pkg/interfaces#readme",
"repository": {
"type": "git",
"url": "https://github.com/balancer-labs/balancer-v2-monorepo.git",
"directory": "pkg/interfaces"
},
"bugs": {
"url": "https://github.com/balancer-labs/balancer-v2-monorepo/issues"
},
"files": [
"contracts/**/*"
],
"scripts": {
"build": "yarn compile",
"compile": "hardhat compile && rm -rf artifacts/build-info",
"compile:watch": "nodemon --ext sol --exec yarn compile",
"lint": "yarn lint:solidity && yarn lint:typescript",
"lint:solidity": "solhint 'contracts/**/*.sol'",
"lint:typescript": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ../../.eslintignore --max-warnings 0"
},
"devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.2.1",
"@nomiclabs/hardhat-waffle": "^2.0.3",
"@types/chai": "^4.3.3",
"@types/lodash": "^4.14.186",
"@types/mocha": "^10.0.0",
"@types/node": "^14.14.31",
"@typescript-eslint/eslint-plugin": "^5.41.0",
"@typescript-eslint/parser": "^5.41.0",
"chai": "^4.3.6",
"decimal.js": "^10.4.2",
"eslint": "^8.26.0",
"eslint-plugin-mocha-no-only": "^1.1.1",
"eslint-plugin-prettier": "^4.2.1",
"ethereum-waffle": "^3.4.4",
"ethers": "^5.7.2",
"hardhat": "^2.12.5",
"hardhat-ignore-warnings": "^0.2.4",
"lodash.frompairs": "^4.0.1",
"lodash.pick": "^4.4.0",
"lodash.range": "^3.2.0",
"lodash.times": "^4.3.2",
"lodash.zip": "^4.2.0",
"mocha": "^10.1.0",
"nodemon": "^2.0.20",
"prettier": "^2.7.1",
"prettier-plugin-solidity": "v1.0.0-alpha.59",
"solhint": "^3.2.0",
"solhint-plugin-prettier": "^0.0.4",
"ts-node": "^10.9.1",
"typescript": "^4.0.2"
}
}

View File

@@ -3,3 +3,4 @@
@permit2/=lib/permit2/
@src/=src/
@uniswap-v2/=lib/v2-core/
@balancer-labs/v2-interfaces/=lib/balancer-labs/v2-interfaces/

View File

@@ -0,0 +1,91 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;
import "@interfaces/IExecutor.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@balancer-labs/v2-interfaces/contracts/vault/IAsset.sol";
import "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol";
error BalancerV2Executor__InvalidDataLength();
contract BalancerV2Executor is IExecutor {
using SafeERC20 for IERC20;
address private constant VAULT = 0xBA12222222228d8Ba445958a75a0704d566BF2C8;
function swap(uint256 givenAmount, bytes calldata data)
external
returns (uint256 calculatedAmount)
{
(
IERC20 tokenIn,
IERC20 tokenOut,
bytes32 poolId,
address receiver,
bool exactOut,
bool needsApproval
) = _decodeData(data);
if (needsApproval) {
tokenIn.safeApprove(VAULT, type(uint256).max);
}
IVault.SingleSwap memory singleSwap = IVault.SingleSwap({
poolId: poolId,
kind: exactOut ? IVault.SwapKind.GIVEN_OUT : IVault.SwapKind.GIVEN_IN,
assetIn: IAsset(address(tokenIn)),
assetOut: IAsset(address(tokenOut)),
amount: givenAmount,
userData: ""
});
IVault.FundManagement memory funds = IVault.FundManagement({
sender: address(this),
fromInternalBalance: false,
recipient: payable(receiver),
toInternalBalance: false
});
uint256 limit = exactOut ? type(uint256).max : 0;
calculatedAmount = IVault(VAULT).swap(
singleSwap,
funds,
limit,
block.timestamp
);
}
function _decodeData(bytes calldata data)
internal
pure
returns (
IERC20 tokenIn,
IERC20 tokenOut,
bytes32 poolId,
address receiver,
bool exactOut,
bool needsApproval
)
{
// Verify data length (20 + 20 + 32 + 20 + 1 + 1 = 94 bytes)
if (data.length != 94) {
revert BalancerV2Executor__InvalidDataLength();
}
tokenIn = IERC20(address(bytes20(data[0:20])));
tokenOut = IERC20(address(bytes20(data[20:40])));
poolId = bytes32(data[40:72]);
receiver = address(bytes20(data[72:92]));
exactOut = uint8(data[92]) > 0;
needsApproval = uint8(data[93]) > 0;
}
}