// 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.8.17;

import '@openzeppelin/contracts/utils/structs/EnumerableSet.sol';

import '@mimic-fi/v2-helpers/contracts/math/FixedPoint.sol';

import './BaseAction.sol';
import './interfaces/IRelayedAction.sol';

/**
 * @dev Relayers config for actions. It allows redeeming consumed gas based on an allow-list of relayers and cost limit.
 */
abstract contract RelayedAction is IRelayedAction, BaseAction {
    using FixedPoint for uint256;
    using EnumerableSet for EnumerableSet.AddressSet;

    // Base gas amount charged to cover default amounts
    // solhint-disable-next-line func-name-mixedcase
    function BASE_GAS() external view virtual returns (uint256);

    // Note to be used to mark tx cost payments
    bytes private constant REDEEM_GAS_NOTE = bytes('RELAYER');

    // Variable used to allow a better developer experience to reimburse tx gas cost
    // solhint-disable-next-line var-name-mixedcase
    uint256 private __initialGas__;

    // Gas price limit expressed in the native token
    uint256 private _gasPriceLimit;

    // Priority fee limit expressed in the native token
    uint256 private _priorityFeeLimit;

    // Total transaction cost limit expressed in the native token
    uint256 private _txCostLimit;

    // Token that will be used to redeem gas costs
    address private _gasToken;

    // Allows relaying transactions even if there is not enough balance in the Smart Vault to pay for the tx gas cost
    bool private _permissiveMode;

    // List of allowed relayers
    EnumerableSet.AddressSet private _relayers;

    /**
     * @dev Relayed action config. Only used in the constructor.
     * @param gasPriceLimit Gas price limit expressed in the native token
     * @param priorityFeeLimit Priority fee limit expressed in the native token
     * @param txCostLimit Transaction cost limit to be set
     * @param gasToken Token that will be used to redeem gas costs
     * @param permissiveMode Whether the permissive mode is active
     * @param relayers List of relayers to be added to the allow-list
     */
    struct RelayConfig {
        uint256 gasPriceLimit;
        uint256 priorityFeeLimit;
        uint256 txCostLimit;
        address gasToken;
        bool permissiveMode;
        address[] relayers;
    }

    /**
     * @dev Creates a new relayers config
     */
    constructor(RelayConfig memory config) {
        _setRelayGasLimit(config.gasPriceLimit, config.priorityFeeLimit);
        _setRelayTxCostLimit(config.txCostLimit);
        _setRelayGasToken(config.gasToken);
        _setRelayPermissiveMode(config.permissiveMode);
        _addRelayers(config.relayers);
    }

    /**
     * @dev Tells the action gas limits
     */
    function getRelayGasLimits() public view override returns (uint256 gasPriceLimit, uint256 priorityFeeLimit) {
        return (_gasPriceLimit, _priorityFeeLimit);
    }

    /**
     * @dev Tells the transaction cost limit
     */
    function getRelayTxCostLimit() public view override returns (uint256) {
        return _txCostLimit;
    }

    /**
     * @dev Tells the relayed paying gas token
     */
    function getRelayGasToken() public view override returns (address) {
        return _gasToken;
    }

    /**
     * @dev Tells whether the permissive relayed mode is active
     */
    function isRelayPermissiveModeActive() public view override returns (bool) {
        return _permissiveMode;
    }

    /**
     * @dev Tells if a relayer is allowed or not
     * @param relayer Address of the relayer to be checked
     */
    function isRelayer(address relayer) public view override returns (bool) {
        return _relayers.contains(relayer);
    }

    /**
     * @dev Tells the list of allowed relayers
     */
    function getRelayers() public view override returns (address[] memory) {
        return _relayers.values();
    }

    /**
     * @dev Sets the relay gas limits
     * @param gasPriceLimit New relay gas price limit to be set
     * @param priorityFeeLimit New relay priority fee limit to be set
     */
    function setRelayGasLimits(uint256 gasPriceLimit, uint256 priorityFeeLimit) external override auth {
        _setRelayGasLimit(gasPriceLimit, priorityFeeLimit);
    }

    /**
     * @dev Sets the relay transaction cost limit
     * @param txCostLimit New relay transaction cost limit to be set
     */
    function setRelayTxCostLimit(uint256 txCostLimit) external override auth {
        _setRelayTxCostLimit(txCostLimit);
    }

    /**
     * @dev Sets the relay gas token
     * @param token Address of the token to be set as the relay gas token
     */
    function setRelayGasToken(address token) external override auth {
        _setRelayGasToken(token);
    }

    /**
     * @dev Sets the relay permissive mode
     * @param active Whether the relay permissive mode should be active or not
     */
    function setRelayPermissiveMode(bool active) external override auth {
        _setRelayPermissiveMode(active);
    }

    /**
     * @dev Updates the list of allowed relayers
     * @param relayersToAdd List of relayers to be added to the allow-list
     * @param relayersToRemove List of relayers to be removed from the allow-list
     * @notice The list of relayers to be added will be processed first to make sure no undesired relayers are allowed
     */
    function setRelayers(address[] memory relayersToAdd, address[] memory relayersToRemove) external override auth {
        _addRelayers(relayersToAdd);
        _removeRelayers(relayersToRemove);
    }

    /**
     * @dev Reverts if the tx fee does not comply with the configured gas limits
     */
    function _validateGasLimit() internal view {
        require(_areGasLimitsValid(), 'ACTION_GAS_LIMITS_EXCEEDED');
    }

    /**
     * @dev Tells if the tx fee data is compliant with the configured gas limits
     */
    function _areGasLimitsValid() internal view returns (bool) {
        return _isGasPriceValid() && _isPriorityFeeValid();
    }

    /**
     * @dev Tells if the tx gas price is compliant with the configured gas price limit
     */
    function _isGasPriceValid() internal view returns (bool) {
        if (_gasPriceLimit == 0) return true;
        return tx.gasprice <= _gasPriceLimit;
    }

    /**
     * @dev Tells if the tx priority fee is compliant with the configured priority fee limit
     */
    function _isPriorityFeeValid() internal view returns (bool) {
        if (_priorityFeeLimit == 0) return true;
        return tx.gasprice - block.basefee <= _priorityFeeLimit;
    }

    /**
     * @dev Reverts if the tx cost does not comply with the configured limit
     */
    function _validateTxCostLimit(uint256 totalCost) internal view {
        require(_isTxCostValid(totalCost), 'ACTION_TX_COST_LIMIT_EXCEEDED');
    }

    /**
     * @dev Tells if a given transaction cost is compliant with the configured transaction cost limit
     * @param totalCost Transaction cost in native token to be checked
     */
    function _isTxCostValid(uint256 totalCost) internal view returns (bool) {
        return _txCostLimit == 0 || totalCost <= _txCostLimit;
    }

    /**
     * @dev Initializes relayed txs, only when the sender is marked as a relayer
     */
    function _beforeAction(address, uint256) internal virtual override {
        if (!isRelayer(msg.sender)) return;
        __initialGas__ = gasleft();
        _validateGasLimit();
    }

    /**
     * @dev Reimburses the tx cost, only when the sender is marked as a relayer
     */
    function _afterAction(address, uint256) internal virtual override {
        if (!isRelayer(msg.sender)) return;
        require(__initialGas__ > 0, 'ACTION_RELAY_NOT_INITIALIZED');

        uint256 totalGas = RelayedAction(this).BASE_GAS() + __initialGas__ - gasleft();
        uint256 totalCostNative = totalGas * tx.gasprice;
        _validateTxCostLimit(totalCostNative);

        uint256 price = _isWrappedOrNative(_gasToken) ? FixedPoint.ONE : _getPrice(_wrappedNativeToken(), _gasToken);
        uint256 totalCostGasToken = totalCostNative.mulDown(price);
        if (getSmartVaultBalance(_gasToken) >= totalCostGasToken || !_permissiveMode) {
            smartVault.withdraw(_gasToken, totalCostGasToken, smartVault.feeCollector(), REDEEM_GAS_NOTE);
        }

        delete __initialGas__;
    }

    /**
     * @dev Sets the relay gas limits
     * @param gasPriceLimit New relay gas price limit to be set
     * @param priorityFeeLimit New relay priority fee limit to be set
     */
    function _setRelayGasLimit(uint256 gasPriceLimit, uint256 priorityFeeLimit) internal {
        _gasPriceLimit = gasPriceLimit;
        _priorityFeeLimit = priorityFeeLimit;
        emit RelayGasLimitsSet(gasPriceLimit, priorityFeeLimit);
    }

    /**
     * @dev Sets the relay transaction cost limit
     * @param txCostLimit New relay transaction cost limit to be set
     */
    function _setRelayTxCostLimit(uint256 txCostLimit) internal {
        _txCostLimit = txCostLimit;
        emit RelayTxCostLimitSet(txCostLimit);
    }

    /**
     * @dev Sets the relay gas token
     * @param token Address of the token to be set as the relay gas token
     */
    function _setRelayGasToken(address token) internal {
        _gasToken = token;
        emit RelayGasTokenSet(token);
    }

    /**
     * @dev Sets the relay permissive mode
     * @param active Whether the relay permissive mode should be active or not
     */
    function _setRelayPermissiveMode(bool active) internal {
        _permissiveMode = active;
        emit RelayPermissiveModeSet(active);
    }

    /**
     * @dev Adds a list of addresses to the relayers allow-list
     * @param relayers List of addresses to be added to the allow-list
     */
    function _addRelayers(address[] memory relayers) internal {
        for (uint256 i = 0; i < relayers.length; i++) {
            address relayer = relayers[i];
            require(relayer != address(0), 'RELAYER_ADDRESS_ZERO');
            if (_relayers.add(relayer)) emit RelayerAllowed(relayer);
        }
    }

    /**
     * @dev Removes a list of addresses from the relayers allow-list
     * @param relayers List of addresses to be removed from the allow-list
     */
    function _removeRelayers(address[] memory relayers) internal {
        for (uint256 i = 0; i < relayers.length; i++) {
            address relayer = relayers[i];
            if (_relayers.remove(relayer)) emit RelayerDisallowed(relayer);
        }
    }
}
[{"inputs":[{"components":[{"internalType":"address","name":"recipient","type":"address"},{"components":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"smartVault","type":"address"},{"internalType":"uint8","name":"groupId","type":"uint8"}],"internalType":"struct BaseAction.BaseConfig","name":"baseConfig","type":"tuple"},{"components":[{"internalType":"uint256","name":"gasPriceLimit","type":"uint256"},{"internalType":"uint256","name":"priorityFeeLimit","type":"uint256"},{"internalType":"uint256","name":"txCostLimit","type":"uint256"},{"internalType":"address","name":"gasToken","type":"address"},{"internalType":"bool","name":"permissiveMode","type":"bool"},{"internalType":"address[]","name":"relayers","type":"address[]"}],"internalType":"struct RelayedAction.RelayConfig","name":"relayConfig","type":"tuple"},{"components":[{"internalType":"address[]","name":"signers","type":"address[]"}],"internalType":"struct OracledAction.OracleConfig","name":"oracleConfig","type":"tuple"},{"components":[{"internalType":"uint256","name":"delay","type":"uint256"},{"internalType":"uint256","name":"nextExecutionTimestamp","type":"uint256"}],"internalType":"struct TimeLockedAction.TimeLockConfig","name":"timeLockConfig","type":"tuple"},{"components":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"address[]","name":"sources","type":"address[]"},{"internalType":"enum ITokenIndexedAction.TokensAcceptanceType","name":"acceptanceType","type":"uint8"}],"internalType":"struct TokenIndexedAction.TokenIndexConfig","name":"tokenIndexConfig","type":"tuple"},{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"min","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"internalType":"struct ITokenThresholdAction.Threshold","name":"defaultThreshold","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"min","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"internalType":"struct ITokenThresholdAction.Threshold","name":"threshold","type":"tuple"}],"internalType":"struct TokenThresholdAction.CustomThreshold[]","name":"customThresholds","type":"tuple[]"}],"internalType":"struct TokenThresholdAction.TokenThresholdConfig","name":"tokenThresholdConfig","type":"tuple"}],"internalType":"struct Action.ActionConfig","name":"actionConfig","type":"tuple"}],"internalType":"struct Withdrawer.WithdrawerConfig","name":"config","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"who","type":"address"},{"indexed":false,"internalType":"bytes4","name":"what","type":"bytes4"}],"name":"Authorized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"min","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"indexed":false,"internalType":"struct ITokenThresholdAction.Threshold","name":"threshold","type":"tuple"}],"name":"CustomTokenThresholdSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"CustomTokenThresholdUnset","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"min","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"indexed":false,"internalType":"struct ITokenThresholdAction.Threshold","name":"threshold","type":"tuple"}],"name":"DefaultTokenThresholdSet","type":"event"},{"anonymous":false,"inputs":[],"name":"DefaultTokenThresholdUnset","type":"event"},{"anonymous":false,"inputs":[],"name":"Executed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"groupId","type":"uint8"}],"name":"GroupIdSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"signer","type":"address"}],"name":"OracleSignerAllowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"signer","type":"address"}],"name":"OracleSignerDisallowed","type":"event"},{"anonymous":false,"inputs":[],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"RecipientSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"gasPriceLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priorityFeeLimit","type":"uint256"}],"name":"RelayGasLimitsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"RelayGasTokenSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"active","type":"bool"}],"name":"RelayPermissiveModeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"txCostLimit","type":"uint256"}],"name":"RelayTxCostLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerAllowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerDisallowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"delay","type":"uint256"}],"name":"TimeLockDelaySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"expiration","type":"uint256"}],"name":"TimeLockExpirationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"source","type":"address"}],"name":"TokenIndexSourceAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"source","type":"address"}],"name":"TokenIndexSourceRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"TokensAcceptanceAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"TokensAcceptanceRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum ITokenIndexedAction.TokensAcceptanceType","name":"acceptanceType","type":"uint8"}],"name":"TokensAcceptanceTypeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"who","type":"address"},{"indexed":false,"internalType":"bytes4","name":"what","type":"bytes4"}],"name":"Unauthorized","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpaused","type":"event"},{"inputs":[],"name":"ANY_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BASE_GAS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"},{"internalType":"bytes4","name":"what","type":"bytes4"}],"name":"authorize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"call","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getActionBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getCustomTokenThreshold","outputs":[{"internalType":"bool","name":"exists","type":"bool"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"min","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"internalType":"struct ITokenThresholdAction.Threshold","name":"threshold","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCustomTokenThresholds","outputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"min","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"internalType":"struct ITokenThresholdAction.Threshold[]","name":"thresholds","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDefaultTokenThreshold","outputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"min","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"internalType":"struct ITokenThresholdAction.Threshold","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"base","type":"address"},{"internalType":"address","name":"quote","type":"address"},{"internalType":"uint256","name":"rate","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct IOracledAction.FeedData[]","name":"feeds","type":"tuple[]"}],"name":"getFeedsDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getGroupId","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOracleSigners","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRelayGasLimits","outputs":[{"internalType":"uint256","name":"gasPriceLimit","type":"uint256"},{"internalType":"uint256","name":"priorityFeeLimit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRelayGasToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRelayTxCostLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRelayers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getSmartVaultBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTimeLock","outputs":[{"internalType":"uint256","name":"delay","type":"uint256"},{"internalType":"uint256","name":"expiresAt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokensAcceptanceList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokensAcceptanceType","outputs":[{"internalType":"enum ITokenIndexedAction.TokensAcceptanceType","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokensIndexSources","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getTotalBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"},{"internalType":"bytes4","name":"what","type":"bytes4"}],"name":"isAuthorized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isOracleSigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRelayPermissiveModeActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"relayer","type":"address"}],"name":"isRelayer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isTimeLockExpired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"isTokenAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"min","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"internalType":"struct ITokenThresholdAction.Threshold[]","name":"thresholds","type":"tuple[]"}],"name":"setCustomTokenThresholds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"min","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"internalType":"struct ITokenThresholdAction.Threshold","name":"threshold","type":"tuple"}],"name":"setDefaultTokenThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"groupId","type":"uint8"}],"name":"setGroupId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"toAdd","type":"address[]"},{"internalType":"address[]","name":"toRemove","type":"address[]"}],"name":"setOracleSigners","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"setRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"gasPriceLimit","type":"uint256"},{"internalType":"uint256","name":"priorityFeeLimit","type":"uint256"}],"name":"setRelayGasLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"setRelayGasToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"active","type":"bool"}],"name":"setRelayPermissiveMode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"txCostLimit","type":"uint256"}],"name":"setRelayTxCostLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"relayersToAdd","type":"address[]"},{"internalType":"address[]","name":"relayersToRemove","type":"address[]"}],"name":"setRelayers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"delay","type":"uint256"}],"name":"setTimeLockDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"setTimeLockExpiration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"toAdd","type":"address[]"},{"internalType":"address[]","name":"toRemove","type":"address[]"}],"name":"setTokensAcceptanceList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum ITokenIndexedAction.TokensAcceptanceType","name":"acceptanceType","type":"uint8"}],"name":"setTokensAcceptanceType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"toAdd","type":"address[]"},{"internalType":"address[]","name":"toRemove","type":"address[]"}],"name":"setTokensIndexSources","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"smartVault","outputs":[{"internalType":"contract ISmartVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferToSmartVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"who","type":"address"},{"internalType":"bytes4","name":"what","type":"bytes4"}],"name":"unauthorize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"unsetCustomTokenThresholds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unsetDefaultTokenThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]