Source Code
Overview
POL Balance
POL Value
$0.00Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
ZkBobDirectDepositQueue
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../libraries/ZkAddress.sol";
import "../interfaces/IOperatorManager.sol";
import "../interfaces/IZkBobDirectDeposits.sol";
import "../interfaces/IZkBobDirectDepositQueue.sol";
import "../interfaces/IZkBobPool.sol";
import "../utils/Ownable.sol";
import "../proxy/EIP1967Admin.sol";
/**
* @title ZkBobDirectDepositQueue
* Queue for zkBob direct deposits.
*/
contract ZkBobDirectDepositQueue is IZkBobDirectDeposits, IZkBobDirectDepositQueue, EIP1967Admin, Ownable {
using SafeERC20 for IERC20;
uint256 internal constant R = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
uint256 internal constant MAX_NUMBER_OF_DIRECT_DEPOSITS = 16;
bytes4 internal constant MESSAGE_PREFIX_DIRECT_DEPOSIT_V1 = 0x00000001;
uint256 internal immutable TOKEN_DENOMINATOR;
uint256 internal constant TOKEN_NUMERATOR = 1000;
address public immutable token;
uint256 public immutable pool_id;
address public immutable pool;
IOperatorManager public operatorManager;
mapping(uint256 => IZkBobDirectDeposits.DirectDeposit) internal directDeposits;
uint32 public directDepositNonce;
uint64 public directDepositFee;
uint40 public directDepositTimeout;
event UpdateOperatorManager(address manager);
event UpdateDirectDepositFee(uint64 fee);
event UpdateDirectDepositTimeout(uint40 timeout);
event SubmitDirectDeposit(
address indexed sender,
uint256 indexed nonce,
address fallbackUser,
ZkAddress.ZkAddress zkAddress,
uint64 deposit
);
event RefundDirectDeposit(uint256 indexed nonce, address receiver, uint256 amount);
event CompleteDirectDepositBatch(uint256[] indices);
constructor(address _pool, address _token, uint256 _denominator) {
require(Address.isContract(_token), "ZkBobDirectDepositQueue: not a contract");
require(TOKEN_NUMERATOR == 1 || _denominator == 1, "ZkBobDirectDepositQueue: incorrect denominator");
pool = _pool;
token = _token;
TOKEN_DENOMINATOR = _denominator;
pool_id = uint24(IZkBobPool(_pool).pool_id());
}
/**
* @dev Updates used operator manager contract.
* Operator manager in this contract is only responsible for fast-track processing of refunds.
* Usage of fully permissionless operator managers is not recommended, due to existence of front-running DoS attacks.
* Callable only by the contract owner / proxy admin.
* @param _operatorManager new operator manager implementation.
*/
function setOperatorManager(IOperatorManager _operatorManager) external onlyOwner {
require(address(_operatorManager) != address(0), "ZkBobDirectDepositQueue: manager is zero address");
operatorManager = _operatorManager;
emit UpdateOperatorManager(address(_operatorManager));
}
/**
* @dev Updates direct deposit fee.
* Callable only by the contract owner / proxy admin.
* @param _fee new absolute fee value for making a direct deposit, in zkBOB units.
*/
function setDirectDepositFee(uint64 _fee) external onlyOwner {
directDepositFee = _fee;
emit UpdateDirectDepositFee(_fee);
}
/**
* @dev Updates direct deposit timeout.
* Callable only by the contract owner / proxy admin.
* @param _timeout new timeout value for refunding non-fulfilled/rejected direct deposits.
*/
function setDirectDepositTimeout(uint40 _timeout) external onlyOwner {
require(_timeout <= 7 days, "ZkBobDirectDepositQueue: timeout too large");
directDepositTimeout = _timeout;
emit UpdateDirectDepositTimeout(_timeout);
}
/// @inheritdoc IZkBobDirectDeposits
function getDirectDeposit(uint256 _index) external view returns (IZkBobDirectDeposits.DirectDeposit memory) {
return directDeposits[_index];
}
/// @inheritdoc IZkBobDirectDepositQueue
function collect(
uint256[] calldata _indices,
uint256 _out_commit
)
external
returns (uint256 total, uint256 totalFee, uint256 hashsum, bytes memory message)
{
require(msg.sender == pool, "ZkBobDirectDepositQueue: invalid caller");
uint256 count = _indices.length;
require(count > 0, "ZkBobDirectDepositQueue: empty deposit list");
require(count <= MAX_NUMBER_OF_DIRECT_DEPOSITS, "ZkBobDirectDepositQueue: too many deposits");
bytes memory input = new bytes(32 + (10 + 32 + 8) * MAX_NUMBER_OF_DIRECT_DEPOSITS);
message = new bytes(4 + count * (8 + 10 + 32 + 8));
assembly {
mstore(add(input, 32), _out_commit)
mstore(add(message, 32), or(shl(248, count), MESSAGE_PREFIX_DIRECT_DEPOSIT_V1))
}
total = 0;
totalFee = 0;
for (uint256 i = 0; i < count; ++i) {
uint256 index = _indices[i];
DirectDeposit storage dd = directDeposits[index];
(bytes32 pk, bytes10 diversifier, uint64 deposit, uint64 fee, DirectDepositStatus status) =
(dd.pk, dd.diversifier, dd.deposit, dd.fee, dd.status);
require(status == DirectDepositStatus.Pending, "ZkBobDirectDepositQueue: direct deposit not pending");
assembly {
// bytes10(dd.diversifier) ++ bytes32(dd.pk) ++ bytes8(dd.deposit)
let offset := mul(i, 50)
mstore(add(input, add(64, offset)), diversifier)
mstore(add(input, add(82, offset)), deposit)
mstore(add(input, add(74, offset)), pk)
}
assembly {
// bytes8(dd.index) ++ bytes10(dd.diversifier) ++ bytes32(dd.pk) ++ bytes8(dd.deposit)
let offset := mul(i, 58)
mstore(add(message, add(36, offset)), shl(192, index))
mstore(add(message, add(44, offset)), diversifier)
mstore(add(message, add(62, offset)), deposit)
mstore(add(message, add(54, offset)), pk)
}
dd.status = DirectDepositStatus.Completed;
total += deposit;
totalFee += fee;
}
hashsum = uint256(keccak256(input)) % R;
IERC20(token).safeTransfer(msg.sender, (total + totalFee) * TOKEN_DENOMINATOR / TOKEN_NUMERATOR);
emit CompleteDirectDepositBatch(_indices);
}
/// @inheritdoc IZkBobDirectDeposits
function directDeposit(
address _fallbackUser,
uint256 _amount,
string calldata _zkAddress
)
external
returns (uint256)
{
return directDeposit(_fallbackUser, _amount, bytes(_zkAddress));
}
/// @inheritdoc IZkBobDirectDeposits
function directDeposit(
address _fallbackUser,
uint256 _amount,
bytes memory _rawZkAddress
)
public
returns (uint256)
{
IERC20(token).safeTransferFrom(msg.sender, address(this), _amount);
return _recordDirectDeposit(msg.sender, _fallbackUser, _amount, _rawZkAddress);
}
/// @inheritdoc IZkBobDirectDeposits
function onTokenTransfer(address _from, uint256 _value, bytes calldata _data) external returns (bool) {
require(msg.sender == token, "ZkBobDirectDepositQueue: not a token caller");
(address fallbackUser, bytes memory rawZkAddress) = abi.decode(_data, (address, bytes));
_recordDirectDeposit(_from, fallbackUser, _value, rawZkAddress);
return true;
}
/// @inheritdoc IZkBobDirectDeposits
function refundDirectDeposit(uint256 _index) external {
bool isOperator = operatorManager.isOperator(msg.sender);
DirectDeposit storage dd = directDeposits[_index];
require(dd.status == DirectDepositStatus.Pending, "ZkBobDirectDepositQueue: direct deposit not pending");
require(
isOperator || dd.timestamp + directDepositTimeout < block.timestamp,
"ZkBobDirectDepositQueue: direct deposit timeout not passed"
);
_refundDirectDeposit(_index, dd);
}
/// @inheritdoc IZkBobDirectDeposits
function refundDirectDeposit(uint256[] calldata _indices) external {
bool isOperator = operatorManager.isOperator(msg.sender);
uint256 timeout = directDepositTimeout;
for (uint256 i = 0; i < _indices.length; ++i) {
DirectDeposit storage dd = directDeposits[_indices[i]];
if (dd.status == DirectDepositStatus.Pending) {
require(
isOperator || dd.timestamp + timeout < block.timestamp,
"ZkBobDirectDepositQueue: direct deposit timeout not passed"
);
_refundDirectDeposit(_indices[i], dd);
}
}
}
function _refundDirectDeposit(uint256 _index, IZkBobDirectDeposits.DirectDeposit storage _dd) internal {
_dd.status = IZkBobDirectDeposits.DirectDepositStatus.Refunded;
(address fallbackReceiver, uint96 amount) = (_dd.fallbackReceiver, _dd.sent);
IERC20(token).safeTransfer(fallbackReceiver, amount);
emit RefundDirectDeposit(_index, fallbackReceiver, amount);
}
function _recordDirectDeposit(
address _sender,
address _fallbackReceiver,
uint256 _amount,
bytes memory _rawZkAddress
)
internal
returns (uint256 nonce)
{
require(_fallbackReceiver != address(0), "ZkBobDirectDepositQueue: fallback user is zero");
uint64 fee = directDepositFee;
// small amount of wei might get lost during division, this amount will stay in the contract indefinitely
uint64 depositAmount = uint64(_amount / TOKEN_DENOMINATOR * TOKEN_NUMERATOR);
require(depositAmount > fee, "ZkBobDirectDepositQueue: direct deposit amount is too low");
unchecked {
depositAmount -= fee;
}
ZkAddress.ZkAddress memory zkAddress = ZkAddress.parseZkAddress(_rawZkAddress, uint24(pool_id));
IZkBobDirectDeposits.DirectDeposit memory dd = IZkBobDirectDeposits.DirectDeposit({
fallbackReceiver: _fallbackReceiver,
sent: uint96(_amount),
deposit: depositAmount,
fee: fee,
timestamp: uint40(block.timestamp),
status: DirectDepositStatus.Pending,
diversifier: zkAddress.diversifier,
pk: zkAddress.pk
});
nonce = directDepositNonce++;
directDeposits[nonce] = dd;
IZkBobPool(pool).recordDirectDeposit(_sender, depositAmount);
emit SubmitDirectDeposit(_sender, nonce, _fallbackReceiver, zkAddress, depositAmount);
}
/**
* @dev Tells if caller is the contract owner.
* Gives ownership rights to the proxy admin as well.
* @return true, if caller is the contract owner or proxy admin.
*/
function _isOwner() internal view override returns (bool) {
return super._isOwner() || _admin() == _msgSender();
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
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");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
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");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
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));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
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 safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.15;
import "@base58-solidity/Base58.sol";
/**
* @title ZkAddress
* Library for parsing zkBob addresses.
*/
library ZkAddress {
uint256 internal constant R = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
error InvalidZkAddress();
error InvalidZkAddressLength();
error InvalidZkAddressChecksum();
struct ZkAddress {
bytes10 diversifier;
bytes32 pk;
}
/**
* @notice Parses zkBob address from the zkBob UI representation.
* Note that on-chain base58 decoding is quite gas intensive (610k gas),
* consider to use other gas efficient formats from the below.
* @param _rawZkAddress zk address base58 string representation in the zkBob UI format.
* @param _poolId id of the pool to verify checksum for.
*/
function parseZkAddress(
string calldata _rawZkAddress,
uint24 _poolId
)
external
pure
returns (ZkAddress memory res)
{
bytes memory _rawZkAddressBytes = bytes(_rawZkAddress);
uint256 len = _len(_rawZkAddressBytes);
if (len > 63 || len < 47) {
revert InvalidZkAddressLength();
}
// _zkAddress == Base58.encode(abi.encodePacked(bytes10(diversifier_le), bytes32(pk_le), bytes4(checksum)))
bytes memory dec = Base58.decode(_rawZkAddressBytes);
if (_len(dec) != 46) {
revert InvalidZkAddressLength();
}
res = _parseZkAddressLE46(dec, _poolId);
if (uint256(res.pk) >= R) {
revert InvalidZkAddress();
}
}
/**
* @notice Parses zkBob address from the gas-efficient hex formats.
* Note difference in endianness among checksummed and non-checksummed formats.
* @param _rawZkAddress zk address hex representation in one of 3 formats.
* @param _poolId id of the pool to verify checksum for.
*/
function parseZkAddress(bytes memory _rawZkAddress, uint24 _poolId) external pure returns (ZkAddress memory res) {
uint256 len = _len(_rawZkAddress);
if (len == 42) {
// _zkAddress == abi.encodePacked(bytes10(diversifier_be), bytes32(pk_be))
res = ZkAddress(bytes10(_load(_rawZkAddress, 32)), _load(_rawZkAddress, 42));
} else if (len == 64) {
// _zkAddress == abi.encode(bytes10(diversifier_be), bytes32(pk_be)) == abi.encode(ZkAddress(zkAddress))
res = abi.decode(_rawZkAddress, (ZkAddress));
} else if (len == 46) {
// _zkAddress == abi.encodePacked(bytes10(diversifier_le), bytes32(pk_le), bytes4(checksum))
res = _parseZkAddressLE46(_rawZkAddress, _poolId);
} else if (len < 64 && len > 46) {
// _zkAddress == Base58.encode(abi.encodePacked(bytes10(diversifier_le), bytes32(pk_le), bytes4(checksum)))
bytes memory dec = Base58.decode(_rawZkAddress);
if (_len(dec) != 46) {
revert InvalidZkAddressLength();
}
res = _parseZkAddressLE46(dec, _poolId);
} else {
revert InvalidZkAddressLength();
}
if (uint256(res.pk) >= R) {
revert InvalidZkAddress();
}
}
function _parseZkAddressLE46(bytes memory _rawZkAddress, uint24 _poolId) internal pure returns (ZkAddress memory) {
_verifyChecksum(_poolId, _rawZkAddress);
bytes32 diversifier = _toLE(_load(_rawZkAddress, 32)) << 176;
bytes32 pk = _toLE(_load(_rawZkAddress, 42));
return ZkAddress(bytes10(diversifier), pk);
}
function _verifyChecksum(uint24 _poolId, bytes memory _rawZkAddress) internal pure {
bytes4 checksum = bytes4(_load(_rawZkAddress, 74));
bytes32 zkAddressHash;
assembly {
zkAddressHash := keccak256(add(_rawZkAddress, 32), 42)
}
bytes4 zkAddressChecksum1 = bytes4(zkAddressHash);
bytes4 zkAddressChecksum2 = bytes4(keccak256(abi.encodePacked(_poolId, zkAddressHash)));
if (checksum != zkAddressChecksum1 && checksum != zkAddressChecksum2) {
revert InvalidZkAddressChecksum();
}
}
function _len(bytes memory _b) internal pure returns (uint256 len) {
assembly {
len := mload(_b)
}
}
function _load(bytes memory _b, uint256 _offset) internal pure returns (bytes32 word) {
assembly {
word := mload(add(_b, _offset))
}
}
function _toLE(bytes32 _value) internal pure returns (bytes32 res) {
assembly {
res := byte(0, _value)
res := add(res, shl(8, byte(1, _value)))
res := add(res, shl(16, byte(2, _value)))
res := add(res, shl(24, byte(3, _value)))
res := add(res, shl(32, byte(4, _value)))
res := add(res, shl(40, byte(5, _value)))
res := add(res, shl(48, byte(6, _value)))
res := add(res, shl(56, byte(7, _value)))
res := add(res, shl(64, byte(8, _value)))
res := add(res, shl(72, byte(9, _value)))
res := add(res, shl(80, byte(10, _value)))
res := add(res, shl(88, byte(11, _value)))
res := add(res, shl(96, byte(12, _value)))
res := add(res, shl(104, byte(13, _value)))
res := add(res, shl(112, byte(14, _value)))
res := add(res, shl(120, byte(15, _value)))
res := add(res, shl(128, byte(16, _value)))
res := add(res, shl(136, byte(17, _value)))
res := add(res, shl(144, byte(18, _value)))
res := add(res, shl(152, byte(19, _value)))
res := add(res, shl(160, byte(20, _value)))
res := add(res, shl(168, byte(21, _value)))
res := add(res, shl(176, byte(22, _value)))
res := add(res, shl(184, byte(23, _value)))
res := add(res, shl(192, byte(24, _value)))
res := add(res, shl(200, byte(25, _value)))
res := add(res, shl(208, byte(26, _value)))
res := add(res, shl(216, byte(27, _value)))
res := add(res, shl(224, byte(28, _value)))
res := add(res, shl(232, byte(29, _value)))
res := add(res, shl(240, byte(30, _value)))
res := add(res, shl(248, byte(31, _value)))
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
interface IOperatorManager {
function isOperator(address _addr) external view returns (bool);
function isOperatorFeeReceiver(address _operator, address _addr) external view returns (bool);
function operatorURI() external view returns (string memory);
}// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;
interface IZkBobDirectDeposits {
enum DirectDepositStatus {
Missing, // requested deposit does not exist
Pending, // requested deposit was submitted and is pending in the queue
Completed, // requested deposit was successfully processed
Refunded // requested deposit was refunded to the fallback receiver
}
struct DirectDeposit {
address fallbackReceiver; // refund receiver for deposits that cannot be processed
uint96 sent; // sent amount in BOB tokens (18 decimals)
uint64 deposit; // deposit amount, after subtracting all fees (9 decimals)
uint64 fee; // deposit fee (9 decimals)
uint40 timestamp; // deposit submission timestamp
DirectDepositStatus status; // deposit status
bytes10 diversifier; // receiver zk address, part 1/2
bytes32 pk; // receiver zk address, part 2/2
}
/**
* @notice Retrieves the direct deposits from the queue by its id.
* @param depositId id of the submitted deposit.
* @return deposit recorded deposit struct
*/
function getDirectDeposit(uint256 depositId) external view returns (DirectDeposit memory deposit);
/**
* @notice Performs a direct deposit to the specified zk address.
* In case the deposit cannot be processed, it can be refunded later to the fallbackReceiver address.
* @param fallbackReceiver receiver of deposit refund.
* @param amount direct deposit amount.
* @param zkAddress receiver zk address.
* @return depositId id of the submitted deposit to query status for.
*/
function directDeposit(
address fallbackReceiver,
uint256 amount,
bytes memory zkAddress
)
external
returns (uint256 depositId);
/**
* @notice Performs a direct deposit to the specified zk address.
* In case the deposit cannot be processed, it can be refunded later to the fallbackReceiver address.
* @param fallbackReceiver receiver of deposit refund.
* @param amount direct deposit amount.
* @param zkAddress receiver zk address.
* @return depositId id of the submitted deposit to query status for.
*/
function directDeposit(
address fallbackReceiver,
uint256 amount,
string memory zkAddress
)
external
returns (uint256 depositId);
/**
* @notice ERC677 callback for performing a direct deposit.
* Do not call this function directly, it's only intended to be called by the token contract.
* @param from original tokens sender.
* @param amount direct deposit amount.
* @param data encoded address pair - abi.encode(address(fallbackReceiver), bytes(zkAddress))
* @return ok true, if deposit of submitted successfully.
*/
function onTokenTransfer(address from, uint256 amount, bytes memory data) external returns (bool ok);
/**
* @notice Tells the direct deposit fee, in zkBOB units (9 decimals).
* @return fee direct deposit submission fee.
*/
function directDepositFee() external view returns (uint64 fee);
/**
* @notice Tells the timeout after which unprocessed direct deposits can be refunded.
* @return timeout duration in seconds.
*/
function directDepositTimeout() external view returns (uint40 timeout);
/**
* @notice Tells the nonce of next direct deposit.
* @return nonce direct deposit nonce.
*/
function directDepositNonce() external view returns (uint32 nonce);
/**
* @notice Refunds specified direct deposit.
* Can be called by anyone, but only after the configured timeout has passed.
* Function will revert for deposit that is not pending.
* @param index deposit id to issue a refund for.
*/
function refundDirectDeposit(uint256 index) external;
/**
* @notice Refunds multiple direct deposits.
* Can be called by anyone, but only after the configured timeout has passed.
* Function will do nothing for non-pending deposits and will not revert.
* @param indices deposit ids to issue a refund for.
*/
function refundDirectDeposit(uint256[] memory indices) external;
}// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;
interface IZkBobDirectDepositQueue {
/**
* @dev Collects aggregated info about submitted direct deposits and marks them as completed.
* Callable only by the zkBOB pool contract.
* @param _indices list of direct deposit indices to process, max of 16 indices are allowed.
* @param _out_commit pre-calculated out commitment associated with the given deposits.
* @return total sum of deposit amounts, not counting fees.
* @return totalFee sum of deposit fees.
* @return hashsum hashsum over all retrieved direct deposits.
* @return message memo message to record into the tree.
*/
function collect(
uint256[] calldata _indices,
uint256 _out_commit
)
external
returns (uint256 total, uint256 totalFee, uint256 hashsum, bytes memory message);
}// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;
interface IZkBobPool {
function pool_id() external view returns (uint256);
function recordDirectDeposit(address _sender, uint256 _amount) external;
}// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.15;
import "@openzeppelin/contracts/access/Ownable.sol" as OZOwnable;
/**
* @title Ownable
*/
contract Ownable is OZOwnable.Ownable {
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view override {
require(_isOwner(), "Ownable: caller is not the owner");
}
/**
* @dev Tells if caller is the contract owner.
* @return true, if caller is the contract owner.
*/
function _isOwner() internal view virtual returns (bool) {
return owner() == _msgSender();
}
}// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.15;
/**
* @title EIP1967Admin
* @dev Upgradeable proxy pattern implementation according to minimalistic EIP1967.
*/
contract EIP1967Admin {
// EIP 1967
// bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)
uint256 internal constant EIP1967_ADMIN_STORAGE = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
modifier onlyAdmin() {
require(msg.sender == _admin(), "EIP1967Admin: not an admin");
_;
}
function _admin() internal view returns (address res) {
assembly {
res := sload(EIP1967_ADMIN_STORAGE)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; /** * @title Base58 * @author [email protected] * @notice This algorithm was migrated from github.com/mr-tron/base58 to solidity. * Note that it is not yet optimized for gas, so it is recommended to use it only in the view/pure function. */ library Base58 { bytes constant ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; /** * @notice encode is used to encode the given bytes in base58 standard. * @param data_ raw data, passed in as bytes. * @return base58 encoded data_, returned as bytes. */ function encode(bytes memory data_) public pure returns (bytes memory) { unchecked { uint256 size = data_.length; uint256 zeroCount; while (zeroCount < size && data_[zeroCount] == 0) { zeroCount++; } size = zeroCount + ((size - zeroCount) * 8351) / 6115 + 1; bytes memory slot = new bytes(size); uint32 carry; int256 m; int256 high = int256(size) - 1; for (uint256 i = 0; i < data_.length; i++) { m = int256(size - 1); for (carry = uint8(data_[i]); m > high || carry != 0; m--) { carry = carry + 256 * uint8(slot[uint256(m)]); slot[uint256(m)] = bytes1(uint8(carry % 58)); carry /= 58; } high = m; } uint256 n; for (n = zeroCount; n < size && slot[n] == 0; n++) {} size = slot.length - (n - zeroCount); bytes memory out = new bytes(size); for (uint256 i = 0; i < size; i++) { uint256 j = i + n - zeroCount; out[i] = ALPHABET[uint8(slot[j])]; } return out; } } /** * @notice decode is used to decode the given string in base58 standard. * @param data_ data encoded with base58, passed in as bytes. * @return raw data, returned as bytes. */ function decode(bytes memory data_) public pure returns (bytes memory) { unchecked { uint256 zero = 49; uint256 b58sz = data_.length; uint256 zcount = 0; for (uint256 i = 0; i < b58sz && uint8(data_[i]) == zero; i++) { zcount++; } uint256 t; uint256 c; bool f; bytes memory binu = new bytes(2 * (((b58sz * 8351) / 6115) + 1)); uint32[] memory outi = new uint32[]((b58sz + 3) / 4); for (uint256 i = 0; i < data_.length; i++) { bytes1 r = data_[i]; (c, f) = indexOf(ALPHABET, r); require(f, "invalid base58 digit"); for (int256 k = int256(outi.length) - 1; k >= 0; k--) { t = uint64(outi[uint256(k)]) * 58 + c; c = t >> 32; outi[uint256(k)] = uint32(t & 0xffffffff); } } uint64 mask = uint64(b58sz % 4) * 8; if (mask == 0) { mask = 32; } mask -= 8; uint256 outLen = 0; for (uint256 j = 0; j < outi.length; j++) { while (mask < 32) { binu[outLen] = bytes1(uint8(outi[j] >> mask)); outLen++; if (mask < 8) { break; } mask -= 8; } mask = 24; } for (uint256 msb = zcount; msb < binu.length; msb++) { if (binu[msb] > 0) { return slice(binu, msb - zcount, outLen); } } return slice(binu, 0, outLen); } } /** * @notice encodeToString is used to encode the given byte in base58 standard. * @param data_ raw data, passed in as bytes. * @return base58 encoded data_, returned as a string. */ function encodeToString(bytes memory data_) public pure returns (string memory) { return string(encode(data_)); } /** * @notice encodeFromString is used to encode the given string in base58 standard. * @param data_ raw data, passed in as a string. * @return base58 encoded data_, returned as bytes. */ function encodeFromString(string memory data_) public pure returns (bytes memory) { return encode(bytes(data_)); } /** * @notice decode is used to decode the given string in base58 standard. * @param data_ data encoded with base58, passed in as string. * @return raw data, returned as bytes. */ function decodeFromString(string memory data_) public pure returns (bytes memory) { return decode(bytes(data_)); } /** * @notice slice is used to slice the given byte, returns the bytes in the range of [start_, end_) * @param data_ raw data, passed in as bytes. * @param start_ start index. * @param end_ end index. * @return slice data */ function slice( bytes memory data_, uint256 start_, uint256 end_ ) public pure returns (bytes memory) { unchecked { bytes memory ret = new bytes(end_ - start_); for (uint256 i = 0; i < end_ - start_; i++) { ret[i] = data_[i + start_]; } return ret; } } /** * @notice indexOf is used to find where char_ appears in data_. * @param data_ raw data, passed in as bytes. * @param char_ target byte. * @return index, and whether the search was successful. */ function indexOf(bytes memory data_, bytes1 char_) public pure returns (uint256, bool) { unchecked { for (uint256 i = 0; i < data_.length; i++) { if (data_[i] == char_) { return (i, true); } } return (0, false); } } }
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../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.
*
* By default, the owner account will be the one that deploys the contract. 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;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @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 {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing 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 {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_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 v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @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;
}
}{
"remappings": [
"@base58-solidity/=lib/base58-solidity/contracts/",
"@gnosis/=lib/@gnosis/",
"@gnosis/auction/=lib/@gnosis/auction/contracts/",
"@openzeppelin/=lib/@openzeppelin/contracts/",
"@openzeppelin/contracts/=lib/@openzeppelin/contracts/contracts/",
"@uniswap/=lib/@uniswap/",
"base58-solidity/=lib/base58-solidity/contracts/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"libraries": {
"lib/base58-solidity/contracts/Base58.sol": {
"Base58": "0xcb11bf4543efeb83d7d2fb99f6b9dd040d7a6eaa"
},
"src/libraries/ZkAddress.sol": {
"ZkAddress": "0x43830a424783657b92913bef78ec839d2085fcf9"
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_pool","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_denominator","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"indices","type":"uint256[]"}],"name":"CompleteDirectDepositBatch","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":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RefundDirectDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"address","name":"fallbackUser","type":"address"},{"components":[{"internalType":"bytes10","name":"diversifier","type":"bytes10"},{"internalType":"bytes32","name":"pk","type":"bytes32"}],"indexed":false,"internalType":"struct ZkAddress.ZkAddress","name":"zkAddress","type":"tuple"},{"indexed":false,"internalType":"uint64","name":"deposit","type":"uint64"}],"name":"SubmitDirectDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"fee","type":"uint64"}],"name":"UpdateDirectDepositFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint40","name":"timeout","type":"uint40"}],"name":"UpdateDirectDepositTimeout","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"manager","type":"address"}],"name":"UpdateOperatorManager","type":"event"},{"inputs":[{"internalType":"uint256[]","name":"_indices","type":"uint256[]"},{"internalType":"uint256","name":"_out_commit","type":"uint256"}],"name":"collect","outputs":[{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"totalFee","type":"uint256"},{"internalType":"uint256","name":"hashsum","type":"uint256"},{"internalType":"bytes","name":"message","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fallbackUser","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_rawZkAddress","type":"bytes"}],"name":"directDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fallbackUser","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"string","name":"_zkAddress","type":"string"}],"name":"directDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"directDepositFee","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"directDepositNonce","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"directDepositTimeout","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getDirectDeposit","outputs":[{"components":[{"internalType":"address","name":"fallbackReceiver","type":"address"},{"internalType":"uint96","name":"sent","type":"uint96"},{"internalType":"uint64","name":"deposit","type":"uint64"},{"internalType":"uint64","name":"fee","type":"uint64"},{"internalType":"uint40","name":"timestamp","type":"uint40"},{"internalType":"enum IZkBobDirectDeposits.DirectDepositStatus","name":"status","type":"uint8"},{"internalType":"bytes10","name":"diversifier","type":"bytes10"},{"internalType":"bytes32","name":"pk","type":"bytes32"}],"internalType":"struct IZkBobDirectDeposits.DirectDeposit","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onTokenTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"operatorManager","outputs":[{"internalType":"contract IOperatorManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool_id","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_indices","type":"uint256[]"}],"name":"refundDirectDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"refundDirectDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_fee","type":"uint64"}],"name":"setDirectDepositFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint40","name":"_timeout","type":"uint40"}],"name":"setDirectDepositTimeout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IOperatorManager","name":"_operatorManager","type":"address"}],"name":"setOperatorManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6101006040523480156200001257600080fd5b50604051620023a7380380620023a783398101604081905262000035916200022c565b6200004033620001b0565b62000056826200020060201b62000f701760201c565b620000b85760405162461bcd60e51b815260206004820152602760248201527f5a6b426f624469726563744465706f73697451756575653a206e6f74206120636044820152661bdb9d1c9858dd60ca1b60648201526084015b60405180910390fd5b80600114620001215760405162461bcd60e51b815260206004820152602e60248201527f5a6b426f624469726563744465706f73697451756575653a20696e636f72726560448201526d31ba103232b737b6b4b730ba37b960911b6064820152608401620000af565b6001600160a01b0380841660e081905290831660a052608082905260408051632762b5b960e21b81529051639d8ad6e4916004808201926020929091908290030181865afa15801562000178573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200019e91906200026d565b62ffffff1660c0525062000287915050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03163b151590565b80516001600160a01b03811681146200022757600080fd5b919050565b6000806000606084860312156200024257600080fd5b6200024d846200020f565b92506200025d602085016200020f565b9150604084015190509250925092565b6000602082840312156200028057600080fd5b5051919050565b60805160a05160c05160e0516120ae620002f96000396000818161015c01528181610ab401526113db015260008181610235015261116e015260008181610361015281816103920152818161062201528181610e8c01526114ec015260008181610e45015261107d01526120ae6000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c8063a4c0ed36116100ad578063d7f59caa11610071578063d7f59caa14610300578063dc3ba6a314610313578063e24546f214610326578063f2fde38b14610349578063fc0c546a1461035c57600080fd5b8063a4c0ed3614610257578063b130603e1461027a578063b85369e6146102a8578063c278b761146102cd578063c41100fa146102ed57600080fd5b80636918822d116100f45780636918822d146101f1578063715018a61461020457806380a328921461020c5780638da5cb5b1461021f5780639d8ad6e41461023057600080fd5b806302592d371461013157806316f0115b146101575780632f84c96f1461019657806335d3cbcc146101a957806368dc1c55146101dc575b600080fd5b61014461013f3660046119a3565b610383565b6040519081526020015b60405180910390f35b61017e7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161014e565b60015461017e906001600160a01b031681565b6003546101c49064010000000090046001600160401b031681565b6040516001600160401b03909116815260200161014e565b6101ef6101ea366004611a46565b6103ce565b005b6101446101ff366004611ac8565b610549565b6101ef610595565b6101ef61021a366004611b23565b6105a9565b6000546001600160a01b031661017e565b6101447f000000000000000000000000000000000000000000000000000000000000000081565b61026a610265366004611ac8565b610615565b604051901515815260200161014e565b60035461029290600160601b900464ffffffffff1681565b60405164ffffffffff909116815260200161014e565b6003546102b89063ffffffff1681565b60405163ffffffff909116815260200161014e565b6102e06102db366004611b53565b6106d0565b60405161014e9190611ba4565b6101ef6102fb366004611c45565b6107ef565b6101ef61030e366004611b53565b6108b4565b6101ef610321366004611c62565b6109d8565b610339610334366004611c89565b610aa3565b60405161014e9493929190611d2c565b6101ef610357366004611c45565b610ef7565b61017e7f000000000000000000000000000000000000000000000000000000000000000081565b60006103ba6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333086610f7f565b6103c633858585610ff0565b949350505050565b6001546040516336b87bd760e11b81523360048201526000916001600160a01b031690636d70f7ae90602401602060405180830381865afa158015610417573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043b9190611d5b565b600354909150600160601b900464ffffffffff1660005b838110156105425760006002600087878581811061047257610472611d7d565b90506020020135815260200190815260200160002090506001600381111561049c5761049c611b6c565b6001820154600160a81b900460ff1660038111156104bc576104bc611b6c565b036105315783806104ea5750600181015442906104e8908590600160801b900464ffffffffff16611da9565b105b61050f5760405162461bcd60e51b815260040161050690611dc1565b60405180910390fd5b61053186868481811061052457610524611d7d565b90506020020135826114b2565b5061053b81611e1e565b9050610452565b5050505050565b600061058c858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061038392505050565b95945050505050565b61059d611565565b6105a760006115b9565b565b6105b1611565565b600380546bffffffffffffffff0000000019166401000000006001600160401b038416908102919091179091556040519081527f4fc5798183ecfb36b62f43c657e712d8b6e8661646d3c90bd3a5202335203180906020015b60405180910390a150565b6000336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106a35760405162461bcd60e51b815260206004820152602b60248201527f5a6b426f624469726563744465706f73697451756575653a206e6f742061207460448201526a37b5b2b71031b0b63632b960a91b6064820152608401610506565b6000806106b284860186611e37565b915091506106c287838884610ff0565b506001979650505050505050565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915260008281526002602090815260409182902082516101008101845281546001600160a01b0381168252600160a01b90046001600160601b03169281019290925260018101546001600160401b0380821694840194909452600160401b81049093166060830152600160801b830464ffffffffff166080830152909160a0830190600160a81b900460ff1660038111156107ac576107ac611b6c565b60038111156107bd576107bd611b6c565b81526001820154600160b01b900460b01b6001600160b01b031916602082015260029091015460409091015292915050565b6107f7611565565b6001600160a01b0381166108665760405162461bcd60e51b815260206004820152603060248201527f5a6b426f624469726563744465706f73697451756575653a206d616e6167657260448201526f206973207a65726f206164647265737360801b6064820152608401610506565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f267052ecaebdd552dc1b20904f59d83d51ae7add7514165322a7da9ef6cf543b9060200161060a565b6001546040516336b87bd760e11b81523360048201526000916001600160a01b031690636d70f7ae90602401602060405180830381865afa1580156108fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109219190611d5b565b6000838152600260205260409020909150600180820154600160a81b900460ff16600381111561095357610953611b6c565b146109705760405162461bcd60e51b815260040161050690611e86565b81806109ad5750600354600182015442916109a49164ffffffffff600160601b909204821691600160801b90910416611ed9565b64ffffffffff16105b6109c95760405162461bcd60e51b815260040161050690611dc1565b6109d383826114b2565b505050565b6109e0611565565b62093a808164ffffffffff161115610a4d5760405162461bcd60e51b815260206004820152602a60248201527f5a6b426f624469726563744465706f73697451756575653a2074696d656f757460448201526920746f6f206c6172676560b01b6064820152608401610506565b6003805464ffffffffff60601b1916600160601b64ffffffffff8416908102919091179091556040519081527f237f465c227da0b7fcd48ae7b5e7ec9d2ee347abbf6c93b008a616220d06ee399060200161060a565b600080806060336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b315760405162461bcd60e51b815260206004820152602760248201527f5a6b426f624469726563744465706f73697451756575653a20696e76616c69646044820152661031b0b63632b960c91b6064820152608401610506565b8580610b935760405162461bcd60e51b815260206004820152602b60248201527f5a6b426f624469726563744465706f73697451756575653a20656d707479206460448201526a195c1bdcda5d081b1a5cdd60aa1b6064820152608401610506565b6010811115610bf75760405162461bcd60e51b815260206004820152602a60248201527f5a6b426f624469726563744465706f73697451756575653a20746f6f206d616e60448201526979206465706f7369747360b01b6064820152608401610506565b6000610c0560106032611f02565b610c10906020611da9565b6001600160401b03811115610c2757610c27611901565b6040519080825280601f01601f191660200182016040528015610c51576020820181803683370190505b509050610c5f82603a611f02565b610c6a906004611da9565b6001600160401b03811115610c8157610c81611901565b6040519080825280601f01601f191660200182016040528015610cab576020820181803683370190505b509250866020820152600160e01b8260f81b176020840152600095506000945060005b82811015610e075760008a8a83818110610cea57610cea611d7d565b6020908102929092013560008181526002938490526040902092830154600180850154929550909250600160b01b820460b01b916001600160401b0380821692600160401b830490911691600160a81b900460ff1690816003811115610d5257610d52611b6c565b14610d6f5760405162461bcd60e51b815260040161050690611e86565b6032880289016040810185905260528101849052604a0185905260c087901b603a89028c016024810191909152602c8101859052603e810184905260360185905260018601805460ff60a81b1916600160a91b179055610dd86001600160401b0384168f611da9565b9d50610ded6001600160401b0383168e611da9565b9c505050505050505080610e0090611e1e565b9050610cce565b5080516020820120610e3a907f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000190611f37565b9350610eb3336103e87f0000000000000000000000000000000000000000000000000000000000000000610e6e898b611da9565b610e789190611f02565b610e829190611f4b565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190611609565b7f6158333d85f7dbce81f21c5dfee08ec3a6b81728f0f8ae2f329a8dcb0eac2b608989604051610ee4929190611f5f565b60405180910390a1505093509350935093565b610eff611565565b6001600160a01b038116610f645760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610506565b610f6d816115b9565b50565b6001600160a01b03163b151590565b6040516001600160a01b0380851660248301528316604482015260648101829052610fea9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611639565b50505050565b60006001600160a01b03841661105f5760405162461bcd60e51b815260206004820152602e60248201527f5a6b426f624469726563744465706f73697451756575653a2066616c6c62616360448201526d6b2075736572206973207a65726f60901b6064820152608401610506565b60035464010000000090046001600160401b031660006103e86110a27f000000000000000000000000000000000000000000000000000000000000000087611f4b565b6110ac9190611f02565b9050816001600160401b0316816001600160401b0316116111355760405162461bcd60e51b815260206004820152603960248201527f5a6b426f624469726563744465706f73697451756575653a206469726563742060448201527f6465706f73697420616d6f756e7420697320746f6f206c6f77000000000000006064820152608401610506565b60405163a7ac5aed60e01b815290829003906000907343830a424783657b92913bef78ec839d2085fcf99063a7ac5aed906111969088907f000000000000000000000000000000000000000000000000000000000000000090600401611f9b565b6040805180830381865af41580156111b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111d69190611fc2565b90506000604051806101000160405280896001600160a01b03168152602001886001600160601b03168152602001846001600160401b03168152602001856001600160401b031681526020014264ffffffffff1681526020016001600381111561124257611242611b6c565b815283516001600160b01b0319166020808301919091528401516040909101526003805491925063ffffffff90911690600061127d83612026565b825463ffffffff9182166101009390930a928302928202191691909117909155166000818152600260209081526040918290208451918501516001600160601b0316600160a01b026001600160a01b03909216919091178155908301516001820180546060860151608087015164ffffffffff16600160801b0264ffffffffff60801b196001600160401b03928316600160401b026fffffffffffffffffffffffffffffffff199094169290951691909117919091179283168117825560a086015194995085949260ff60a81b1990911665ffffffffffff60801b1990911617600160a81b83600381111561137457611374611b6c565b021790555060c082015160018201805460b09290921c600160b01b026001600160b01b0390921691909117905560e090910151600290910155604051631cbec71160e01b81526001600160a01b038a811660048301526001600160401b03851660248301527f00000000000000000000000000000000000000000000000000000000000000001690631cbec71190604401600060405180830381600087803b15801561141f57600080fd5b505af1158015611433573d6000803e3d6000fd5b5050604080516001600160a01b038c8116825286516001600160b01b031916602080840191909152870151828401526001600160401b03881660608301529151899450918d1692507fcde1b1a4bd18b6b8ddb2a80b1fce51c4eee01748267692ac6bc0770a84bc6c58919081900360800190a350505050949350505050565b60018101805460ff60a81b1916600360a81b17905580546001600160a01b0380821691600160a01b90046001600160601b031690611513907f0000000000000000000000000000000000000000000000000000000000000000168383611609565b604080516001600160a01b03841681526001600160601b038316602082015285917fb0cf2923048b0f1ffd594948402295be48a7de9d3484175e13a2cd4de8650a8c910160405180910390a250505050565b61156d61170b565b6105a75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610506565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516001600160a01b0383166024820152604481018290526109d390849063a9059cbb60e01b90606401610fb3565b600061168e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166117509092919063ffffffff16565b8051909150156109d357808060200190518101906116ac9190611d5b565b6109d35760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610506565b600061171561175f565b8061174b57507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035433905b6001600160a01b0316145b905090565b60606103c68484600085611773565b6000805433906001600160a01b0316611740565b6060824710156117d45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610506565b600080866001600160a01b031685876040516117f09190612049565b60006040518083038185875af1925050503d806000811461182d576040519150601f19603f3d011682016040523d82523d6000602084013e611832565b606091505b50915091506118438783838761184e565b979650505050505050565b606083156118bd5782516000036118b6576001600160a01b0385163b6118b65760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610506565b50816103c6565b6103c683838151156118d25781518083602001fd5b8060405162461bcd60e51b81526004016105069190612065565b6001600160a01b0381168114610f6d57600080fd5b634e487b7160e01b600052604160045260246000fd5b600082601f83011261192857600080fd5b81356001600160401b038082111561194257611942611901565b604051601f8301601f19908116603f0116810190828211818310171561196a5761196a611901565b8160405283815286602085880101111561198357600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156119b857600080fd5b83356119c3816118ec565b92506020840135915060408401356001600160401b038111156119e557600080fd5b6119f186828701611917565b9150509250925092565b60008083601f840112611a0d57600080fd5b5081356001600160401b03811115611a2457600080fd5b6020830191508360208260051b8501011115611a3f57600080fd5b9250929050565b60008060208385031215611a5957600080fd5b82356001600160401b03811115611a6f57600080fd5b611a7b858286016119fb565b90969095509350505050565b60008083601f840112611a9957600080fd5b5081356001600160401b03811115611ab057600080fd5b602083019150836020828501011115611a3f57600080fd5b60008060008060608587031215611ade57600080fd5b8435611ae9816118ec565b93506020850135925060408501356001600160401b03811115611b0b57600080fd5b611b1787828801611a87565b95989497509550505050565b600060208284031215611b3557600080fd5b81356001600160401b0381168114611b4c57600080fd5b9392505050565b600060208284031215611b6557600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60048110611ba057634e487b7160e01b600052602160045260246000fd5b9052565b60006101008201905060018060a01b0383511682526001600160601b03602084015116602083015260408301516001600160401b03808216604085015280606086015116606085015250506080830151611c07608084018264ffffffffff169052565b5060a0830151611c1a60a0840182611b82565b5060c0830151611c3660c08401826001600160b01b0319169052565b5060e092830151919092015290565b600060208284031215611c5757600080fd5b8135611b4c816118ec565b600060208284031215611c7457600080fd5b813564ffffffffff81168114611b4c57600080fd5b600080600060408486031215611c9e57600080fd5b83356001600160401b03811115611cb457600080fd5b611cc0868287016119fb565b909790965060209590950135949350505050565b60005b83811015611cef578181015183820152602001611cd7565b83811115610fea5750506000910152565b60008151808452611d18816020860160208601611cd4565b601f01601f19169290920160200192915050565b848152836020820152826040820152608060608201526000611d516080830184611d00565b9695505050505050565b600060208284031215611d6d57600080fd5b81518015158114611b4c57600080fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115611dbc57611dbc611d93565b500190565b6020808252603a908201527f5a6b426f624469726563744465706f73697451756575653a206469726563742060408201527f6465706f7369742074696d656f7574206e6f7420706173736564000000000000606082015260800190565b600060018201611e3057611e30611d93565b5060010190565b60008060408385031215611e4a57600080fd5b8235611e55816118ec565b915060208301356001600160401b03811115611e7057600080fd5b611e7c85828601611917565b9150509250929050565b60208082526033908201527f5a6b426f624469726563744465706f73697451756575653a20646972656374206040820152726465706f736974206e6f742070656e64696e6760681b606082015260800190565b600064ffffffffff808316818516808303821115611ef957611ef9611d93565b01949350505050565b6000816000190483118215151615611f1c57611f1c611d93565b500290565b634e487b7160e01b600052601260045260246000fd5b600082611f4657611f46611f21565b500690565b600082611f5a57611f5a611f21565b500490565b6020808252810182905260006001600160fb1b03831115611f7f57600080fd5b8260051b80856040850137600092016040019182525092915050565b604081526000611fae6040830185611d00565b905062ffffff831660208301529392505050565b600060408284031215611fd457600080fd5b604051604081018181106001600160401b0382111715611ff657611ff6611901565b60405282516001600160b01b03198116811461201157600080fd5b81526020928301519281019290925250919050565b600063ffffffff80831681810361203f5761203f611d93565b6001019392505050565b6000825161205b818460208701611cd4565b9190910192915050565b602081526000611b4c6020830184611d0056fea2646970667358221220535d4f5036b94d1956cb3053c529504549419788827829ed4890cec6fbca72d264736f6c634300080f003300000000000000000000000072e6b59d4a90ab232e55d4bb7ed2dd17494d62fb0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061012c5760003560e01c8063a4c0ed36116100ad578063d7f59caa11610071578063d7f59caa14610300578063dc3ba6a314610313578063e24546f214610326578063f2fde38b14610349578063fc0c546a1461035c57600080fd5b8063a4c0ed3614610257578063b130603e1461027a578063b85369e6146102a8578063c278b761146102cd578063c41100fa146102ed57600080fd5b80636918822d116100f45780636918822d146101f1578063715018a61461020457806380a328921461020c5780638da5cb5b1461021f5780639d8ad6e41461023057600080fd5b806302592d371461013157806316f0115b146101575780632f84c96f1461019657806335d3cbcc146101a957806368dc1c55146101dc575b600080fd5b61014461013f3660046119a3565b610383565b6040519081526020015b60405180910390f35b61017e7f00000000000000000000000072e6b59d4a90ab232e55d4bb7ed2dd17494d62fb81565b6040516001600160a01b03909116815260200161014e565b60015461017e906001600160a01b031681565b6003546101c49064010000000090046001600160401b031681565b6040516001600160401b03909116815260200161014e565b6101ef6101ea366004611a46565b6103ce565b005b6101446101ff366004611ac8565b610549565b6101ef610595565b6101ef61021a366004611b23565b6105a9565b6000546001600160a01b031661017e565b6101447f000000000000000000000000000000000000000000000000000000000000000081565b61026a610265366004611ac8565b610615565b604051901515815260200161014e565b60035461029290600160601b900464ffffffffff1681565b60405164ffffffffff909116815260200161014e565b6003546102b89063ffffffff1681565b60405163ffffffff909116815260200161014e565b6102e06102db366004611b53565b6106d0565b60405161014e9190611ba4565b6101ef6102fb366004611c45565b6107ef565b6101ef61030e366004611b53565b6108b4565b6101ef610321366004611c62565b6109d8565b610339610334366004611c89565b610aa3565b60405161014e9493929190611d2c565b6101ef610357366004611c45565b610ef7565b61017e7f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417481565b60006103ba6001600160a01b037f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417416333086610f7f565b6103c633858585610ff0565b949350505050565b6001546040516336b87bd760e11b81523360048201526000916001600160a01b031690636d70f7ae90602401602060405180830381865afa158015610417573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043b9190611d5b565b600354909150600160601b900464ffffffffff1660005b838110156105425760006002600087878581811061047257610472611d7d565b90506020020135815260200190815260200160002090506001600381111561049c5761049c611b6c565b6001820154600160a81b900460ff1660038111156104bc576104bc611b6c565b036105315783806104ea5750600181015442906104e8908590600160801b900464ffffffffff16611da9565b105b61050f5760405162461bcd60e51b815260040161050690611dc1565b60405180910390fd5b61053186868481811061052457610524611d7d565b90506020020135826114b2565b5061053b81611e1e565b9050610452565b5050505050565b600061058c858585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061038392505050565b95945050505050565b61059d611565565b6105a760006115b9565b565b6105b1611565565b600380546bffffffffffffffff0000000019166401000000006001600160401b038416908102919091179091556040519081527f4fc5798183ecfb36b62f43c657e712d8b6e8661646d3c90bd3a5202335203180906020015b60405180910390a150565b6000336001600160a01b037f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417416146106a35760405162461bcd60e51b815260206004820152602b60248201527f5a6b426f624469726563744465706f73697451756575653a206e6f742061207460448201526a37b5b2b71031b0b63632b960a91b6064820152608401610506565b6000806106b284860186611e37565b915091506106c287838884610ff0565b506001979650505050505050565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915260008281526002602090815260409182902082516101008101845281546001600160a01b0381168252600160a01b90046001600160601b03169281019290925260018101546001600160401b0380821694840194909452600160401b81049093166060830152600160801b830464ffffffffff166080830152909160a0830190600160a81b900460ff1660038111156107ac576107ac611b6c565b60038111156107bd576107bd611b6c565b81526001820154600160b01b900460b01b6001600160b01b031916602082015260029091015460409091015292915050565b6107f7611565565b6001600160a01b0381166108665760405162461bcd60e51b815260206004820152603060248201527f5a6b426f624469726563744465706f73697451756575653a206d616e6167657260448201526f206973207a65726f206164647265737360801b6064820152608401610506565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f267052ecaebdd552dc1b20904f59d83d51ae7add7514165322a7da9ef6cf543b9060200161060a565b6001546040516336b87bd760e11b81523360048201526000916001600160a01b031690636d70f7ae90602401602060405180830381865afa1580156108fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109219190611d5b565b6000838152600260205260409020909150600180820154600160a81b900460ff16600381111561095357610953611b6c565b146109705760405162461bcd60e51b815260040161050690611e86565b81806109ad5750600354600182015442916109a49164ffffffffff600160601b909204821691600160801b90910416611ed9565b64ffffffffff16105b6109c95760405162461bcd60e51b815260040161050690611dc1565b6109d383826114b2565b505050565b6109e0611565565b62093a808164ffffffffff161115610a4d5760405162461bcd60e51b815260206004820152602a60248201527f5a6b426f624469726563744465706f73697451756575653a2074696d656f757460448201526920746f6f206c6172676560b01b6064820152608401610506565b6003805464ffffffffff60601b1916600160601b64ffffffffff8416908102919091179091556040519081527f237f465c227da0b7fcd48ae7b5e7ec9d2ee347abbf6c93b008a616220d06ee399060200161060a565b600080806060336001600160a01b037f00000000000000000000000072e6b59d4a90ab232e55d4bb7ed2dd17494d62fb1614610b315760405162461bcd60e51b815260206004820152602760248201527f5a6b426f624469726563744465706f73697451756575653a20696e76616c69646044820152661031b0b63632b960c91b6064820152608401610506565b8580610b935760405162461bcd60e51b815260206004820152602b60248201527f5a6b426f624469726563744465706f73697451756575653a20656d707479206460448201526a195c1bdcda5d081b1a5cdd60aa1b6064820152608401610506565b6010811115610bf75760405162461bcd60e51b815260206004820152602a60248201527f5a6b426f624469726563744465706f73697451756575653a20746f6f206d616e60448201526979206465706f7369747360b01b6064820152608401610506565b6000610c0560106032611f02565b610c10906020611da9565b6001600160401b03811115610c2757610c27611901565b6040519080825280601f01601f191660200182016040528015610c51576020820181803683370190505b509050610c5f82603a611f02565b610c6a906004611da9565b6001600160401b03811115610c8157610c81611901565b6040519080825280601f01601f191660200182016040528015610cab576020820181803683370190505b509250866020820152600160e01b8260f81b176020840152600095506000945060005b82811015610e075760008a8a83818110610cea57610cea611d7d565b6020908102929092013560008181526002938490526040902092830154600180850154929550909250600160b01b820460b01b916001600160401b0380821692600160401b830490911691600160a81b900460ff1690816003811115610d5257610d52611b6c565b14610d6f5760405162461bcd60e51b815260040161050690611e86565b6032880289016040810185905260528101849052604a0185905260c087901b603a89028c016024810191909152602c8101859052603e810184905260360185905260018601805460ff60a81b1916600160a91b179055610dd86001600160401b0384168f611da9565b9d50610ded6001600160401b0383168e611da9565b9c505050505050505080610e0090611e1e565b9050610cce565b5080516020820120610e3a907f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000190611f37565b9350610eb3336103e87f0000000000000000000000000000000000000000000000000000000000000001610e6e898b611da9565b610e789190611f02565b610e829190611f4b565b6001600160a01b037f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174169190611609565b7f6158333d85f7dbce81f21c5dfee08ec3a6b81728f0f8ae2f329a8dcb0eac2b608989604051610ee4929190611f5f565b60405180910390a1505093509350935093565b610eff611565565b6001600160a01b038116610f645760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610506565b610f6d816115b9565b50565b6001600160a01b03163b151590565b6040516001600160a01b0380851660248301528316604482015260648101829052610fea9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611639565b50505050565b60006001600160a01b03841661105f5760405162461bcd60e51b815260206004820152602e60248201527f5a6b426f624469726563744465706f73697451756575653a2066616c6c62616360448201526d6b2075736572206973207a65726f60901b6064820152608401610506565b60035464010000000090046001600160401b031660006103e86110a27f000000000000000000000000000000000000000000000000000000000000000187611f4b565b6110ac9190611f02565b9050816001600160401b0316816001600160401b0316116111355760405162461bcd60e51b815260206004820152603960248201527f5a6b426f624469726563744465706f73697451756575653a206469726563742060448201527f6465706f73697420616d6f756e7420697320746f6f206c6f77000000000000006064820152608401610506565b60405163a7ac5aed60e01b815290829003906000907343830a424783657b92913bef78ec839d2085fcf99063a7ac5aed906111969088907f000000000000000000000000000000000000000000000000000000000000000090600401611f9b565b6040805180830381865af41580156111b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111d69190611fc2565b90506000604051806101000160405280896001600160a01b03168152602001886001600160601b03168152602001846001600160401b03168152602001856001600160401b031681526020014264ffffffffff1681526020016001600381111561124257611242611b6c565b815283516001600160b01b0319166020808301919091528401516040909101526003805491925063ffffffff90911690600061127d83612026565b825463ffffffff9182166101009390930a928302928202191691909117909155166000818152600260209081526040918290208451918501516001600160601b0316600160a01b026001600160a01b03909216919091178155908301516001820180546060860151608087015164ffffffffff16600160801b0264ffffffffff60801b196001600160401b03928316600160401b026fffffffffffffffffffffffffffffffff199094169290951691909117919091179283168117825560a086015194995085949260ff60a81b1990911665ffffffffffff60801b1990911617600160a81b83600381111561137457611374611b6c565b021790555060c082015160018201805460b09290921c600160b01b026001600160b01b0390921691909117905560e090910151600290910155604051631cbec71160e01b81526001600160a01b038a811660048301526001600160401b03851660248301527f00000000000000000000000072e6b59d4a90ab232e55d4bb7ed2dd17494d62fb1690631cbec71190604401600060405180830381600087803b15801561141f57600080fd5b505af1158015611433573d6000803e3d6000fd5b5050604080516001600160a01b038c8116825286516001600160b01b031916602080840191909152870151828401526001600160401b03881660608301529151899450918d1692507fcde1b1a4bd18b6b8ddb2a80b1fce51c4eee01748267692ac6bc0770a84bc6c58919081900360800190a350505050949350505050565b60018101805460ff60a81b1916600360a81b17905580546001600160a01b0380821691600160a01b90046001600160601b031690611513907f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174168383611609565b604080516001600160a01b03841681526001600160601b038316602082015285917fb0cf2923048b0f1ffd594948402295be48a7de9d3484175e13a2cd4de8650a8c910160405180910390a250505050565b61156d61170b565b6105a75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610506565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516001600160a01b0383166024820152604481018290526109d390849063a9059cbb60e01b90606401610fb3565b600061168e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166117509092919063ffffffff16565b8051909150156109d357808060200190518101906116ac9190611d5b565b6109d35760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610506565b600061171561175f565b8061174b57507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035433905b6001600160a01b0316145b905090565b60606103c68484600085611773565b6000805433906001600160a01b0316611740565b6060824710156117d45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610506565b600080866001600160a01b031685876040516117f09190612049565b60006040518083038185875af1925050503d806000811461182d576040519150601f19603f3d011682016040523d82523d6000602084013e611832565b606091505b50915091506118438783838761184e565b979650505050505050565b606083156118bd5782516000036118b6576001600160a01b0385163b6118b65760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610506565b50816103c6565b6103c683838151156118d25781518083602001fd5b8060405162461bcd60e51b81526004016105069190612065565b6001600160a01b0381168114610f6d57600080fd5b634e487b7160e01b600052604160045260246000fd5b600082601f83011261192857600080fd5b81356001600160401b038082111561194257611942611901565b604051601f8301601f19908116603f0116810190828211818310171561196a5761196a611901565b8160405283815286602085880101111561198357600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156119b857600080fd5b83356119c3816118ec565b92506020840135915060408401356001600160401b038111156119e557600080fd5b6119f186828701611917565b9150509250925092565b60008083601f840112611a0d57600080fd5b5081356001600160401b03811115611a2457600080fd5b6020830191508360208260051b8501011115611a3f57600080fd5b9250929050565b60008060208385031215611a5957600080fd5b82356001600160401b03811115611a6f57600080fd5b611a7b858286016119fb565b90969095509350505050565b60008083601f840112611a9957600080fd5b5081356001600160401b03811115611ab057600080fd5b602083019150836020828501011115611a3f57600080fd5b60008060008060608587031215611ade57600080fd5b8435611ae9816118ec565b93506020850135925060408501356001600160401b03811115611b0b57600080fd5b611b1787828801611a87565b95989497509550505050565b600060208284031215611b3557600080fd5b81356001600160401b0381168114611b4c57600080fd5b9392505050565b600060208284031215611b6557600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60048110611ba057634e487b7160e01b600052602160045260246000fd5b9052565b60006101008201905060018060a01b0383511682526001600160601b03602084015116602083015260408301516001600160401b03808216604085015280606086015116606085015250506080830151611c07608084018264ffffffffff169052565b5060a0830151611c1a60a0840182611b82565b5060c0830151611c3660c08401826001600160b01b0319169052565b5060e092830151919092015290565b600060208284031215611c5757600080fd5b8135611b4c816118ec565b600060208284031215611c7457600080fd5b813564ffffffffff81168114611b4c57600080fd5b600080600060408486031215611c9e57600080fd5b83356001600160401b03811115611cb457600080fd5b611cc0868287016119fb565b909790965060209590950135949350505050565b60005b83811015611cef578181015183820152602001611cd7565b83811115610fea5750506000910152565b60008151808452611d18816020860160208601611cd4565b601f01601f19169290920160200192915050565b848152836020820152826040820152608060608201526000611d516080830184611d00565b9695505050505050565b600060208284031215611d6d57600080fd5b81518015158114611b4c57600080fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115611dbc57611dbc611d93565b500190565b6020808252603a908201527f5a6b426f624469726563744465706f73697451756575653a206469726563742060408201527f6465706f7369742074696d656f7574206e6f7420706173736564000000000000606082015260800190565b600060018201611e3057611e30611d93565b5060010190565b60008060408385031215611e4a57600080fd5b8235611e55816118ec565b915060208301356001600160401b03811115611e7057600080fd5b611e7c85828601611917565b9150509250929050565b60208082526033908201527f5a6b426f624469726563744465706f73697451756575653a20646972656374206040820152726465706f736974206e6f742070656e64696e6760681b606082015260800190565b600064ffffffffff808316818516808303821115611ef957611ef9611d93565b01949350505050565b6000816000190483118215151615611f1c57611f1c611d93565b500290565b634e487b7160e01b600052601260045260246000fd5b600082611f4657611f46611f21565b500690565b600082611f5a57611f5a611f21565b500490565b6020808252810182905260006001600160fb1b03831115611f7f57600080fd5b8260051b80856040850137600092016040019182525092915050565b604081526000611fae6040830185611d00565b905062ffffff831660208301529392505050565b600060408284031215611fd457600080fd5b604051604081018181106001600160401b0382111715611ff657611ff6611901565b60405282516001600160b01b03198116811461201157600080fd5b81526020928301519281019290925250919050565b600063ffffffff80831681810361203f5761203f611d93565b6001019392505050565b6000825161205b818460208701611cd4565b9190910192915050565b602081526000611b4c6020830184611d0056fea2646970667358221220535d4f5036b94d1956cb3053c529504549419788827829ed4890cec6fbca72d264736f6c634300080f0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000072e6b59d4a90ab232e55d4bb7ed2dd17494d62fb0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : _pool (address): 0x72e6B59D4a90ab232e55D4BB7ed2dD17494D62fB
Arg [1] : _token (address): 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174
Arg [2] : _denominator (uint256): 1
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000072e6b59d4a90ab232e55d4bb7ed2dd17494d62fb
Arg [1] : 0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in POL
Multichain Portfolio | 32 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.