// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;
import {IBatchMigrator} from "./interface/IBatchMigrator.sol";
import {IZtakingPool} from "./interface/IZtakingPool.sol";
import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
/// @title Batch Migrator
/// @notice A contract to migrate multiple users from the staking contract in a single transaction.
/// @dev To call the migrateWithSig from the ztakingPool Contract this batch migrator must assume ownership of ztaking pool. Due to that the functions that implement onlyOwner on ztakingPool have been integrated into the Batch Migrator.
contract BatchMigrator is IBatchMigrator, Ownable2Step {
address public immutable ztakingPool;
address public immutable migrator;
uint256 public signatureExpiry;
constructor(
address _ztakingPool,
address _migrator,
uint256 _signatureExpiry
) Ownable(msg.sender) {
if (_ztakingPool == address(0)) revert ZtakingPoolCannotBeZeroAddress();
if (_migrator == address(0)) revert MigratorCannotBeZeroAddress();
if (_signatureExpiry == 0) revert SignatureExpiryCannotBeZero();
ztakingPool = _ztakingPool;
migrator = _migrator;
signatureExpiry = _signatureExpiry;
}
/**
* @inheritdoc IBatchMigrator
*/
function batchMigrate(
address[] calldata _users,
address[][] calldata _tokens,
address[] calldata _destinations,
bytes[] calldata _signatures
) external onlyOwner {
uint256 numUsers = _users.length;
uint256 _signatureExpiry = signatureExpiry;
for (uint256 i = 0; i < numUsers; ++i) {
IZtakingPool(ztakingPool).migrateWithSig(
_users[i],
_tokens[i],
migrator,
_destinations[i],
_signatureExpiry,
_signatures[i]
);
}
}
/**
* @inheritdoc IBatchMigrator
*/
function batchMigrateWithDestinationEqualToUser(
address[] calldata _usersDestinations,
address[][] calldata _tokens,
bytes[] calldata _signatures
) external onlyOwner {
uint256 numUsers = _usersDestinations.length;
uint256 _signatureExpiry = signatureExpiry;
for (uint256 i = 0; i < numUsers; ++i) {
IZtakingPool(ztakingPool).migrateWithSig(
_usersDestinations[i],
_tokens[i],
migrator,
_usersDestinations[i],
_signatureExpiry,
_signatures[i]
);
}
}
/**
* @inheritdoc IBatchMigrator
*/
function setSignatureExpiry(uint256 _signatureExpiry) external onlyOwner {
if (_signatureExpiry == 0) revert SignatureExpiryCannotBeZero();
signatureExpiry = _signatureExpiry;
}
/**
* @inheritdoc IBatchMigrator
*/
function acceptZtakingPoolOwnershipTransfer() external onlyOwner {
Ownable2Step(ztakingPool).acceptOwnership();
}
/**
* @inheritdoc IBatchMigrator
*/
function transferZtakingPoolOwnership(
address _newOwner
) external onlyOwner {
Ownable2Step(ztakingPool).transferOwnership(_newOwner);
}
/**
* @inheritdoc IBatchMigrator
*/
function ztakingPoolSetZircuitSigner(address _signer) external onlyOwner {
IZtakingPool(ztakingPool).setZircuitSigner(_signer);
}
/**
* @inheritdoc IBatchMigrator
*/
function ztakingPoolSetStakable(
address _token,
bool _canStake
) external onlyOwner {
IZtakingPool(ztakingPool).setStakable(_token, _canStake);
}
/**
* @inheritdoc IBatchMigrator
*/
function ztakingPoolBlockMigrator(
address _migrator,
bool _blocklisted
) external onlyOwner {
IZtakingPool(ztakingPool).blockMigrator(
_migrator,
_blocklisted
);
}
/**
* @inheritdoc IBatchMigrator
*/
function ztakingPoolPause() external onlyOwner {
IZtakingPool(ztakingPool).pause();
}
/**
* @inheritdoc IBatchMigrator
*/
function ztakingPoolUnpause() external onlyOwner {
IZtakingPool(ztakingPool).unpause();
}
function renounceOwnership() public override {
revert CannotRenounceOwnership();
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;
///@title Batch Migrator Interface
///@notice An interface containing externally accessible functions of the BatchMigrator contract
interface IBatchMigrator {
/*//////////////////////////////////////////////////////////////
Errors
//////////////////////////////////////////////////////////////*/
error ZtakingPoolCannotBeZeroAddress();
error MigratorCannotBeZeroAddress();
error SignatureExpiryCannotBeZero();
error CannotRenounceOwnership();
/*//////////////////////////////////////////////////////////////
Functions
//////////////////////////////////////////////////////////////*/
///@notice Migrate the staked tokens for the users from the Ztaking Pool to Zircuit Multisig
///@param _users The stakers to migrate tokens for
///@param _tokens Each user token being migrated to Zircuit from the Ztaking Pool
///@param _destinations The addresses which will be credited the tokens on Zircuit
///@param _signatures The signatures from the stakers authorizing the migration of their tokens
///@dev Only callable by the owner
function batchMigrate(
address[] calldata _users,
address[][] calldata _tokens,
address[] calldata _destinations,
bytes[] calldata _signatures
) external;
///@notice Migrate the staked tokens for the users from the Ztaking Pool to Zircuit Multisig, this function is used for when the destination address is the same as user address
///@param _usersDestinations The stakers to migrate tokens for, which are equal to the L2 receiving address
///@param _tokens Each user token being migrated to Zircuit from the Ztaking Pool
///@param _signatures The signatures from the stakers authorizing the migration of their tokens
///@dev Only callable by the owner
function batchMigrateWithDestinationEqualToUser(
address[] calldata _usersDestinations,
address[][] calldata _tokens,
bytes[] calldata _signatures
) external;
///@notice Update the signature expiry for signatures produced by users for token migration.
///@param _signatureExpiry New default signature expiry time for users migration signatures
///@dev Only callable by the owner
function setSignatureExpiry(uint256 _signatureExpiry) external;
///@notice Accept ownership transfer of the staking contract
///@dev Only callable by the owner
function acceptZtakingPoolOwnershipTransfer() external;
///@notice Transfer ownership of the staking contract
///@param newOwner New owner of the staking contract
///@dev Only callable by the owner
function transferZtakingPoolOwnership(address newOwner) external;
///@notice Call setZircuitSigner on staking contract
///@param _signer The address of the new signer for the migration signature
///@dev Only callable by the owner
function ztakingPoolSetZircuitSigner(address _signer) external;
///@notice Call setStakable on staking contract
///@param _token The token to enable or disable for staking
///@param _canStake If true, then staking is to be enabled. If false, then staking will be disabled.
///@dev Only callable by the owner
function ztakingPoolSetStakable(address _token, bool _canStake) external;
///@notice Call blockMigrator on staking contract
///@param _migrator The migrator contract to add or remove from the blocklist
///@param _blocklisted If true, then add the migrator to the blocklist. If false, then remove the migrator from the blocklist.
///@dev Only callable by the owner
function ztakingPoolBlockMigrator(
address _migrator,
bool _blocklisted
) external;
///@notice Call pause on staking contract
///@dev Only callable by the owner
function ztakingPoolPause() external;
///@notice Call unpause on staking contract
///@dev Only callable by the owner
function ztakingPoolUnpause() external;
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;
/// @title Ztaking Pool Interface
/// @notice An interface containing externally accessible functions of the ZtakingPool contract
/// @dev The automatically generated public view functions for the state variables and mappings are not included in the interface
interface IZtakingPool {
/*//////////////////////////////////////////////////////////////
Errors
//////////////////////////////////////////////////////////////*/
error SignerCannotBeZeroAddress(); //Thrown when proposed signer is the zero address
error SignerAlreadySetToAddress(); //Thrown when proposed signer is already set
error SignatureInvalid(); // Thrown when the migration signature is invalid
error SignatureExpired(); // Thrown when the migration signature has expired
error TokenCannotBeZeroAddress(); // Thrown when the specified token is the zero address
error WETHCannotBeZeroAddress(); // Thrown when the specified token is the zero address
error TokenAlreadyConfiguredWithState(); //Thrown if the token as already been enabled or disabled
error DepositAmountCannotBeZero(); // Thrown if staker attempts to call deposit() with zero amount
error WithdrawAmountCannotBeZero(); //Thrown if staker attempts to call withdraw() with zero amount
error TokenNotAllowedForStaking(); // Thrown if staker attempts to stake unsupported token (or token disabled for staking)
error UserDoesNotHaveStake(); //Thrown if the staker is attempting to migrate with no stake
error MigratorCannotBeZeroAddress(); //Thrown if the provided migrator is the zero address
error MigratorAlreadyAllowedOrBlocked(); //Thrown if attempting to block a migrator which has already been blocked or attempting to allow a migrator which is already allowed
error MigratorBlocked(); //Thrown if the provided migrator contract has been blacklisted.
error CannotDepositForZeroAddress(); //Thrown if caller tries to deposit on behalf of the zero address
error CannotRenounceOwnership(); //Thrown if the renounceOwnership() function is called
error DuplicateToken(); //Thrown when there is a duplicate in the provided token address array
error TokenArrayCannotBeEmpty(); //Thrown when the provided token address array is empty
/*//////////////////////////////////////////////////////////////
Staker Events
//////////////////////////////////////////////////////////////*/
///@notice Emitted when a staker deposits/stakes a supported token into the Ztaking Pool
///@param eventId The unique event Id associated with the Deposit event
///@param depositor The address of the depositer/staker transfering funds to the Ztaking Pool
///@param token The address of the token deposited/staked into the pool
///@param amount The amount of token deposited/staked into the pool
event Deposit(
uint256 indexed eventId,
address indexed depositor,
address indexed token,
uint256 amount
);
///@notice Emitted when a staker withdraws a previously staked tokens from the Ztaking Pool
///@param eventId The unique event Id associated with the Withdraw event
///@param withdrawer The address of the staker withdrawing funds from the Ztaking Pool
///@param token The address of the token being withdrawn from the pool
///@param amount The amount of tokens withdrawn the pool
event Withdraw(uint256 indexed eventId, address indexed withdrawer, address indexed token, uint256 amount);
///@notice Emitted when a staker migrates their tokens from the ZtakingPool to Zircuit.
///@param eventId The unique event Id associated with the Migrate event
///@param user The address of the staker migrating funds to Zircuit
///@param tokens The addresses of the tokens being being migrated from the ZtakingPool to Zircuit
///@param destination The address which the tokens will be transferred to on Zircuit
///@param migrator The address of the migrator contract which initially receives the migrated tokens
///@param amounts The amounts of each token migrated to Zircuit
event Migrate(
uint256 indexed eventId,
address indexed user,
address[] tokens,
address destination,
address migrator,
uint256[] amounts
);
/*//////////////////////////////////////////////////////////////
Admin Events
//////////////////////////////////////////////////////////////*/
///@notice Emitted when the required signer for the migration signature is changed
///@param newSigner The address of the new signer which must sign the migration signature
event SignerChanged(address newSigner);
///@notice Emitted when a token has been enabled or disabled for staking
///@param token The address of the token which has been enabled/disabled for staking
///@param enabled Is true if the token is being enabled and false if the token is being disabled
event TokenStakabilityChanged(address token, bool enabled);
///@notice Emitted when a migrator has been added or removed from the blocklist
///@param migrator The address of the migrator which has been added or removed from the blocklist
///@param blocked Is true if the migrator was added to the blocklist, and false if it was removed from the blocklist
event BlocklistChanged(address migrator, bool blocked);
/*//////////////////////////////////////////////////////////////
Staker Functions
//////////////////////////////////////////////////////////////*/
///@notice Stake a specified amount of a particular supported token into the Ztaking Pool
///@param _token The token to deposit/stake in the Ztaking Pool
///@param _for The user to deposit/stake on behalf of
///@param _amount The amount of token to deposit/stake into the Ztaking Pool
function depositFor(address _token, address _for, uint256 _amount) external;
///@notice Stake a specified amount of ether into the Ztaking Pool
///@param _for The user to deposit/stake on behalf of
///@dev the amount deposited is specified by msg.value
function depositETHFor(address _for) payable external;
///@notice Withdraw a specified amount of a particular supported token previously staked into the Ztaking Pool
///@param _token The token to withdraw from the Ztaking Pool
///@param _amount The amount of token to withdraw from the Ztaking Pool
function withdraw(address _token, uint256 _amount) external;
///@notice Migrate the staked tokens for the caller from the Ztaking Pool to Zircuit
///@dev called by the staker
///@param _tokens The tokens to migrate to Zircuit from the Ztaking Pool
///@param _migratorContract The migrator contract which will initially receive the migrated tokens before moving them to Zircuit
///@param _destination The address which will receive the migrated tokens on Zircuit
///@param _signatureExpiry The timestamp at which the signature in _authorizationSignatureFromZircuit expires
///@param _authorizationSignatureFromZircuit The authorization signature which is signed by the zircuit signer and indicates the correct migrator contract
function migrate(
address[] calldata _tokens,
address _migratorContract,
address _destination,
uint256 _signatureExpiry,
bytes memory _authorizationSignatureFromZircuit
) external;
///@notice Migrate the staked tokens for the caller from the Ztaking Pool to Zircuit
///@param _user The staker to migrate tokens for
///@param _tokens The tokens to migrate to Zircuit from the Ztaking Pool
///@param _migratorContract The migrator contract which will initially receive the migrated tokens before moving them to Zircuit
///@param _destination The address which will receive the migrated tokens on Zircuit
///@param _signatureExpiry The timestamp at which the signature in _authorizationSignatureFromZircuit expires
///@param _stakerSignature The signature from the staker authorizing the migration of their tokens
function migrateWithSig(
address _user,
address[] calldata _tokens,
address _migratorContract,
address _destination,
uint256 _signatureExpiry,
bytes memory _stakerSignature
) external;
/*//////////////////////////////////////////////////////////////
Admin Functions
//////////////////////////////////////////////////////////////*/
///@notice Set/Change the required signer for the migration signature (_authorizationSignatureFromZircuit in the migrate() function)
///@param _signer The address of the new signer for the migration signature
///@dev Only callable by the owner
function setZircuitSigner(address _signer) external;
///@notice Enable or disable the specified token for staking
///@param _token The token to enable or disable for staking
///@param _canStake If true, then staking is to be enabled. If false, then staking will be disabled.
///@dev Only callable by the owner
function setStakable(address _token, bool _canStake) external;
///@notice Add or remove the migrator to/from the blocklist, such that it can no longer be used from migrating tokens from the staking pool
///@param _migrator The migrator contract to add or remove from the blocklist
///@param _blocklisted If true, then add the migrator to the blocklist. If false, then remove the migrator from the blocklist.
///@dev Only callable by the owner
function blockMigrator(address _migrator, bool _blocklisted) external;
///@notice Pause further staking through the deposit function.
///@dev Only callable by the owner. Withdrawals and migrations will still be possible when paused
function pause() external;
///@notice Unpause staking allowing the deposit function to be used again
///@dev Only callable by the owner
function unpause() external;
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.20;
import {Ownable} from "./Ownable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is specified at deployment time in the constructor for `Ownable`. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
if (pendingOwner() != sender) {
revert OwnableUnauthorizedAccount(sender);
}
_transferOwnership(sender);
}
}
{
"compilationTarget": {
"contracts/BatchMigrator.sol": "BatchMigrator"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_ztakingPool","type":"address"},{"internalType":"address","name":"_migrator","type":"address"},{"internalType":"uint256","name":"_signatureExpiry","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CannotRenounceOwnership","type":"error"},{"inputs":[],"name":"MigratorCannotBeZeroAddress","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"SignatureExpiryCannotBeZero","type":"error"},{"inputs":[],"name":"ZtakingPoolCannotBeZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","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"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptZtakingPoolOwnershipTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_users","type":"address[]"},{"internalType":"address[][]","name":"_tokens","type":"address[][]"},{"internalType":"address[]","name":"_destinations","type":"address[]"},{"internalType":"bytes[]","name":"_signatures","type":"bytes[]"}],"name":"batchMigrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_usersDestinations","type":"address[]"},{"internalType":"address[][]","name":"_tokens","type":"address[][]"},{"internalType":"bytes[]","name":"_signatures","type":"bytes[]"}],"name":"batchMigrateWithDestinationEqualToUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"migrator","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_signatureExpiry","type":"uint256"}],"name":"setSignatureExpiry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signatureExpiry","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferZtakingPoolOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ztakingPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_migrator","type":"address"},{"internalType":"bool","name":"_blocklisted","type":"bool"}],"name":"ztakingPoolBlockMigrator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ztakingPoolPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"bool","name":"_canStake","type":"bool"}],"name":"ztakingPoolSetStakable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_signer","type":"address"}],"name":"ztakingPoolSetZircuitSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ztakingPoolUnpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]