编译器
0.8.11+commit.d7f03943
文件 1 的 21:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 21:AeraVaultV1.sol
pragma solidity 0.8.11;
import "./dependencies/openzeppelin/SafeERC20.sol";
import "./dependencies/openzeppelin/IERC20.sol";
import "./dependencies/openzeppelin/Ownable.sol";
import "./dependencies/openzeppelin/ReentrancyGuard.sol";
import "./dependencies/openzeppelin/Math.sol";
import "./dependencies/openzeppelin/ERC165Checker.sol";
import "./interfaces/IBManagedPoolFactory.sol";
import "./interfaces/IBManagedPoolController.sol";
import "./interfaces/IBMerkleOrchard.sol";
import "./interfaces/IBVault.sol";
import "./interfaces/IBManagedPool.sol";
import "./interfaces/IAeraVaultV1.sol";
import "./interfaces/IWithdrawalValidator.sol";
contract AeraVaultV1 is IAeraVaultV1, Ownable, ReentrancyGuard {
using SafeERC20 for IERC20;
uint256 internal constant ONE = 10**18;
uint256 private constant MINIMUM_WEIGHT_CHANGE_DURATION = 4 hours;
uint256 private constant MAXIMUM_SWAP_FEE_PERCENT_CHANGE = 0.005e18;
address private constant UNSET_GUARDIAN_ADDRESS = address(0);
uint256 private constant MAX_NOTICE_PERIOD = 60 days;
uint256 private constant SWAP_FEE_COOLDOWN_PERIOD = 1 minutes;
uint256 private constant MAX_WEIGHT_CHANGE_RATIO = 10**16;
uint256 private constant MAX_MANAGEMENT_FEE = 10**9;
IBVault public immutable bVault;
IBManagedPool public immutable pool;
IBManagedPoolController public immutable poolController;
IBMerkleOrchard public immutable merkleOrchard;
bytes32 public immutable poolId;
uint256 public immutable noticePeriod;
IWithdrawalValidator public immutable validator;
uint256 public immutable managementFee;
string public description;
bool public initialized;
bool public finalized;
address public guardian;
address public pendingOwner;
uint256 public noticeTimeoutAt;
uint256 public lastFeeCheckpoint = type(uint256).max;
mapping(address => uint256[]) public guardiansFee;
uint256[] public guardiansFeeTotal;
uint256 public lastSwapFeeCheckpoint;
event Created(
address indexed factory,
string name,
string symbol,
IERC20[] tokens,
uint256[] weights,
uint256 swapFeePercentage,
address indexed guardian,
address indexed validator,
uint256 noticePeriod,
uint256 managementFee,
address merkleOrchard,
string description
);
event Deposit(
uint256[] requestedAmounts,
uint256[] amounts,
uint256[] weights
);
event Withdraw(
uint256[] requestedAmounts,
uint256[] amounts,
uint256[] allowances,
uint256[] weights
);
event DistributeGuardianFees(address indexed guardian, uint256[] amounts);
event GuardianChanged(
address indexed previousGuardian,
address indexed guardian
);
event UpdateWeightsGradually(
uint256 startTime,
uint256 endTime,
uint256[] weights
);
event CancelWeightUpdates(uint256[] weights);
event SetSwapEnabled(bool swapEnabled);
event EnabledTradingWithWeights(uint256 time, uint256[] weights);
event SetSwapFee(uint256 swapFee);
event FinalizationInitiated(uint256 noticeTimeoutAt);
event Finalized(address indexed caller, uint256[] amounts);
event OwnershipTransferOffered(
address indexed currentOwner,
address indexed pendingOwner
);
event OwnershipTransferCanceled(
address indexed currentOwner,
address indexed canceledOwner
);
error Aera__ValueLengthIsNotSame(uint256 numTokens, uint256 numValues);
error Aera__DifferentTokensInPosition(
address actual,
address sortedToken,
uint256 index
);
error Aera__ValidatorIsNotMatched(
uint256 numTokens,
uint256 numAllowances
);
error Aera__ValidatorIsNotValid(address validator);
error Aera__ManagementFeeIsAboveMax(uint256 actual, uint256 max);
error Aera__NoticePeriodIsAboveMax(uint256 actual, uint256 max);
error Aera__NoticeTimeoutNotElapsed(uint256 noticeTimeoutAt);
error Aera__GuardianIsZeroAddress();
error Aera__GuardianIsOwner(address newGuardian);
error Aera__CallerIsNotGuardian();
error Aera__SwapFeePercentageChangeIsAboveMax(uint256 actual, uint256 max);
error Aera__DescriptionIsEmpty();
error Aera__CallerIsNotOwnerOrGuardian();
error Aera__WeightChangeEndBeforeStart();
error Aera__WeightChangeStartTimeIsAboveMax(uint256 actual, uint256 max);
error Aera__WeightChangeEndTimeIsAboveMax(uint256 actual, uint256 max);
error Aera__WeightChangeDurationIsBelowMin(uint256 actual, uint256 min);
error Aera__WeightChangeRatioIsAboveMax(
address token,
uint256 actual,
uint256 max
);
error Aera__WeightIsAboveMax(uint256 actual, uint256 max);
error Aera__WeightIsBelowMin(uint256 actual, uint256 min);
error Aera__AmountIsBelowMin(uint256 actual, uint256 min);
error Aera__AmountExceedAvailable(
address token,
uint256 amount,
uint256 available
);
error Aera__NoAvailableFeeForCaller(address caller);
error Aera__BalanceChangedInCurrentBlock();
error Aera__CannotSweepPoolToken();
error Aera__PoolSwapIsAlreadyEnabled();
error Aera__CannotSetSwapFeeBeforeCooldown();
error Aera__FinalizationNotInitiated();
error Aera__VaultNotInitialized();
error Aera__VaultIsAlreadyInitialized();
error Aera__VaultIsFinalizing();
error Aera__VaultIsAlreadyFinalized();
error Aera__VaultIsNotRenounceable();
error Aera__OwnerIsZeroAddress();
error Aera__NotPendingOwner();
error Aera__NoPendingOwnershipTransfer();
modifier onlyGuardian() {
if (msg.sender != guardian) {
revert Aera__CallerIsNotGuardian();
}
_;
}
modifier onlyOwnerOrGuardian() {
if (msg.sender != owner() && msg.sender != guardian) {
revert Aera__CallerIsNotOwnerOrGuardian();
}
_;
}
modifier whenInitialized() {
if (!initialized) {
revert Aera__VaultNotInitialized();
}
_;
}
modifier whenNotFinalizing() {
if (noticeTimeoutAt != 0) {
revert Aera__VaultIsFinalizing();
}
_;
}
constructor(NewVaultParams memory vaultParams) {
uint256 numTokens = vaultParams.tokens.length;
if (numTokens != vaultParams.weights.length) {
revert Aera__ValueLengthIsNotSame(
numTokens,
vaultParams.weights.length
);
}
if (
!ERC165Checker.supportsInterface(
vaultParams.validator,
type(IWithdrawalValidator).interfaceId
)
) {
revert Aera__ValidatorIsNotValid(vaultParams.validator);
}
{
uint256 numAllowances = IWithdrawalValidator(vaultParams.validator)
.allowance()
.length;
if (numTokens != numAllowances) {
revert Aera__ValidatorIsNotMatched(numTokens, numAllowances);
}
}
if (vaultParams.managementFee > MAX_MANAGEMENT_FEE) {
revert Aera__ManagementFeeIsAboveMax(
vaultParams.managementFee,
MAX_MANAGEMENT_FEE
);
}
if (vaultParams.noticePeriod > MAX_NOTICE_PERIOD) {
revert Aera__NoticePeriodIsAboveMax(
vaultParams.noticePeriod,
MAX_NOTICE_PERIOD
);
}
if (bytes(vaultParams.description).length == 0) {
revert Aera__DescriptionIsEmpty();
}
checkGuardianAddress(vaultParams.guardian);
address[] memory assetManagers = new address[](numTokens);
for (uint256 i = 0; i < numTokens; i++) {
assetManagers[i] = address(this);
}
pool = IBManagedPool(
IBManagedPoolFactory(vaultParams.factory).create(
IBManagedPoolFactory.NewPoolParams({
vault: IBVault(address(0)),
name: vaultParams.name,
symbol: vaultParams.symbol,
tokens: vaultParams.tokens,
normalizedWeights: vaultParams.weights,
assetManagers: assetManagers,
swapFeePercentage: vaultParams.swapFeePercentage,
pauseWindowDuration: 0,
bufferPeriodDuration: 0,
owner: address(this),
swapEnabledOnStart: false,
mustAllowlistLPs: true,
managementSwapFeePercentage: 0
}),
IBManagedPoolFactory.BasePoolRights({
canTransferOwnership: false,
canChangeSwapFee: true,
canUpdateMetadata: false
}),
IBManagedPoolFactory.ManagedPoolRights({
canChangeWeights: true,
canDisableSwaps: true,
canSetMustAllowlistLPs: false,
canSetCircuitBreakers: false,
canChangeTokens: false
}),
0
)
);
bVault = pool.getVault();
poolController = IBManagedPoolController(pool.getOwner());
merkleOrchard = IBMerkleOrchard(vaultParams.merkleOrchard);
poolId = pool.getPoolId();
guardian = vaultParams.guardian;
validator = IWithdrawalValidator(vaultParams.validator);
noticePeriod = vaultParams.noticePeriod;
description = vaultParams.description;
managementFee = vaultParams.managementFee;
guardiansFee[guardian] = new uint256[](numTokens);
guardiansFeeTotal = new uint256[](numTokens);
emit Created(
vaultParams.factory,
vaultParams.name,
vaultParams.symbol,
vaultParams.tokens,
vaultParams.weights,
vaultParams.swapFeePercentage,
vaultParams.guardian,
vaultParams.validator,
vaultParams.noticePeriod,
vaultParams.managementFee,
vaultParams.merkleOrchard,
vaultParams.description
);
emit GuardianChanged(UNSET_GUARDIAN_ADDRESS, vaultParams.guardian);
}
function initialDeposit(TokenValue[] calldata tokenWithAmount)
external
override
onlyOwner
{
if (initialized) {
revert Aera__VaultIsAlreadyInitialized();
}
initialized = true;
lastFeeCheckpoint = block.timestamp;
IERC20[] memory tokens = getTokens();
uint256 numTokens = tokens.length;
uint256[] memory balances = new uint256[](numTokens);
uint256[] memory amounts = getValuesFromTokenWithValues(
tokenWithAmount,
tokens
);
for (uint256 i = 0; i < numTokens; i++) {
balances[i] = depositToken(tokens[i], amounts[i]);
}
bytes memory initUserData = abi.encode(IBVault.JoinKind.INIT, amounts);
IBVault.JoinPoolRequest memory joinPoolRequest = IBVault
.JoinPoolRequest({
assets: tokens,
maxAmountsIn: balances,
userData: initUserData,
fromInternalBalance: false
});
bVault.joinPool(poolId, address(this), address(this), joinPoolRequest);
setSwapEnabled(true);
}
function deposit(TokenValue[] calldata tokenWithAmount)
external
override
nonReentrant
onlyOwner
whenInitialized
whenNotFinalizing
{
depositTokens(tokenWithAmount);
}
function depositIfBalanceUnchanged(TokenValue[] calldata tokenWithAmount)
external
override
nonReentrant
onlyOwner
whenInitialized
whenNotFinalizing
{
(, , uint256 lastChangeBlock) = getTokensData();
if (lastChangeBlock == block.number) {
revert Aera__BalanceChangedInCurrentBlock();
}
depositTokens(tokenWithAmount);
}
function withdraw(TokenValue[] calldata tokenWithAmount)
external
override
nonReentrant
onlyOwner
whenInitialized
whenNotFinalizing
{
withdrawTokens(tokenWithAmount);
}
function withdrawIfBalanceUnchanged(TokenValue[] calldata tokenWithAmount)
external
override
nonReentrant
onlyOwner
whenInitialized
whenNotFinalizing
{
(, , uint256 lastChangeBlock) = getTokensData();
if (lastChangeBlock == block.number) {
revert Aera__BalanceChangedInCurrentBlock();
}
withdrawTokens(tokenWithAmount);
}
function initiateFinalization()
external
override
nonReentrant
onlyOwner
whenInitialized
whenNotFinalizing
{
lockGuardianFees();
noticeTimeoutAt = block.timestamp + noticePeriod;
setSwapEnabled(false);
emit FinalizationInitiated(noticeTimeoutAt);
}
function finalize()
external
override
nonReentrant
onlyOwner
whenInitialized
{
if (finalized) {
revert Aera__VaultIsAlreadyFinalized();
}
if (noticeTimeoutAt == 0) {
revert Aera__FinalizationNotInitiated();
}
if (noticeTimeoutAt > block.timestamp) {
revert Aera__NoticeTimeoutNotElapsed(noticeTimeoutAt);
}
finalized = true;
uint256[] memory amounts = returnFunds();
emit Finalized(owner(), amounts);
}
function setGuardian(address newGuardian)
external
override
nonReentrant
onlyOwner
{
checkGuardianAddress(newGuardian);
if (initialized && noticeTimeoutAt == 0) {
lockGuardianFees();
}
if (guardiansFee[newGuardian].length == 0) {
guardiansFee[newGuardian] = new uint256[](getTokens().length);
}
emit GuardianChanged(guardian, newGuardian);
guardian = newGuardian;
}
function sweep(address token, uint256 amount)
external
override
onlyOwner
{
if (token == address(pool)) {
revert Aera__CannotSweepPoolToken();
}
IERC20(token).safeTransfer(owner(), amount);
}
function enableTradingRiskingArbitrage()
external
override
onlyOwner
whenInitialized
{
setSwapEnabled(true);
}
function enableTradingWithWeights(TokenValue[] calldata tokenWithWeight)
external
override
onlyOwner
whenInitialized
{
if (pool.getSwapEnabled()) {
revert Aera__PoolSwapIsAlreadyEnabled();
}
IERC20[] memory tokens = getTokens();
uint256[] memory weights = getValuesFromTokenWithValues(
tokenWithWeight,
tokens
);
poolController.updateWeightsGradually(
block.timestamp,
block.timestamp,
weights
);
poolController.setSwapEnabled(true);
emit EnabledTradingWithWeights(block.timestamp, weights);
}
function disableTrading()
external
override
onlyOwnerOrGuardian
whenInitialized
{
setSwapEnabled(false);
}
function claimRewards(
IBMerkleOrchard.Claim[] calldata claims,
IERC20[] calldata tokens
)
external
override
onlyOwner
whenInitialized
{
merkleOrchard.claimDistributions(owner(), claims, tokens);
}
function updateWeightsGradually(
TokenValue[] calldata tokenWithWeight,
uint256 startTime,
uint256 endTime
)
external
override
nonReentrant
onlyGuardian
whenInitialized
whenNotFinalizing
{
if (startTime > type(uint32).max) {
revert Aera__WeightChangeStartTimeIsAboveMax(
startTime,
type(uint32).max
);
}
if (endTime > type(uint32).max) {
revert Aera__WeightChangeEndTimeIsAboveMax(
endTime,
type(uint32).max
);
}
startTime = Math.max(block.timestamp, startTime);
if (startTime > endTime) {
revert Aera__WeightChangeEndBeforeStart();
}
if (startTime + MINIMUM_WEIGHT_CHANGE_DURATION > endTime) {
revert Aera__WeightChangeDurationIsBelowMin(
endTime - startTime,
MINIMUM_WEIGHT_CHANGE_DURATION
);
}
uint256[] memory weights = pool.getNormalizedWeights();
IERC20[] memory tokens = getTokens();
uint256 numTokens = tokens.length;
uint256[] memory targetWeights = getValuesFromTokenWithValues(
tokenWithWeight,
tokens
);
uint256 duration = endTime - startTime;
uint256 maximumRatio = MAX_WEIGHT_CHANGE_RATIO * duration;
for (uint256 i = 0; i < numTokens; i++) {
uint256 changeRatio = getWeightChangeRatio(
weights[i],
targetWeights[i]
);
if (changeRatio > maximumRatio) {
revert Aera__WeightChangeRatioIsAboveMax(
address(tokens[i]),
changeRatio,
maximumRatio
);
}
}
poolController.updateWeightsGradually(
startTime,
endTime,
targetWeights
);
emit UpdateWeightsGradually(startTime, endTime, targetWeights);
}
function cancelWeightUpdates()
external
override
nonReentrant
onlyGuardian
whenInitialized
whenNotFinalizing
{
uint256[] memory weights = pool.getNormalizedWeights();
uint256 numWeights = weights.length;
uint256 weightSum;
for (uint256 i = 0; i < numWeights; i++) {
weightSum += weights[i];
}
updateWeights(weights, weightSum);
emit CancelWeightUpdates(weights);
}
function setSwapFee(uint256 newSwapFee)
external
override
nonReentrant
onlyGuardian
{
if (
block.timestamp < lastSwapFeeCheckpoint + SWAP_FEE_COOLDOWN_PERIOD
) {
revert Aera__CannotSetSwapFeeBeforeCooldown();
}
lastSwapFeeCheckpoint = block.timestamp;
uint256 oldSwapFee = pool.getSwapFeePercentage();
uint256 absoluteDelta = (newSwapFee > oldSwapFee)
? newSwapFee - oldSwapFee
: oldSwapFee - newSwapFee;
if (absoluteDelta > MAXIMUM_SWAP_FEE_PERCENT_CHANGE) {
revert Aera__SwapFeePercentageChangeIsAboveMax(
absoluteDelta,
MAXIMUM_SWAP_FEE_PERCENT_CHANGE
);
}
poolController.setSwapFeePercentage(newSwapFee);
emit SetSwapFee(newSwapFee);
}
function claimGuardianFees()
external
override
nonReentrant
whenInitialized
whenNotFinalizing
{
if (msg.sender == guardian) {
lockGuardianFees();
}
if (guardiansFee[msg.sender].length == 0) {
revert Aera__NoAvailableFeeForCaller(msg.sender);
}
IERC20[] memory tokens;
uint256[] memory holdings;
(tokens, holdings, ) = getTokensData();
uint256 numTokens = tokens.length;
uint256[] memory fees = guardiansFee[msg.sender];
for (uint256 i = 0; i < numTokens; i++) {
guardiansFeeTotal[i] -= fees[i];
guardiansFee[msg.sender][i] = 0;
tokens[i].safeTransfer(msg.sender, fees[i]);
}
if (msg.sender != guardian) {
delete guardiansFee[msg.sender];
}
emit DistributeGuardianFees(msg.sender, fees);
}
function holding(uint256 index) external view override returns (uint256) {
uint256[] memory amounts = getHoldings();
return amounts[index];
}
function getHoldings()
public
view
override
returns (uint256[] memory amounts)
{
(, amounts, ) = getTokensData();
}
function isSwapEnabled()
external
view
override
returns (bool)
{
return pool.getSwapEnabled();
}
function getSwapFee()
external
view
override
returns (uint256)
{
return pool.getSwapFeePercentage();
}
function getTokensData()
public
view
override
returns (
IERC20[] memory,
uint256[] memory,
uint256
)
{
return bVault.getPoolTokens(poolId);
}
function getTokens()
public
view
override
returns (IERC20[] memory tokens)
{
(tokens, , ) = getTokensData();
}
function getNormalizedWeights()
external
view
override
returns (uint256[] memory)
{
return pool.getNormalizedWeights();
}
function renounceOwnership() public override onlyOwner {
revert Aera__VaultIsNotRenounceable();
}
function transferOwnership(address newOwner)
public
override(IProtocolAPI, Ownable)
onlyOwner
{
if (newOwner == address(0)) {
revert Aera__OwnerIsZeroAddress();
}
pendingOwner = newOwner;
emit OwnershipTransferOffered(owner(), newOwner);
}
function cancelOwnershipTransfer() external override onlyOwner {
if (pendingOwner == address(0)) {
revert Aera__NoPendingOwnershipTransfer();
}
emit OwnershipTransferCanceled(owner(), pendingOwner);
pendingOwner = address(0);
}
function acceptOwnership() external override {
if (msg.sender != pendingOwner) {
revert Aera__NotPendingOwner();
}
_transferOwnership(pendingOwner);
pendingOwner = address(0);
}
function depositTokens(TokenValue[] calldata tokenWithAmount) internal {
lockGuardianFees();
IERC20[] memory tokens;
uint256[] memory holdings;
(tokens, holdings, ) = getTokensData();
uint256 numTokens = tokens.length;
uint256[] memory weights = pool.getNormalizedWeights();
uint256[] memory newBalances = new uint256[](numTokens);
uint256[] memory amounts = getValuesFromTokenWithValues(
tokenWithAmount,
tokens
);
for (uint256 i = 0; i < numTokens; i++) {
if (amounts[i] != 0) {
newBalances[i] = depositToken(tokens[i], amounts[i]);
}
}
updatePoolBalance(newBalances, IBVault.PoolBalanceOpKind.UPDATE);
updatePoolBalance(newBalances, IBVault.PoolBalanceOpKind.DEPOSIT);
uint256[] memory newHoldings = getHoldings();
uint256 weightSum;
for (uint256 i = 0; i < numTokens; i++) {
if (amounts[i] != 0) {
weights[i] = (weights[i] * newHoldings[i]) / holdings[i];
newBalances[i] = newHoldings[i] - holdings[i];
}
weightSum += weights[i];
}
updateWeights(weights, weightSum);
emit Deposit(amounts, newBalances, pool.getNormalizedWeights());
}
function withdrawTokens(TokenValue[] calldata tokenWithAmount) internal {
lockGuardianFees();
IERC20[] memory tokens;
uint256[] memory holdings;
(tokens, holdings, ) = getTokensData();
uint256 numTokens = tokens.length;
uint256[] memory allowances = validator.allowance();
uint256[] memory weights = pool.getNormalizedWeights();
uint256[] memory balances = new uint256[](numTokens);
uint256[] memory amounts = getValuesFromTokenWithValues(
tokenWithAmount,
tokens
);
for (uint256 i = 0; i < numTokens; i++) {
if (amounts[i] > holdings[i] || amounts[i] > allowances[i]) {
revert Aera__AmountExceedAvailable(
address(tokens[i]),
amounts[i],
Math.min(holdings[i], allowances[i])
);
}
if (amounts[i] != 0) {
balances[i] = tokens[i].balanceOf(address(this));
}
}
withdrawFromPool(amounts);
uint256 weightSum;
for (uint256 i = 0; i < numTokens; i++) {
if (amounts[i] != 0) {
balances[i] = tokens[i].balanceOf(address(this)) - balances[i];
tokens[i].safeTransfer(owner(), balances[i]);
uint256 newBalance = holdings[i] - amounts[i];
weights[i] = (weights[i] * newBalance) / holdings[i];
}
weightSum += weights[i];
}
updateWeights(weights, weightSum);
emit Withdraw(
amounts,
balances,
allowances,
pool.getNormalizedWeights()
);
}
function withdrawFromPool(uint256[] memory amounts) internal {
uint256[] memory managed = new uint256[](amounts.length);
updatePoolBalance(amounts, IBVault.PoolBalanceOpKind.WITHDRAW);
updatePoolBalance(managed, IBVault.PoolBalanceOpKind.UPDATE);
}
function lockGuardianFees() internal {
if (managementFee == 0) {
return;
}
if (block.timestamp <= lastFeeCheckpoint) {
return;
}
IERC20[] memory tokens;
uint256[] memory holdings;
(tokens, holdings, ) = getTokensData();
uint256 numTokens = tokens.length;
uint256[] memory newFees = new uint256[](numTokens);
uint256[] memory balances = new uint256[](numTokens);
for (uint256 i = 0; i < numTokens; i++) {
balances[i] = tokens[i].balanceOf(address(this));
newFees[i] =
(holdings[i] *
(block.timestamp - lastFeeCheckpoint) *
managementFee) /
ONE;
}
lastFeeCheckpoint = block.timestamp;
withdrawFromPool(newFees);
for (uint256 i = 0; i < numTokens; i++) {
newFees[i] = tokens[i].balanceOf(address(this)) - balances[i];
guardiansFee[guardian][i] += newFees[i];
guardiansFeeTotal[i] += newFees[i];
}
}
function getWeightChangeRatio(uint256 weight, uint256 targetWeight)
internal
pure
returns (uint256)
{
return
weight > targetWeight
? (ONE * weight) / targetWeight
: (ONE * targetWeight) / weight;
}
function getValuesFromTokenWithValues(
TokenValue[] calldata tokenWithValues,
IERC20[] memory tokens
) internal pure returns (uint256[] memory) {
uint256 numTokens = tokens.length;
if (numTokens != tokenWithValues.length) {
revert Aera__ValueLengthIsNotSame(
numTokens,
tokenWithValues.length
);
}
uint256[] memory values = new uint256[](numTokens);
for (uint256 i = 0; i < numTokens; i++) {
if (address(tokenWithValues[i].token) != address(tokens[i])) {
revert Aera__DifferentTokensInPosition(
address(tokenWithValues[i].token),
address(tokens[i]),
i
);
}
values[i] = tokenWithValues[i].value;
}
return values;
}
function updatePoolBalance(
uint256[] memory amounts,
IBVault.PoolBalanceOpKind kind
) internal {
uint256 numAmounts = amounts.length;
IBVault.PoolBalanceOp[] memory ops = new IBVault.PoolBalanceOp[](
numAmounts
);
IERC20[] memory tokens = getTokens();
bytes32 balancerPoolId = poolId;
for (uint256 i = 0; i < numAmounts; i++) {
ops[i].kind = kind;
ops[i].poolId = balancerPoolId;
ops[i].token = tokens[i];
ops[i].amount = amounts[i];
}
bVault.managePoolBalance(ops);
}
function updateWeights(uint256[] memory weights, uint256 weightSum)
internal
{
uint256 numWeights = weights.length;
uint256[] memory newWeights = new uint256[](numWeights);
uint256 adjustedSum;
for (uint256 i = 0; i < numWeights; i++) {
newWeights[i] = (weights[i] * ONE) / weightSum;
adjustedSum += newWeights[i];
}
newWeights[0] = newWeights[0] + ONE - adjustedSum;
poolController.updateWeightsGradually(
block.timestamp,
block.timestamp,
newWeights
);
}
function depositToken(IERC20 token, uint256 amount)
internal
returns (uint256)
{
uint256 balance = token.balanceOf(address(this));
token.safeTransferFrom(owner(), address(this), amount);
balance = token.balanceOf(address(this)) - balance;
uint256 allowance = token.allowance(address(this), address(bVault));
if (allowance > 0) {
token.safeDecreaseAllowance(address(bVault), allowance);
}
token.safeIncreaseAllowance(address(bVault), balance);
return balance;
}
function returnFunds() internal returns (uint256[] memory amounts) {
IERC20[] memory tokens;
uint256[] memory holdings;
(tokens, holdings, ) = getTokensData();
uint256 numTokens = tokens.length;
amounts = new uint256[](numTokens);
withdrawFromPool(holdings);
uint256 amount;
IERC20 token;
for (uint256 i = 0; i < numTokens; i++) {
token = tokens[i];
amount = token.balanceOf(address(this)) - guardiansFeeTotal[i];
token.safeTransfer(owner(), amount);
amounts[i] = amount;
}
}
function setSwapEnabled(bool swapEnabled) internal {
poolController.setSwapEnabled(swapEnabled);
emit SetSwapEnabled(swapEnabled);
}
function checkGuardianAddress(address newGuardian) internal {
if (newGuardian == address(0)) {
revert Aera__GuardianIsZeroAddress();
}
if (newGuardian == owner()) {
revert Aera__GuardianIsOwner(newGuardian);
}
}
}
文件 3 的 21:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 4 的 21:ERC165Checker.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
library ERC165Checker {
bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;
function supportsERC165(address account) internal view returns (bool) {
return
_supportsERC165Interface(account, type(IERC165).interfaceId) &&
!_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
}
function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);
}
function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)
internal
view
returns (bool[] memory)
{
bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);
if (supportsERC165(account)) {
for (uint256 i = 0; i < interfaceIds.length; i++) {
interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);
}
}
return interfaceIdsSupported;
}
function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
if (!supportsERC165(account)) {
return false;
}
for (uint256 i = 0; i < interfaceIds.length; i++) {
if (!_supportsERC165Interface(account, interfaceIds[i])) {
return false;
}
}
return true;
}
function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);
(bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);
if (result.length < 32) return false;
return success && abi.decode(result, (bool));
}
}
文件 5 的 21:IAeraVaultV1.sol
pragma solidity 0.8.11;
import "./IUserAPI.sol";
import "./IGuardianAPI.sol";
import "./IProtocolAPI.sol";
import "./IMultiAssetVault.sol";
interface IAeraVaultV1 is
IUserAPI,
IGuardianAPI,
IProtocolAPI,
IMultiAssetVault
{
struct NewVaultParams {
address factory;
string name;
string symbol;
IERC20[] tokens;
uint256[] weights;
uint256 swapFeePercentage;
address guardian;
address validator;
uint32 noticePeriod;
uint256 managementFee;
address merkleOrchard;
string description;
}
}
文件 6 的 21:IBManagedPool.sol
pragma solidity 0.8.11;
import "../dependencies/openzeppelin/IERC20.sol";
import "./IBVault.sol";
interface IBManagedPool {
function getSwapEnabled() external view returns (bool);
function getSwapFeePercentage() external view returns (uint256);
function getNormalizedWeights() external view returns (uint256[] memory);
function getPoolId() external view returns (bytes32);
function getVault() external view returns (IBVault);
function getOwner() external view returns (address);
}
文件 7 的 21:IBManagedPoolController.sol
pragma solidity 0.8.11;
interface IBManagedPoolController {
function updateWeightsGradually(
uint256 startTime,
uint256 endTime,
uint256[] memory endWeights
) external;
function setSwapEnabled(bool swapEnabled) external;
function setSwapFeePercentage(uint256 swapFeePercentage) external;
}
文件 8 的 21:IBManagedPoolFactory.sol
pragma solidity 0.8.11;
import "../dependencies/openzeppelin/IERC20.sol";
import "./IBVault.sol";
interface IBManagedPoolFactory {
struct NewPoolParams {
IBVault vault;
string name;
string symbol;
IERC20[] tokens;
uint256[] normalizedWeights;
address[] assetManagers;
uint256 swapFeePercentage;
uint256 pauseWindowDuration;
uint256 bufferPeriodDuration;
address owner;
bool swapEnabledOnStart;
bool mustAllowlistLPs;
uint256 managementSwapFeePercentage;
}
struct BasePoolRights {
bool canTransferOwnership;
bool canChangeSwapFee;
bool canUpdateMetadata;
}
struct ManagedPoolRights {
bool canChangeWeights;
bool canDisableSwaps;
bool canSetMustAllowlistLPs;
bool canSetCircuitBreakers;
bool canChangeTokens;
}
function create(
NewPoolParams memory poolParams,
BasePoolRights memory basePoolRights,
ManagedPoolRights memory managedPoolRights,
uint256 minWeightChangeDuration
) external returns (address);
}
文件 9 的 21:IBMerkleOrchard.sol
pragma solidity 0.8.11;
import "../dependencies/openzeppelin/IERC20.sol";
interface IBMerkleOrchard {
struct Claim {
uint256 distributionId;
uint256 balance;
address distributor;
uint256 tokenIndex;
bytes32[] merkleProof;
}
function claimDistributions(
address claimer,
Claim[] memory claims,
IERC20[] memory tokens
) external;
}
文件 10 的 21:IBVault.sol
pragma solidity 0.8.11;
import "../dependencies/openzeppelin/IERC20.sol";
interface IBVault {
enum JoinKind {
INIT,
EXACT_TOKENS_IN_FOR_BPT_OUT,
TOKEN_IN_FOR_EXACT_BPT_OUT,
ALL_TOKENS_IN_FOR_EXACT_BPT_OUT
}
function getPoolTokens(bytes32 poolId)
external
view
returns (
IERC20[] memory tokens,
uint256[] memory balances,
uint256 lastChangeBlock
);
function joinPool(
bytes32 poolId,
address sender,
address recipient,
JoinPoolRequest memory request
) external payable;
struct JoinPoolRequest {
IERC20[] assets;
uint256[] maxAmountsIn;
bytes userData;
bool fromInternalBalance;
}
function exitPool(
bytes32 poolId,
address sender,
address payable recipient,
ExitPoolRequest memory request
) external;
struct ExitPoolRequest {
IERC20[] assets;
uint256[] minAmountsOut;
bytes userData;
bool toInternalBalance;
}
enum PoolBalanceChangeKind {
JOIN,
EXIT
}
enum SwapKind {
GIVEN_IN,
GIVEN_OUT
}
function swap(
SingleSwap memory singleSwap,
FundManagement memory funds,
uint256 limit,
uint256 deadline
) external payable returns (uint256);
struct SingleSwap {
bytes32 poolId;
SwapKind kind;
IERC20 assetIn;
IERC20 assetOut;
uint256 amount;
bytes userData;
}
function batchSwap(
SwapKind kind,
BatchSwapStep[] memory swaps,
IERC20[] memory assets,
FundManagement memory funds,
int256[] memory limits,
uint256 deadline
) external payable returns (int256[] memory);
struct BatchSwapStep {
bytes32 poolId;
uint256 assetInIndex;
uint256 assetOutIndex;
uint256 amount;
bytes userData;
}
struct FundManagement {
address sender;
bool fromInternalBalance;
address payable recipient;
bool toInternalBalance;
}
function managePoolBalance(PoolBalanceOp[] memory ops) external;
struct PoolBalanceOp {
PoolBalanceOpKind kind;
bytes32 poolId;
IERC20 token;
uint256 amount;
}
enum PoolBalanceOpKind {
WITHDRAW,
DEPOSIT,
UPDATE
}
function setPaused(bool paused) external;
}
文件 11 的 21:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 12 的 21:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
文件 13 的 21:IGuardianAPI.sol
pragma solidity 0.8.11;
import "../dependencies/openzeppelin/IERC20.sol";
import "./IProtocolAPI.sol";
interface IGuardianAPI {
function updateWeightsGradually(
IProtocolAPI.TokenValue[] memory tokenWithWeight,
uint256 startTime,
uint256 endTime
) external;
function cancelWeightUpdates() external;
function setSwapFee(uint256 newSwapFee) external;
function claimGuardianFees() external;
}
文件 14 的 21:IMultiAssetVault.sol
pragma solidity 0.8.11;
interface IMultiAssetVault {
function holding(uint256 index) external view returns (uint256);
function getHoldings() external view returns (uint256[] memory);
}
文件 15 的 21:IProtocolAPI.sol
pragma solidity 0.8.11;
import "./IBMerkleOrchard.sol";
interface IProtocolAPI {
struct TokenValue {
IERC20 token;
uint256 value;
}
function initialDeposit(TokenValue[] memory tokenWithAmount) external;
function deposit(TokenValue[] memory tokenWithAmount) external;
function depositIfBalanceUnchanged(TokenValue[] memory tokenWithAmount)
external;
function withdraw(TokenValue[] memory tokenWithAmount) external;
function withdrawIfBalanceUnchanged(TokenValue[] memory tokenWithAmount)
external;
function initiateFinalization() external;
function finalize() external;
function setGuardian(address newGuardian) external;
function sweep(address token, uint256 amount) external;
function enableTradingRiskingArbitrage() external;
function enableTradingWithWeights(TokenValue[] memory tokenWithWeight)
external;
function disableTrading() external;
function claimRewards(
IBMerkleOrchard.Claim[] memory claims,
IERC20[] memory tokens
) external;
function transferOwnership(address newOwner) external;
function cancelOwnershipTransfer() external;
}
文件 16 的 21:IUserAPI.sol
pragma solidity 0.8.11;
import "../dependencies/openzeppelin/IERC20.sol";
interface IUserAPI {
function isSwapEnabled() external view returns (bool);
function getSwapFee() external view returns (uint256);
function poolId() external view returns (bytes32);
function getTokensData()
external
view
returns (
IERC20[] memory tokens,
uint256[] memory balances,
uint256 lastChangeBlock
);
function getTokens() external view returns (IERC20[] memory);
function getNormalizedWeights() external view returns (uint256[] memory);
function acceptOwnership() external;
}
文件 17 的 21:IWithdrawalValidator.sol
pragma solidity 0.8.11;
interface IWithdrawalValidator {
function allowance() external returns (uint256[] memory);
}
文件 18 的 21:Math.sol
pragma solidity ^0.8.0;
library Math {
enum Rounding {
Down,
Up,
Zero
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
require(denominator > prod1);
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}
文件 19 的 21:Ownable.sol
pragma solidity ^0.8.0;
import "./Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 20 的 21:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 21 的 21:SafeERC20.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
{
"compilationTarget": {
"lib/aera-contracts/contracts/v1/AeraVaultV1.sol": "AeraVaultV1"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":aera-contracts/=lib/aera-contracts/contracts/",
":chainlink/=lib/chainlink/",
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/",
":v3-core/=lib/v3-core/",
":v3-periphery-foundry/=lib/v3-periphery-foundry/contracts/"
]
}
[{"inputs":[{"components":[{"internalType":"address","name":"factory","type":"address"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"weights","type":"uint256[]"},{"internalType":"uint256","name":"swapFeePercentage","type":"uint256"},{"internalType":"address","name":"guardian","type":"address"},{"internalType":"address","name":"validator","type":"address"},{"internalType":"uint32","name":"noticePeriod","type":"uint32"},{"internalType":"uint256","name":"managementFee","type":"uint256"},{"internalType":"address","name":"merkleOrchard","type":"address"},{"internalType":"string","name":"description","type":"string"}],"internalType":"struct IAeraVaultV1.NewVaultParams","name":"vaultParams","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"available","type":"uint256"}],"name":"Aera__AmountExceedAvailable","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"min","type":"uint256"}],"name":"Aera__AmountIsBelowMin","type":"error"},{"inputs":[],"name":"Aera__BalanceChangedInCurrentBlock","type":"error"},{"inputs":[],"name":"Aera__CallerIsNotGuardian","type":"error"},{"inputs":[],"name":"Aera__CallerIsNotOwnerOrGuardian","type":"error"},{"inputs":[],"name":"Aera__CannotSetSwapFeeBeforeCooldown","type":"error"},{"inputs":[],"name":"Aera__CannotSweepPoolToken","type":"error"},{"inputs":[],"name":"Aera__DescriptionIsEmpty","type":"error"},{"inputs":[{"internalType":"address","name":"actual","type":"address"},{"internalType":"address","name":"sortedToken","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"Aera__DifferentTokensInPosition","type":"error"},{"inputs":[],"name":"Aera__FinalizationNotInitiated","type":"error"},{"inputs":[{"internalType":"address","name":"newGuardian","type":"address"}],"name":"Aera__GuardianIsOwner","type":"error"},{"inputs":[],"name":"Aera__GuardianIsZeroAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"Aera__ManagementFeeIsAboveMax","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"Aera__NoAvailableFeeForCaller","type":"error"},{"inputs":[],"name":"Aera__NoPendingOwnershipTransfer","type":"error"},{"inputs":[],"name":"Aera__NotPendingOwner","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"Aera__NoticePeriodIsAboveMax","type":"error"},{"inputs":[{"internalType":"uint256","name":"noticeTimeoutAt","type":"uint256"}],"name":"Aera__NoticeTimeoutNotElapsed","type":"error"},{"inputs":[],"name":"Aera__OwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"Aera__PoolSwapIsAlreadyEnabled","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"Aera__SwapFeePercentageChangeIsAboveMax","type":"error"},{"inputs":[{"internalType":"uint256","name":"numTokens","type":"uint256"},{"internalType":"uint256","name":"numAllowances","type":"uint256"}],"name":"Aera__ValidatorIsNotMatched","type":"error"},{"inputs":[{"internalType":"address","name":"validator","type":"address"}],"name":"Aera__ValidatorIsNotValid","type":"error"},{"inputs":[{"internalType":"uint256","name":"numTokens","type":"uint256"},{"internalType":"uint256","name":"numValues","type":"uint256"}],"name":"Aera__ValueLengthIsNotSame","type":"error"},{"inputs":[],"name":"Aera__VaultIsAlreadyFinalized","type":"error"},{"inputs":[],"name":"Aera__VaultIsAlreadyInitialized","type":"error"},{"inputs":[],"name":"Aera__VaultIsFinalizing","type":"error"},{"inputs":[],"name":"Aera__VaultIsNotRenounceable","type":"error"},{"inputs":[],"name":"Aera__VaultNotInitialized","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"min","type":"uint256"}],"name":"Aera__WeightChangeDurationIsBelowMin","type":"error"},{"inputs":[],"name":"Aera__WeightChangeEndBeforeStart","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"Aera__WeightChangeEndTimeIsAboveMax","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"Aera__WeightChangeRatioIsAboveMax","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"Aera__WeightChangeStartTimeIsAboveMax","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"Aera__WeightIsAboveMax","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"min","type":"uint256"}],"name":"Aera__WeightIsBelowMin","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"weights","type":"uint256[]"}],"name":"CancelWeightUpdates","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"factory","type":"address"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"symbol","type":"string"},{"indexed":false,"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"weights","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"swapFeePercentage","type":"uint256"},{"indexed":true,"internalType":"address","name":"guardian","type":"address"},{"indexed":true,"internalType":"address","name":"validator","type":"address"},{"indexed":false,"internalType":"uint256","name":"noticePeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"managementFee","type":"uint256"},{"indexed":false,"internalType":"address","name":"merkleOrchard","type":"address"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"Created","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"requestedAmounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"weights","type":"uint256[]"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"guardian","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"DistributeGuardianFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"weights","type":"uint256[]"}],"name":"EnabledTradingWithWeights","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"noticeTimeoutAt","type":"uint256"}],"name":"FinalizationInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"Finalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousGuardian","type":"address"},{"indexed":true,"internalType":"address","name":"guardian","type":"address"}],"name":"GuardianChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"currentOwner","type":"address"},{"indexed":true,"internalType":"address","name":"canceledOwner","type":"address"}],"name":"OwnershipTransferCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"currentOwner","type":"address"},{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipTransferOffered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"swapEnabled","type":"bool"}],"name":"SetSwapEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"SetSwapFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"weights","type":"uint256[]"}],"name":"UpdateWeightsGradually","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"requestedAmounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"allowances","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"weights","type":"uint256[]"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bVault","outputs":[{"internalType":"contract IBVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelWeightUpdates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimGuardianFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"distributionId","type":"uint256"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"address","name":"distributor","type":"address"},{"internalType":"uint256","name":"tokenIndex","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"internalType":"struct IBMerkleOrchard.Claim[]","name":"claims","type":"tuple[]"},{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IProtocolAPI.TokenValue[]","name":"tokenWithAmount","type":"tuple[]"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IProtocolAPI.TokenValue[]","name":"tokenWithAmount","type":"tuple[]"}],"name":"depositIfBalanceUnchanged","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"description","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disableTrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableTradingRiskingArbitrage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IProtocolAPI.TokenValue[]","name":"tokenWithWeight","type":"tuple[]"}],"name":"enableTradingWithWeights","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finalize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finalized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHoldings","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNormalizedWeights","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSwapFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokens","outputs":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokensData","outputs":[{"internalType":"contract IERC20[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"guardiansFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"guardiansFeeTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"holding","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IProtocolAPI.TokenValue[]","name":"tokenWithAmount","type":"tuple[]"}],"name":"initialDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initiateFinalization","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isSwapEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastFeeCheckpoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastSwapFeeCheckpoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"managementFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleOrchard","outputs":[{"internalType":"contract IBMerkleOrchard","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"noticePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"noticeTimeoutAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"contract IBManagedPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolController","outputs":[{"internalType":"contract IBManagedPoolController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newGuardian","type":"address"}],"name":"setGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newSwapFee","type":"uint256"}],"name":"setSwapFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IProtocolAPI.TokenValue[]","name":"tokenWithWeight","type":"tuple[]"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"updateWeightsGradually","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"validator","outputs":[{"internalType":"contract IWithdrawalValidator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IProtocolAPI.TokenValue[]","name":"tokenWithAmount","type":"tuple[]"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct IProtocolAPI.TokenValue[]","name":"tokenWithAmount","type":"tuple[]"}],"name":"withdrawIfBalanceUnchanged","outputs":[],"stateMutability":"nonpayable","type":"function"}]