Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
DishonestWork
Compiler Version
v0.8.27+commit.40a35a09
Optimization Enabled:
Yes with 10000 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.27;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@balancer-labs/v2-interfaces/contracts/vault/IVault.sol";
import "@balancer-labs/v2-interfaces/contracts/vault/IFlashLoanRecipient.sol";
import "@balancer-labs/v2-interfaces/contracts/solidity-utils/misc/IWETH.sol";
import "./IHonestWork.sol";
/**
* @title DishonestWork
* @notice A helper smart contract to assist/cheat with Honest Work by @0xShiroi tasks.
* @author Yigit Duman (@yigitduman)
* @custom:version v5
* @custom:changelog Added utility functions to aid off-chain tools, added events, updated documentation.
*/
contract DishonestWork is Ownable(msg.sender), IFlashLoanRecipient {
IHonestWork public honestWork;
IWETH public weth;
/// @notice Addresses for various deposit locations
address public beef;
address public babe;
address public deaf;
address public dead;
address public face;
address public feed;
address public fed;
address public bad;
/// @notice Address that can withdraw orphaned assets
/// @dev Can only withdraw assets with no associated owner
address public withdrawAddress;
/// @notice Balancer vault interface for flashloans
IVault private vault;
/// @notice Mapping of token IDs to their original depositors
/// @dev Used to track ownership for withdrawal permissions
mapping(uint256 => address) public ownerMap;
/**
* @notice Modifier to restrict access to withdraw address
* @dev Used for emergency withdrawal functions and withdraw address management
*/
modifier onlyWithdrawAddress() {
require(msg.sender == withdrawAddress, "Only withdraw address");
_;
}
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
/**
* @notice Emitted when a deposit is made to any special address
* @param tokenId The ID of the deposited token
* @param depositor The address that deposited the token
* @param destination The address where the token was deposited
*/
event TokenDeposited(uint256 indexed tokenId, address indexed depositor, address indexed destination);
/**
* @notice Emitted when a withdrawal is made from any special address
* @param tokenId The ID of the withdrawn token
* @param withdrawer The address that withdrew the token
* @param source The address from where the token was withdrawn
*/
event TokenWithdrawn(uint256 indexed tokenId, address indexed withdrawer, address indexed source);
/*//////////////////////////////////////////////////////////////
INITIALIZATION
//////////////////////////////////////////////////////////////*/
/**
* @notice Initializes the contract with required addresses
* @param _honestWork Address of the HonestWork contract
* @param _withdrawAddress Address that can withdraw orphaned assets
* @param _vault Address of the Balancer vault for flashloans
*/
constructor(IHonestWork _honestWork, address _withdrawAddress, address _vault) {
require(address(_honestWork) != address(0), "Invalid HonestWork address");
require(_withdrawAddress != address(0), "Invalid withdraw address");
require(_vault != address(0), "Invalid vault address");
honestWork = _honestWork;
withdrawAddress = _withdrawAddress;
vault = IVault(_vault);
weth = vault.WETH();
}
/*//////////////////////////////////////////////////////////////
INTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////*/
/**
* @notice Internal function to deposit an Honest Work token to a specific address
* @dev Only works after ownership is renounced to prevent unauthorized deposits
* @param tokenId ID of the token to deposit
* @param destination Target address for the deposit
* @param msgSender Address of the sender
* @custom:security Requires ownership renouncement
*/
function deposit(uint256 tokenId, address destination, address msgSender) internal {
if (owner() != address(0)) {
revert("Deposit functions do not work before ownership is renounced");
}
honestWork.transferFrom(msgSender, destination, tokenId);
ownerMap[tokenId] = msgSender;
emit TokenDeposited(tokenId, msgSender, destination);
}
/**
* @notice Internal function to withdraw Honest Work from a specific address
* @dev Only original depositor can withdraw
* @param tokenId ID of the token to withdraw
* @param source Address to withdraw from
* @param msgSender Address of the sender
*/
function _withdraw(uint256 tokenId, address source, address msgSender) internal {
require(ownerMap[tokenId] == msgSender, "You are not the owner");
honestWork.transferFrom(source, msgSender, tokenId);
ownerMap[tokenId] = address(0);
emit TokenWithdrawn(tokenId, msgSender, source);
}
/*//////////////////////////////////////////////////////////////
PUBLIC FUNCTIONS
//////////////////////////////////////////////////////////////*/
/**
* @notice Withdraws a token from a specific source address
* @param tokenId ID of the token to withdraw
* @param source Address to withdraw the token from
*/
function withdraw(uint256 tokenId, address source) external {
_withdraw(tokenId, source, msg.sender);
}
/**
* @notice Withdraws a token from any special address where it's currently held
* @dev Checks all possible special addresses (this, beef, babe, etc.) to find the token
* @param tokenId ID of the token to withdraw
*/
function withdraw(uint256 tokenId) public {
// Check each special address in sequence to find where the token is held
if (honestWork.ownerOf(tokenId) == address(this)) {
_withdraw(tokenId, address(this), msg.sender);
} else if (honestWork.ownerOf(tokenId) == beef) {
_withdraw(tokenId, beef, msg.sender);
} else if (honestWork.ownerOf(tokenId) == babe) {
_withdraw(tokenId, babe, msg.sender);
} else if (honestWork.ownerOf(tokenId) == deaf) {
_withdraw(tokenId, deaf, msg.sender);
} else if (honestWork.ownerOf(tokenId) == dead) {
_withdraw(tokenId, dead, msg.sender);
} else if (honestWork.ownerOf(tokenId) == face) {
_withdraw(tokenId, face, msg.sender);
} else if (honestWork.ownerOf(tokenId) == feed) {
_withdraw(tokenId, feed, msg.sender);
} else if (honestWork.ownerOf(tokenId) == fed) {
_withdraw(tokenId, fed, msg.sender);
} else if (honestWork.ownerOf(tokenId) == bad) {
_withdraw(tokenId, bad, msg.sender);
} else {
revert("Token not found in any special address");
}
}
/**
* @notice Withdraws all tokens that the caller has deposited
* @dev Uses getDepositedTokens to find all tokens owned by the caller
*/
function withdrawAll() external {
uint256[] memory tokenIds = getDepositedTokens(msg.sender);
uint256 tokenIdsLength = tokenIds.length;
if (tokenIdsLength == 0) {
revert("No tokens deposited");
}
for (uint256 i = 0; i < tokenIdsLength; i++) {
withdraw(tokenIds[i]);
}
}
/**
* @notice Deposits token to this contract
* @param tokenId ID of the token to deposit
*/
function takeAVacation(uint256 tokenId) external {
deposit(tokenId, address(this), msg.sender);
}
/**
* @notice Withdraws token previously deposited to this contract
* @param tokenId ID of the token to withdraw
*/
function backToWork(uint256 tokenId) external {
_withdraw(tokenId, address(this), msg.sender);
}
/**
* @notice Deposits token to the beef address
* @param tokenId ID of the token to deposit
*/
function startABeef(uint256 tokenId) external {
deposit(tokenId, beef, msg.sender);
}
/**
* @notice Withdraws token from the beef address
* @param tokenId ID of the token to withdraw
*/
function endYourBeef(uint256 tokenId) external {
_withdraw(tokenId, beef, msg.sender);
}
/**
* @notice Deposits token to the babe address
* @param tokenId ID of the token to deposit
*/
function callABabe(uint256 tokenId) external {
deposit(tokenId, babe, msg.sender);
}
/**
* @notice Withdraws token from the babe address
* @param tokenId ID of the token to withdraw
*/
function sayGoodbyeToBabe(uint256 tokenId) external {
_withdraw(tokenId, babe, msg.sender);
}
/**
* @notice Deposits token to the deaf address
* @param tokenId ID of the token to deposit
*/
function goRaveTurnDeaf(uint256 tokenId) external {
deposit(tokenId, deaf, msg.sender);
}
/**
* @notice Withdraws token from the deaf address
* @param tokenId ID of the token to withdraw
*/
function goToDoctorHealDeaf(uint256 tokenId) external {
_withdraw(tokenId, deaf, msg.sender);
}
/**
* @notice Deposits token to the dead address
* @param tokenId ID of the token to deposit
*/
function overdoseAndGoDead(uint256 tokenId) external {
deposit(tokenId, dead, msg.sender);
}
/**
* @notice Withdraws token from the dead address
* @param tokenId ID of the token to withdraw
*/
function shotAdrenalineNoMoreDead(uint256 tokenId) external {
_withdraw(tokenId, dead, msg.sender);
}
/**
* @notice Deposits token to the face address
* @param tokenId ID of the token to deposit
*/
function faceYourFears(uint256 tokenId) external {
deposit(tokenId, face, msg.sender);
}
/**
* @notice Withdraws token from the face address
* @param tokenId ID of the token to withdraw
*/
function turnBackWithAHappyFace(uint256 tokenId) external {
_withdraw(tokenId, face, msg.sender);
}
/**
* @notice Deposits token to the feed address
* @param tokenId ID of the token to deposit
*/
function goToAFancyRestaurantFeedYourself(uint256 tokenId) external {
deposit(tokenId, feed, msg.sender);
}
/**
* @notice Withdraws token from the feed address
* @param tokenId ID of the token to withdraw
*/
function returnHomeToFeedYourHead(uint256 tokenId) external {
_withdraw(tokenId, feed, msg.sender);
}
/**
* @notice Deposits token to the fed address
* @param tokenId ID of the token to deposit
*/
function snitchToFeds(uint256 tokenId) external {
deposit(tokenId, fed, msg.sender);
}
/**
* @notice Withdraws token from the fed address
* @param tokenId ID of the token to withdraw
*/
function returnFromFedsWithWitnessProtection(uint256 tokenId) external {
_withdraw(tokenId, fed, msg.sender);
}
/**
* @notice Deposits token to the bad address
* @param tokenId ID of the token to deposit
*/
function shillScamTokenToYourFriendsBeBad(uint256 tokenId) external {
deposit(tokenId, bad, msg.sender);
}
/**
* @notice Withdraws token from the bad address
* @param tokenId ID of the token to withdraw
*/
function putAMiladyPfpNoMoreBad(uint256 tokenId) external {
_withdraw(tokenId, bad, msg.sender);
}
/**
* @notice Transfers token to a specific address with a random chance of success
* @param probability Probability of success (0-100)
* @param to Address to transfer the token to
* @param tokenId ID of the token to transfer
*/
function makeYourOwnLuck(uint256 probability, address to, uint256 tokenId) external {
honestWork.transferFrom(msg.sender, to, tokenId);
uint256 currentProbability = uint256(keccak256(abi.encodePacked(block.timestamp, block.prevrandao))) % 100;
if (currentProbability > probability) {
revert("You are unlucky");
}
}
/**
* @notice Transfers token to a specific address
* @param to Address to transfer the token to
* @param tokenId ID of the token to transfer
*/
function makeOriginNotSender(address to, uint256 tokenId) external {
honestWork.transferFrom(msg.sender, to, tokenId);
}
/**
* @notice Transfers token to this contract and then back to the sender
* @param tokenId ID of the token to transfer
*/
function sendToAnEmptyAddress(uint256 tokenId) external {
honestWork.transferFrom(msg.sender, address(this), tokenId);
honestWork.transferFrom(address(this), msg.sender, tokenId);
}
/**
* @notice Transfers token a specific number of times
* @dev You can also use this for TWICE_WITHIN_A_BLOCK and TO_CONTRACT tasks.
* @param tokenId ID of the token to transfer
* @param times Number of times to transfer the token
*/
function transferXTimes(uint256 tokenId, uint256 times) external {
for (uint256 i = 0; i < times; i++) {
if (i % 2 == 0) {
honestWork.transferFrom(msg.sender, address(this), tokenId);
} else {
honestWork.transferFrom(address(this), msg.sender, tokenId);
}
}
if (honestWork.ownerOf(tokenId) == address(this)) {
honestWork.transferFrom(address(this), msg.sender, tokenId);
}
}
/**
* @notice Transfers token to a specific address with a password
* @param to Address to transfer the token to
* @param tokenId ID of the token to transfer
*/
function sendWithPassword(address to, uint256 tokenId) external {
honestWork.safeTransferFrom(msg.sender, to, tokenId, abi.encodePacked("password"));
}
/*//////////////////////////////////////////////////////////////
FLASH LOANS
//////////////////////////////////////////////////////////////*/
/**
* @notice Performs a flashloan-assisted token transfer
* @param tokenId ID of the token to transfer
* @param ethAmount Amount of ETH to flashloan
*/
function sendWithFakeRolex(uint256 tokenId, uint256 ethAmount) external {
IERC20[] memory tokens = new IERC20[](1);
tokens[0] = weth;
uint256[] memory amounts = new uint256[](1);
amounts[0] = ethAmount;
bytes memory userData = abi.encode(msg.sender, tokenId);
deposit(tokenId, address(this), msg.sender);
vault.flashLoan(this, tokens, amounts, userData);
}
/**
* @notice Callback function for Balancer flashloan
* @dev Only callable by Balancer vault
* @param amounts Array of amounts for each token
* @param userData Encoded sender address and tokenId
*/
function receiveFlashLoan(
IERC20[] memory,
uint256[] memory amounts,
uint256[] memory,
bytes memory userData
)
external
override
{
require(msg.sender == address(vault));
(address sender, uint256 tokenId) = abi.decode(userData, (address, uint256));
weth.withdraw(amounts[0]);
_withdraw(tokenId, address(this), sender);
weth.deposit{ value: amounts[0] }();
weth.transfer(address(vault), amounts[0]);
}
/**
* @dev Prevents direct ETH transfers except from vault or WETH
*/
fallback() external {
if (msg.sender != address(vault) && msg.sender != address(weth)) {
revert("You can't send ETH to this contract!");
}
}
/**
* @dev Prevents direct ETH transfers except from vault or WETH
*/
receive() external payable {
if (msg.sender != address(vault) && msg.sender != address(weth)) {
revert("You can't send ETH to this contract!");
}
}
/*//////////////////////////////////////////////////////////////
OWNER FUNCTIONS
//////////////////////////////////////////////////////////////*/
/**
* @notice Sets addresses for various deposit locations
* @dev Only callable by contract owner
* @param _beef Address for beef-related deposits
* @param _babe Address for babe-related deposits
* @param _deaf Address for deaf-related deposits
* @param _dead Address for dead-related deposits
* @param _face Address for face-related deposits
* @param _feed Address for feed-related deposits
* @param _fed Address for fed-related deposits
* @param _bad Address for bad-related deposits
*/
function setAddresses(
address _beef,
address _babe,
address _deaf,
address _dead,
address _face,
address _feed,
address _fed,
address _bad
)
external
onlyOwner
{
beef = _beef;
babe = _babe;
deaf = _deaf;
dead = _dead;
face = _face;
feed = _feed;
fed = _fed;
bad = _bad;
}
/**
* @notice Updates the withdraw address
* @dev Only callable by current withdraw address
* @param _newAddress New address to set as withdraw address
*/
function setWithdrawAddress(address _newAddress) external onlyWithdrawAddress {
withdrawAddress = _newAddress;
}
/**
* @notice Withdraws any ETH in the contract
* @dev Only callable by withdraw address, emergency function
*/
function withdrawEth() external onlyWithdrawAddress {
payable(withdrawAddress).transfer(address(this).balance);
}
/**
* @notice Withdraws any ERC20 tokens in the contract
* @dev Only callable by withdraw address, emergency function
* @param erc20 Address of the ERC20 token to withdraw
*/
function withdrawErc20(IERC20 erc20) external onlyWithdrawAddress {
erc20.transfer(withdrawAddress, erc20.balanceOf(address(this)));
}
/**
* @notice Withdraws orphaned NFTs to the withdraw address
* @dev Can only withdraw NFTs that have no associated owner
* @param erc721 Address of the NFT contract
* @param tokenId ID of the NFT to withdraw
*/
function withdrawErc721(IERC721 erc721, uint256 tokenId) external onlyWithdrawAddress {
if (erc721 == honestWork) {
require(ownerMap[tokenId] == address(0), "Owner exists");
}
erc721.transferFrom(address(this), withdrawAddress, tokenId);
}
/*//////////////////////////////////////////////////////////////
UTILITY FUNCTIONS
//////////////////////////////////////////////////////////////*/
/**
* @notice Returns all token IDs deposited to this contract and other special addresses
* @dev This function is intended to be used off-chain and not optimized.
* @return Array of all token IDs
*/
function getAllDepositedTokens() public view returns (uint256[] memory, address[] memory) {
address[9] memory addresses = [address(this), babe, deaf, dead, face, feed, fed, bad, beef];
// Get total length
uint256 totalLength;
for (uint256 i = 0; i < addresses.length; i++) {
totalLength += honestWork.tokensOf(addresses[i]).length;
}
uint256[] memory allTokens = new uint256[](totalLength);
address[] memory owners = new address[](totalLength);
uint256 index;
// Copy tokens from each address
for (uint256 i = 0; i < addresses.length; i++) {
uint256[] memory tokens = honestWork.tokensOf(addresses[i]);
for (uint256 j = 0; j < tokens.length; j++) {
allTokens[index] = tokens[j];
owners[index] = addresses[i];
index++;
}
}
return (allTokens, owners);
}
/**
* @notice Returns all token IDs deposited to a specific address
* @dev This function is intended to be used off-chain and not optimized.
* @param user Address to check
* @return Array of token IDs
*/
function getDepositedTokens(address user) public view returns (uint256[] memory) {
(uint256[] memory allDepositedTokens,) = getAllDepositedTokens();
// First count matching tokens
uint256 count = 0;
for (uint256 i = 0; i < allDepositedTokens.length; i++) {
if (ownerMap[allDepositedTokens[i]] == user) {
count++;
}
}
// Create fixed-size array and populate it
uint256[] memory depositedTokens = new uint256[](count);
uint256 index = 0;
for (uint256 i = 0; i < allDepositedTokens.length; i++) {
if (ownerMap[allDepositedTokens[i]] == user) {
depositedTokens[index] = allDepositedTokens[i];
index++;
}
}
return depositedTokens;
}
}// 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: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma experimental ABIEncoderV2;
import "../solidity-utils/openzeppelin/IERC20.sol";
import "../solidity-utils/helpers/IAuthentication.sol";
import "../solidity-utils/helpers/ISignaturesValidator.sol";
import "../solidity-utils/helpers/ITemporarilyPausable.sol";
import "../solidity-utils/misc/IWETH.sol";
import "./IAsset.sol";
import "./IAuthorizer.sol";
import "./IFlashLoanRecipient.sol";
import "./IProtocolFeesCollector.sol";
pragma solidity >=0.7.0 <0.9.0;
/**
* @dev Full external interface for the Vault core contract - no external or public methods exist in the contract that
* don't override one of these declarations.
*/
interface IVault is ISignaturesValidator, ITemporarilyPausable, IAuthentication {
// Generalities about the Vault:
//
// - Whenever documentation refers to 'tokens', it strictly refers to ERC20-compliant token contracts. Tokens are
// transferred out of the Vault by calling the `IERC20.transfer` function, and transferred in by calling
// `IERC20.transferFrom`. In these cases, the sender must have previously allowed the Vault to use their tokens by
// calling `IERC20.approve`. The only deviation from the ERC20 standard that is supported is functions not returning
// a boolean value: in these scenarios, a non-reverting call is assumed to be successful.
//
// - All non-view functions in the Vault are non-reentrant: calling them while another one is mid-execution (e.g.
// while execution control is transferred to a token contract during a swap) will result in a revert. View
// functions can be called in a re-reentrant way, but doing so might cause them to return inconsistent results.
// Contracts calling view functions in the Vault must make sure the Vault has not already been entered.
//
// - View functions revert if referring to either unregistered Pools, or unregistered tokens for registered Pools.
// Authorizer
//
// Some system actions are permissioned, like setting and collecting protocol fees. This permissioning system exists
// outside of the Vault in the Authorizer contract: the Vault simply calls the Authorizer to check if the caller
// can perform a given action.
/**
* @dev Returns the Vault's Authorizer.
*/
function getAuthorizer() external view returns (IAuthorizer);
/**
* @dev Sets a new Authorizer for the Vault. The caller must be allowed by the current Authorizer to do this.
*
* Emits an `AuthorizerChanged` event.
*/
function setAuthorizer(IAuthorizer newAuthorizer) external;
/**
* @dev Emitted when a new authorizer is set by `setAuthorizer`.
*/
event AuthorizerChanged(IAuthorizer indexed newAuthorizer);
// Relayers
//
// Additionally, it is possible for an account to perform certain actions on behalf of another one, using their
// Vault ERC20 allowance and Internal Balance. These accounts are said to be 'relayers' for these Vault functions,
// and are expected to be smart contracts with sound authentication mechanisms. For an account to be able to wield
// this power, two things must occur:
// - The Authorizer must grant the account the permission to be a relayer for the relevant Vault function. This
// means that Balancer governance must approve each individual contract to act as a relayer for the intended
// functions.
// - Each user must approve the relayer to act on their behalf.
// This double protection means users cannot be tricked into approving malicious relayers (because they will not
// have been allowed by the Authorizer via governance), nor can malicious relayers approved by a compromised
// Authorizer or governance drain user funds, since they would also need to be approved by each individual user.
/**
* @dev Returns true if `user` has approved `relayer` to act as a relayer for them.
*/
function hasApprovedRelayer(address user, address relayer) external view returns (bool);
/**
* @dev Allows `relayer` to act as a relayer for `sender` if `approved` is true, and disallows it otherwise.
*
* Emits a `RelayerApprovalChanged` event.
*/
function setRelayerApproval(
address sender,
address relayer,
bool approved
) external;
/**
* @dev Emitted every time a relayer is approved or disapproved by `setRelayerApproval`.
*/
event RelayerApprovalChanged(address indexed relayer, address indexed sender, bool approved);
// Internal Balance
//
// Users can deposit tokens into the Vault, where they are allocated to their Internal Balance, and later
// transferred or withdrawn. It can also be used as a source of tokens when joining Pools, as a destination
// when exiting them, and as either when performing swaps. This usage of Internal Balance results in greatly reduced
// gas costs when compared to relying on plain ERC20 transfers, leading to large savings for frequent users.
//
// Internal Balance management features batching, which means a single contract call can be used to perform multiple
// operations of different kinds, with different senders and recipients, at once.
/**
* @dev Returns `user`'s Internal Balance for a set of tokens.
*/
function getInternalBalance(address user, IERC20[] memory tokens) external view returns (uint256[] memory);
/**
* @dev Performs a set of user balance operations, which involve Internal Balance (deposit, withdraw or transfer)
* and plain ERC20 transfers using the Vault's allowance. This last feature is particularly useful for relayers, as
* it lets integrators reuse a user's Vault allowance.
*
* For each operation, if the caller is not `sender`, it must be an authorized relayer for them.
*/
function manageUserBalance(UserBalanceOp[] memory ops) external payable;
/**
* @dev Data for `manageUserBalance` operations, which include the possibility for ETH to be sent and received
without manual WETH wrapping or unwrapping.
*/
struct UserBalanceOp {
UserBalanceOpKind kind;
IAsset asset;
uint256 amount;
address sender;
address payable recipient;
}
// There are four possible operations in `manageUserBalance`:
//
// - DEPOSIT_INTERNAL
// Increases the Internal Balance of the `recipient` account by transferring tokens from the corresponding
// `sender`. The sender must have allowed the Vault to use their tokens via `IERC20.approve()`.
//
// ETH can be used by passing the ETH sentinel value as the asset and forwarding ETH in the call: it will be wrapped
// and deposited as WETH. Any ETH amount remaining will be sent back to the caller (not the sender, which is
// relevant for relayers).
//
// Emits an `InternalBalanceChanged` event.
//
//
// - WITHDRAW_INTERNAL
// Decreases the Internal Balance of the `sender` account by transferring tokens to the `recipient`.
//
// ETH can be used by passing the ETH sentinel value as the asset. This will deduct WETH instead, unwrap it and send
// it to the recipient as ETH.
//
// Emits an `InternalBalanceChanged` event.
//
//
// - TRANSFER_INTERNAL
// Transfers tokens from the Internal Balance of the `sender` account to the Internal Balance of `recipient`.
//
// Reverts if the ETH sentinel value is passed.
//
// Emits an `InternalBalanceChanged` event.
//
//
// - TRANSFER_EXTERNAL
// Transfers tokens from `sender` to `recipient`, using the Vault's ERC20 allowance. This is typically used by
// relayers, as it lets them reuse a user's Vault allowance.
//
// Reverts if the ETH sentinel value is passed.
//
// Emits an `ExternalBalanceTransfer` event.
enum UserBalanceOpKind { DEPOSIT_INTERNAL, WITHDRAW_INTERNAL, TRANSFER_INTERNAL, TRANSFER_EXTERNAL }
/**
* @dev Emitted when a user's Internal Balance changes, either from calls to `manageUserBalance`, or through
* interacting with Pools using Internal Balance.
*
* Because Internal Balance works exclusively with ERC20 tokens, ETH deposits and withdrawals will use the WETH
* address.
*/
event InternalBalanceChanged(address indexed user, IERC20 indexed token, int256 delta);
/**
* @dev Emitted when a user's Vault ERC20 allowance is used by the Vault to transfer tokens to an external account.
*/
event ExternalBalanceTransfer(IERC20 indexed token, address indexed sender, address recipient, uint256 amount);
// Pools
//
// There are three specialization settings for Pools, which allow for cheaper swaps at the cost of reduced
// functionality:
//
// - General: no specialization, suited for all Pools. IGeneralPool is used for swap request callbacks, passing the
// balance of all tokens in the Pool. These Pools have the largest swap costs (because of the extra storage reads),
// which increase with the number of registered tokens.
//
// - Minimal Swap Info: IMinimalSwapInfoPool is used instead of IGeneralPool, which saves gas by only passing the
// balance of the two tokens involved in the swap. This is suitable for some pricing algorithms, like the weighted
// constant product one popularized by Balancer V1. Swap costs are smaller compared to general Pools, and are
// independent of the number of registered tokens.
//
// - Two Token: only allows two tokens to be registered. This achieves the lowest possible swap gas cost. Like
// minimal swap info Pools, these are called via IMinimalSwapInfoPool.
enum PoolSpecialization { GENERAL, MINIMAL_SWAP_INFO, TWO_TOKEN }
/**
* @dev Registers the caller account as a Pool with a given specialization setting. Returns the Pool's ID, which
* is used in all Pool-related functions. Pools cannot be deregistered, nor can the Pool's specialization be
* changed.
*
* The caller is expected to be a smart contract that implements either `IGeneralPool` or `IMinimalSwapInfoPool`,
* depending on the chosen specialization setting. This contract is known as the Pool's contract.
*
* Note that the same contract may register itself as multiple Pools with unique Pool IDs, or in other words,
* multiple Pools may share the same contract.
*
* Emits a `PoolRegistered` event.
*/
function registerPool(PoolSpecialization specialization) external returns (bytes32);
/**
* @dev Emitted when a Pool is registered by calling `registerPool`.
*/
event PoolRegistered(bytes32 indexed poolId, address indexed poolAddress, PoolSpecialization specialization);
/**
* @dev Returns a Pool's contract address and specialization setting.
*/
function getPool(bytes32 poolId) external view returns (address, PoolSpecialization);
/**
* @dev Registers `tokens` for the `poolId` Pool. Must be called by the Pool's contract.
*
* Pools can only interact with tokens they have registered. Users join a Pool by transferring registered tokens,
* exit by receiving registered tokens, and can only swap registered tokens.
*
* Each token can only be registered once. For Pools with the Two Token specialization, `tokens` must have a length
* of two, that is, both tokens must be registered in the same `registerTokens` call, and they must be sorted in
* ascending order.
*
* The `tokens` and `assetManagers` arrays must have the same length, and each entry in these indicates the Asset
* Manager for the corresponding token. Asset Managers can manage a Pool's tokens via `managePoolBalance`,
* depositing and withdrawing them directly, and can even set their balance to arbitrary amounts. They are therefore
* expected to be highly secured smart contracts with sound design principles, and the decision to register an
* Asset Manager should not be made lightly.
*
* Pools can choose not to assign an Asset Manager to a given token by passing in the zero address. Once an Asset
* Manager is set, it cannot be changed except by deregistering the associated token and registering again with a
* different Asset Manager.
*
* Emits a `TokensRegistered` event.
*/
function registerTokens(
bytes32 poolId,
IERC20[] memory tokens,
address[] memory assetManagers
) external;
/**
* @dev Emitted when a Pool registers tokens by calling `registerTokens`.
*/
event TokensRegistered(bytes32 indexed poolId, IERC20[] tokens, address[] assetManagers);
/**
* @dev Deregisters `tokens` for the `poolId` Pool. Must be called by the Pool's contract.
*
* Only registered tokens (via `registerTokens`) can be deregistered. Additionally, they must have zero total
* balance. For Pools with the Two Token specialization, `tokens` must have a length of two, that is, both tokens
* must be deregistered in the same `deregisterTokens` call.
*
* A deregistered token can be re-registered later on, possibly with a different Asset Manager.
*
* Emits a `TokensDeregistered` event.
*/
function deregisterTokens(bytes32 poolId, IERC20[] memory tokens) external;
/**
* @dev Emitted when a Pool deregisters tokens by calling `deregisterTokens`.
*/
event TokensDeregistered(bytes32 indexed poolId, IERC20[] tokens);
/**
* @dev Returns detailed information for a Pool's registered token.
*
* `cash` is the number of tokens the Vault currently holds for the Pool. `managed` is the number of tokens
* withdrawn and held outside the Vault by the Pool's token Asset Manager. The Pool's total balance for `token`
* equals the sum of `cash` and `managed`.
*
* Internally, `cash` and `managed` are stored using 112 bits. No action can ever cause a Pool's token `cash`,
* `managed` or `total` balance to be greater than 2^112 - 1.
*
* `lastChangeBlock` is the number of the block in which `token`'s total balance was last modified (via either a
* join, exit, swap, or Asset Manager update). This value is useful to avoid so-called 'sandwich attacks', for
* example when developing price oracles. A change of zero (e.g. caused by a swap with amount zero) is considered a
* change for this purpose, and will update `lastChangeBlock`.
*
* `assetManager` is the Pool's token Asset Manager.
*/
function getPoolTokenInfo(bytes32 poolId, IERC20 token)
external
view
returns (
uint256 cash,
uint256 managed,
uint256 lastChangeBlock,
address assetManager
);
/**
* @dev Returns a Pool's registered tokens, the total balance for each, and the latest block when *any* of
* the tokens' `balances` changed.
*
* The order of the `tokens` array is the same order that will be used in `joinPool`, `exitPool`, as well as in all
* Pool hooks (where applicable). Calls to `registerTokens` and `deregisterTokens` may change this order.
*
* If a Pool only registers tokens once, and these are sorted in ascending order, they will be stored in the same
* order as passed to `registerTokens`.
*
* Total balances include both tokens held by the Vault and those withdrawn by the Pool's Asset Managers. These are
* the amounts used by joins, exits and swaps. For a detailed breakdown of token balances, use `getPoolTokenInfo`
* instead.
*/
function getPoolTokens(bytes32 poolId)
external
view
returns (
IERC20[] memory tokens,
uint256[] memory balances,
uint256 lastChangeBlock
);
/**
* @dev Called by users to join a Pool, which transfers tokens from `sender` into the Pool's balance. This will
* trigger custom Pool behavior, which will typically grant something in return to `recipient` - often tokenized
* Pool shares.
*
* If the caller is not `sender`, it must be an authorized relayer for them.
*
* The `assets` and `maxAmountsIn` arrays must have the same length, and each entry indicates the maximum amount
* to send for each asset. The amounts to send are decided by the Pool and not the Vault: it just enforces
* these maximums.
*
* If joining a Pool that holds WETH, it is possible to send ETH directly: the Vault will do the wrapping. To enable
* this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead of the
* WETH address. Note that it is not possible to combine ETH and WETH in the same join. Any excess ETH will be sent
* back to the caller (not the sender, which is important for relayers).
*
* `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when
* interacting with Pools that register and deregister tokens frequently. If sending ETH however, the array must be
* sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the final
* `assets` array might not be sorted. Pools with no registered tokens cannot be joined.
*
* If `fromInternalBalance` is true, the caller's Internal Balance will be preferred: ERC20 transfers will only
* be made for the difference between the requested amount and Internal Balance (if any). Note that ETH cannot be
* withdrawn from Internal Balance: attempting to do so will trigger a revert.
*
* This causes the Vault to call the `IBasePool.onJoinPool` hook on the Pool's contract, where Pools implement
* their own custom logic. This typically requires additional information from the user (such as the expected number
* of Pool shares). This can be encoded in the `userData` argument, which is ignored by the Vault and passed
* directly to the Pool's contract, as is `recipient`.
*
* Emits a `PoolBalanceChanged` event.
*/
function joinPool(
bytes32 poolId,
address sender,
address recipient,
JoinPoolRequest memory request
) external payable;
struct JoinPoolRequest {
IAsset[] assets;
uint256[] maxAmountsIn;
bytes userData;
bool fromInternalBalance;
}
/**
* @dev Called by users to exit a Pool, which transfers tokens from the Pool's balance to `recipient`. This will
* trigger custom Pool behavior, which will typically ask for something in return from `sender` - often tokenized
* Pool shares. The amount of tokens that can be withdrawn is limited by the Pool's `cash` balance (see
* `getPoolTokenInfo`).
*
* If the caller is not `sender`, it must be an authorized relayer for them.
*
* The `tokens` and `minAmountsOut` arrays must have the same length, and each entry in these indicates the minimum
* token amount to receive for each token contract. The amounts to send are decided by the Pool and not the Vault:
* it just enforces these minimums.
*
* If exiting a Pool that holds WETH, it is possible to receive ETH directly: the Vault will do the unwrapping. To
* enable this mechanism, the IAsset sentinel value (the zero address) must be passed in the `assets` array instead
* of the WETH address. Note that it is not possible to combine ETH and WETH in the same exit.
*
* `assets` must have the same length and order as the array returned by `getPoolTokens`. This prevents issues when
* interacting with Pools that register and deregister tokens frequently. If receiving ETH however, the array must
* be sorted *before* replacing the WETH address with the ETH sentinel value (the zero address), which means the
* final `assets` array might not be sorted. Pools with no registered tokens cannot be exited.
*
* If `toInternalBalance` is true, the tokens will be deposited to `recipient`'s Internal Balance. Otherwise,
* an ERC20 transfer will be performed. Note that ETH cannot be deposited to Internal Balance: attempting to
* do so will trigger a revert.
*
* `minAmountsOut` is the minimum amount of tokens the user expects to get out of the Pool, for each token in the
* `tokens` array. This array must match the Pool's registered tokens.
*
* This causes the Vault to call the `IBasePool.onExitPool` hook on the Pool's contract, where Pools implement
* their own custom logic. This typically requires additional information from the user (such as the expected number
* of Pool shares to return). This can be encoded in the `userData` argument, which is ignored by the Vault and
* passed directly to the Pool's contract.
*
* Emits a `PoolBalanceChanged` event.
*/
function exitPool(
bytes32 poolId,
address sender,
address payable recipient,
ExitPoolRequest memory request
) external;
struct ExitPoolRequest {
IAsset[] assets;
uint256[] minAmountsOut;
bytes userData;
bool toInternalBalance;
}
/**
* @dev Emitted when a user joins or exits a Pool by calling `joinPool` or `exitPool`, respectively.
*/
event PoolBalanceChanged(
bytes32 indexed poolId,
address indexed liquidityProvider,
IERC20[] tokens,
int256[] deltas,
uint256[] protocolFeeAmounts
);
enum PoolBalanceChangeKind { JOIN, EXIT }
// Swaps
//
// Users can swap tokens with Pools by calling the `swap` and `batchSwap` functions. To do this,
// they need not trust Pool contracts in any way: all security checks are made by the Vault. They must however be
// aware of the Pools' pricing algorithms in order to estimate the prices Pools will quote.
//
// The `swap` function executes a single swap, while `batchSwap` can perform multiple swaps in sequence.
// In each individual swap, tokens of one kind are sent from the sender to the Pool (this is the 'token in'),
// and tokens of another kind are sent from the Pool to the recipient in exchange (this is the 'token out').
// More complex swaps, such as one token in to multiple tokens out can be achieved by batching together
// individual swaps.
//
// There are two swap kinds:
// - 'given in' swaps, where the amount of tokens in (sent to the Pool) is known, and the Pool determines (via the
// `onSwap` hook) the amount of tokens out (to send to the recipient).
// - 'given out' swaps, where the amount of tokens out (received from the Pool) is known, and the Pool determines
// (via the `onSwap` hook) the amount of tokens in (to receive from the sender).
//
// Additionally, it is possible to chain swaps using a placeholder input amount, which the Vault replaces with
// the calculated output of the previous swap. If the previous swap was 'given in', this will be the calculated
// tokenOut amount. If the previous swap was 'given out', it will use the calculated tokenIn amount. These extended
// swaps are known as 'multihop' swaps, since they 'hop' through a number of intermediate tokens before arriving at
// the final intended token.
//
// In all cases, tokens are only transferred in and out of the Vault (or withdrawn from and deposited into Internal
// Balance) after all individual swaps have been completed, and the net token balance change computed. This makes
// certain swap patterns, such as multihops, or swaps that interact with the same token pair in multiple Pools, cost
// much less gas than they would otherwise.
//
// It also means that under certain conditions it is possible to perform arbitrage by swapping with multiple
// Pools in a way that results in net token movement out of the Vault (profit), with no tokens being sent in (only
// updating the Pool's internal accounting).
//
// To protect users from front-running or the market changing rapidly, they supply a list of 'limits' for each token
// involved in the swap, where either the maximum number of tokens to send (by passing a positive value) or the
// minimum amount of tokens to receive (by passing a negative value) is specified.
//
// Additionally, a 'deadline' timestamp can also be provided, forcing the swap to fail if it occurs after
// this point in time (e.g. if the transaction failed to be included in a block promptly).
//
// If interacting with Pools that hold WETH, it is possible to both send and receive ETH directly: the Vault will do
// the wrapping and unwrapping. To enable this mechanism, the IAsset sentinel value (the zero address) must be
// passed in the `assets` array instead of the WETH address. Note that it is possible to combine ETH and WETH in the
// same swap. Any excess ETH will be sent back to the caller (not the sender, which is relevant for relayers).
//
// Finally, Internal Balance can be used when either sending or receiving tokens.
enum SwapKind { GIVEN_IN, GIVEN_OUT }
/**
* @dev Performs a swap with a single Pool.
*
* If the swap is 'given in' (the number of tokens to send to the Pool is known), it returns the amount of tokens
* taken from the Pool, which must be greater than or equal to `limit`.
*
* If the swap is 'given out' (the number of tokens to take from the Pool is known), it returns the amount of tokens
* sent to the Pool, which must be less than or equal to `limit`.
*
* Internal Balance usage and the recipient are determined by the `funds` struct.
*
* Emits a `Swap` event.
*/
function swap(
SingleSwap memory singleSwap,
FundManagement memory funds,
uint256 limit,
uint256 deadline
) external payable returns (uint256);
/**
* @dev Data for a single swap executed by `swap`. `amount` is either `amountIn` or `amountOut` depending on
* the `kind` value.
*
* `assetIn` and `assetOut` are either token addresses, or the IAsset sentinel value for ETH (the zero address).
* Note that Pools never interact with ETH directly: it will be wrapped to or unwrapped from WETH by the Vault.
*
* The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be
* used to extend swap behavior.
*/
struct SingleSwap {
bytes32 poolId;
SwapKind kind;
IAsset assetIn;
IAsset assetOut;
uint256 amount;
bytes userData;
}
/**
* @dev Performs a series of swaps with one or multiple Pools. In each individual swap, the caller determines either
* the amount of tokens sent to or received from the Pool, depending on the `kind` value.
*
* Returns an array with the net Vault asset balance deltas. Positive amounts represent tokens (or ETH) sent to the
* Vault, and negative amounts represent tokens (or ETH) sent by the Vault. Each delta corresponds to the asset at
* the same index in the `assets` array.
*
* Swaps are executed sequentially, in the order specified by the `swaps` array. Each array element describes a
* Pool, the token to be sent to this Pool, the token to receive from it, and an amount that is either `amountIn` or
* `amountOut` depending on the swap kind.
*
* Multihop swaps can be executed by passing an `amount` value of zero for a swap. This will cause the amount in/out
* of the previous swap to be used as the amount in for the current one. In a 'given in' swap, 'tokenIn' must equal
* the previous swap's `tokenOut`. For a 'given out' swap, `tokenOut` must equal the previous swap's `tokenIn`.
*
* The `assets` array contains the addresses of all assets involved in the swaps. These are either token addresses,
* or the IAsset sentinel value for ETH (the zero address). Each entry in the `swaps` array specifies tokens in and
* out by referencing an index in `assets`. Note that Pools never interact with ETH directly: it will be wrapped to
* or unwrapped from WETH by the Vault.
*
* Internal Balance usage, sender, and recipient are determined by the `funds` struct. The `limits` array specifies
* the minimum or maximum amount of each token the vault is allowed to transfer.
*
* `batchSwap` can be used to make a single swap, like `swap` does, but doing so requires more gas than the
* equivalent `swap` call.
*
* Emits `Swap` events.
*/
function batchSwap(
SwapKind kind,
BatchSwapStep[] memory swaps,
IAsset[] memory assets,
FundManagement memory funds,
int256[] memory limits,
uint256 deadline
) external payable returns (int256[] memory);
/**
* @dev Data for each individual swap executed by `batchSwap`. The asset in and out fields are indexes into the
* `assets` array passed to that function, and ETH assets are converted to WETH.
*
* If `amount` is zero, the multihop mechanism is used to determine the actual amount based on the amount in/out
* from the previous swap, depending on the swap kind.
*
* The `userData` field is ignored by the Vault, but forwarded to the Pool in the `onSwap` hook, and may be
* used to extend swap behavior.
*/
struct BatchSwapStep {
bytes32 poolId;
uint256 assetInIndex;
uint256 assetOutIndex;
uint256 amount;
bytes userData;
}
/**
* @dev Emitted for each individual swap performed by `swap` or `batchSwap`.
*/
event Swap(
bytes32 indexed poolId,
IERC20 indexed tokenIn,
IERC20 indexed tokenOut,
uint256 amountIn,
uint256 amountOut
);
/**
* @dev All tokens in a swap are either sent from the `sender` account to the Vault, or from the Vault to the
* `recipient` account.
*
* If the caller is not `sender`, it must be an authorized relayer for them.
*
* If `fromInternalBalance` is true, the `sender`'s Internal Balance will be preferred, performing an ERC20
* transfer for the difference between the requested amount and the User's Internal Balance (if any). The `sender`
* must have allowed the Vault to use their tokens via `IERC20.approve()`. This matches the behavior of
* `joinPool`.
*
* If `toInternalBalance` is true, tokens will be deposited to `recipient`'s internal balance instead of
* transferred. This matches the behavior of `exitPool`.
*
* Note that ETH cannot be deposited to or withdrawn from Internal Balance: attempting to do so will trigger a
* revert.
*/
struct FundManagement {
address sender;
bool fromInternalBalance;
address payable recipient;
bool toInternalBalance;
}
/**
* @dev Simulates a call to `batchSwap`, returning an array of Vault asset deltas. Calls to `swap` cannot be
* simulated directly, but an equivalent `batchSwap` call can and will yield the exact same result.
*
* Each element in the array corresponds to the asset at the same index, and indicates the number of tokens (or ETH)
* the Vault would take from the sender (if positive) or send to the recipient (if negative). The arguments it
* receives are the same that an equivalent `batchSwap` call would receive.
*
* Unlike `batchSwap`, this function performs no checks on the sender or recipient field in the `funds` struct.
* This makes it suitable to be called by off-chain applications via eth_call without needing to hold tokens,
* approve them for the Vault, or even know a user's address.
*
* Note that this function is not 'view' (due to implementation details): the client code must explicitly execute
* eth_call instead of eth_sendTransaction.
*/
function queryBatchSwap(
SwapKind kind,
BatchSwapStep[] memory swaps,
IAsset[] memory assets,
FundManagement memory funds
) external returns (int256[] memory assetDeltas);
// Flash Loans
/**
* @dev Performs a 'flash loan', sending tokens to `recipient`, executing the `receiveFlashLoan` hook on it,
* and then reverting unless the tokens plus a proportional protocol fee have been returned.
*
* The `tokens` and `amounts` arrays must have the same length, and each entry in these indicates the loan amount
* for each token contract. `tokens` must be sorted in ascending order.
*
* The 'userData' field is ignored by the Vault, and forwarded as-is to `recipient` as part of the
* `receiveFlashLoan` call.
*
* Emits `FlashLoan` events.
*/
function flashLoan(
IFlashLoanRecipient recipient,
IERC20[] memory tokens,
uint256[] memory amounts,
bytes memory userData
) external;
/**
* @dev Emitted for each individual flash loan performed by `flashLoan`.
*/
event FlashLoan(IFlashLoanRecipient indexed recipient, IERC20 indexed token, uint256 amount, uint256 feeAmount);
// Asset Management
//
// Each token registered for a Pool can be assigned an Asset Manager, which is able to freely withdraw the Pool's
// tokens from the Vault, deposit them, or assign arbitrary values to its `managed` balance (see
// `getPoolTokenInfo`). This makes them extremely powerful and dangerous. Even if an Asset Manager only directly
// controls one of the tokens in a Pool, a malicious manager could set that token's balance to manipulate the
// prices of the other tokens, and then drain the Pool with swaps. The risk of using Asset Managers is therefore
// not constrained to the tokens they are managing, but extends to the entire Pool's holdings.
//
// However, a properly designed Asset Manager smart contract can be safely used for the Pool's benefit,
// for example by lending unused tokens out for interest, or using them to participate in voting protocols.
//
// This concept is unrelated to the IAsset interface.
/**
* @dev Performs a set of Pool balance operations, which may be either withdrawals, deposits or updates.
*
* Pool Balance management features batching, which means a single contract call can be used to perform multiple
* operations of different kinds, with different Pools and tokens, at once.
*
* For each operation, the caller must be registered as the Asset Manager for `token` in `poolId`.
*/
function managePoolBalance(PoolBalanceOp[] memory ops) external;
struct PoolBalanceOp {
PoolBalanceOpKind kind;
bytes32 poolId;
IERC20 token;
uint256 amount;
}
/**
* Withdrawals decrease the Pool's cash, but increase its managed balance, leaving the total balance unchanged.
*
* Deposits increase the Pool's cash, but decrease its managed balance, leaving the total balance unchanged.
*
* Updates don't affect the Pool's cash balance, but because the managed balance changes, it does alter the total.
* The external amount can be either increased or decreased by this call (i.e., reporting a gain or a loss).
*/
enum PoolBalanceOpKind { WITHDRAW, DEPOSIT, UPDATE }
/**
* @dev Emitted when a Pool's token Asset Manager alters its balance via `managePoolBalance`.
*/
event PoolBalanceManaged(
bytes32 indexed poolId,
address indexed assetManager,
IERC20 indexed token,
int256 cashDelta,
int256 managedDelta
);
// Protocol Fees
//
// Some operations cause the Vault to collect tokens in the form of protocol fees, which can then be withdrawn by
// permissioned accounts.
//
// There are two kinds of protocol fees:
//
// - flash loan fees: charged on all flash loans, as a percentage of the amounts lent.
//
// - swap fees: a percentage of the fees charged by Pools when performing swaps. For a number of reasons, including
// swap gas costs and interface simplicity, protocol swap fees are not charged on each individual swap. Rather,
// Pools are expected to keep track of how much they have charged in swap fees, and pay any outstanding debts to the
// Vault when they are joined or exited. This prevents users from joining a Pool with unpaid debt, as well as
// exiting a Pool in debt without first paying their share.
/**
* @dev Returns the current protocol fee module.
*/
function getProtocolFeesCollector() external view returns (IProtocolFeesCollector);
/**
* @dev Safety mechanism to pause most Vault operations in the event of an emergency - typically detection of an
* error in some part of the system.
*
* The Vault can only be paused during an initial time period, after which pausing is forever disabled.
*
* While the contract is paused, the following features are disabled:
* - depositing and transferring internal balance
* - transferring external balance (using the Vault's allowance)
* - swaps
* - joining Pools
* - Asset Manager interactions
*
* Internal Balance can still be withdrawn, and Pools exited.
*/
function setPaused(bool paused) external;
/**
* @dev Returns the Vault's WETH instance.
*/
function WETH() external view returns (IWETH);
// solhint-disable-previous-line func-name-mixedcase
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
// Inspired by Aave Protocol's IFlashLoanReceiver.
import "../solidity-utils/openzeppelin/IERC20.sol";
interface IFlashLoanRecipient {
/**
* @dev When `flashLoan` is called on the Vault, it invokes the `receiveFlashLoan` hook on the recipient.
*
* At the time of the call, the Vault will have transferred `amounts` for `tokens` to the recipient. Before this
* call returns, the recipient must have transferred `amounts` plus `feeAmounts` for each token back to the
* Vault, or else the entire flash loan will revert.
*
* `userData` is the same value passed in the `IVault.flashLoan` call.
*/
function receiveFlashLoan(
IERC20[] memory tokens,
uint256[] memory amounts,
uint256[] memory feeAmounts,
bytes memory userData
) external;
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
import "../openzeppelin/IERC20.sol";
/**
* @dev Interface for WETH9.
* See https://github.com/gnosis/canonical-weth/blob/0dd1ea3e295eef916d0c6223ec63141137d22d67/contracts/WETH9.sol
*/
interface IWETH is IERC20 {
function deposit() external payable;
function withdraw(uint256 amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.27;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
interface IHonestWork is IERC721 {
function tokensOf(address owner) external view returns (uint256[] memory);
}// 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: MIT
pragma solidity >=0.7.0 <0.9.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
interface IAuthentication {
/**
* @dev Returns the action identifier associated with the external function described by `selector`.
*/
function getActionId(bytes4 selector) external view returns (bytes32);
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
/**
* @dev Interface for the SignatureValidator helper, used to support meta-transactions.
*/
interface ISignaturesValidator {
/**
* @dev Returns the EIP712 domain separator.
*/
function getDomainSeparator() external view returns (bytes32);
/**
* @dev Returns the next nonce used by an address to sign messages.
*/
function getNextNonce(address user) external view returns (uint256);
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
/**
* @dev Interface for the TemporarilyPausable helper.
*/
interface ITemporarilyPausable {
/**
* @dev Emitted every time the pause state changes by `_setPaused`.
*/
event PausedStateChanged(bool paused);
/**
* @dev Returns the current paused state.
*/
function getPausedState()
external
view
returns (
bool paused,
uint256 pauseWindowEndTime,
uint256 bufferPeriodEndTime
);
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
/**
* @dev This is an empty interface used to represent either ERC20-conforming token contracts or ETH (using the zero
* address sentinel value). We're just relying on the fact that `interface` can be used to declare new address-like
* types.
*
* This concept is unrelated to a Pool's Asset Managers.
*/
interface IAsset {
// solhint-disable-previous-line no-empty-blocks
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
interface IAuthorizer {
/**
* @dev Returns true if `account` can perform the action described by `actionId` in the contract `where`.
*/
function canPerform(
bytes32 actionId,
address account,
address where
) external view returns (bool);
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
pragma experimental ABIEncoderV2;
import "../solidity-utils/openzeppelin/IERC20.sol";
import "./IVault.sol";
import "./IAuthorizer.sol";
interface IProtocolFeesCollector {
event SwapFeePercentageChanged(uint256 newSwapFeePercentage);
event FlashLoanFeePercentageChanged(uint256 newFlashLoanFeePercentage);
function withdrawCollectedFees(
IERC20[] calldata tokens,
uint256[] calldata amounts,
address recipient
) external;
function setSwapFeePercentage(uint256 newSwapFeePercentage) external;
function setFlashLoanFeePercentage(uint256 newFlashLoanFeePercentage) external;
function getSwapFeePercentage() external view returns (uint256);
function getFlashLoanFeePercentage() external view returns (uint256);
function getCollectedFeeAmounts(IERC20[] memory tokens) external view returns (uint256[] memory feeAmounts);
function getAuthorizer() external view returns (IAuthorizer);
function vault() external view returns (IVault);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
* {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}{
"remappings": [
"@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
"forge-std/=node_modules/forge-std/",
"@balancer-labs/=node_modules/@balancer-labs/"
],
"optimizer": {
"enabled": true,
"runs": 10000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "shanghai",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IHonestWork","name":"_honestWork","type":"address"},{"internalType":"address","name":"_withdrawAddress","type":"address"},{"internalType":"address","name":"_vault","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"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":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"depositor","type":"address"},{"indexed":true,"internalType":"address","name":"destination","type":"address"}],"name":"TokenDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"withdrawer","type":"address"},{"indexed":true,"internalType":"address","name":"source","type":"address"}],"name":"TokenWithdrawn","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"babe","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"backToWork","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bad","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"beef","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"callABabe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dead","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deaf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"endYourBeef","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"face","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"faceYourFears","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fed","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feed","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllDepositedTokens","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getDepositedTokens","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"goRaveTurnDeaf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"goToAFancyRestaurantFeedYourself","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"goToDoctorHealDeaf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"honestWork","outputs":[{"internalType":"contract IHonestWork","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"makeOriginNotSender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"probability","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"makeYourOwnLuck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"overdoseAndGoDead","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ownerMap","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"putAMiladyPfpNoMoreBad","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"receiveFlashLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"returnFromFedsWithWitnessProtection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"returnHomeToFeedYourHead","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"sayGoodbyeToBabe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"sendToAnEmptyAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"ethAmount","type":"uint256"}],"name":"sendWithFakeRolex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"sendWithPassword","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_beef","type":"address"},{"internalType":"address","name":"_babe","type":"address"},{"internalType":"address","name":"_deaf","type":"address"},{"internalType":"address","name":"_dead","type":"address"},{"internalType":"address","name":"_face","type":"address"},{"internalType":"address","name":"_feed","type":"address"},{"internalType":"address","name":"_fed","type":"address"},{"internalType":"address","name":"_bad","type":"address"}],"name":"setAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newAddress","type":"address"}],"name":"setWithdrawAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"shillScamTokenToYourFriendsBeBad","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"shotAdrenalineNoMoreDead","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"snitchToFeds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"startABeef","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"takeAVacation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"times","type":"uint256"}],"name":"transferXTimes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"turnBackWithAHappyFace","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"source","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"erc20","type":"address"}],"name":"withdrawErc20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC721","name":"erc721","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"withdrawErc721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawEth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
608060405234801561000f575f5ffd5b5060405161340738038061340783398101604081905261002e91610287565b338061005457604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61005d81610221565b506001600160a01b0383166100b45760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420486f6e657374576f726b2061646472657373000000000000604482015260640161004b565b6001600160a01b03821661010a5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420776974686472617720616464726573730000000000000000604482015260640161004b565b6001600160a01b0381166101605760405162461bcd60e51b815260206004820152601560248201527f496e76616c6964207661756c7420616464726573730000000000000000000000604482015260640161004b565b600180546001600160a01b038086166001600160a01b031992831617909255600b8054858416908316179055600c80549284169290911682179055604080516315ab88c960e31b8152905163ad5c4648916004808201926020929091908290030181865afa1580156101d4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101f891906102d1565b600280546001600160a01b0319166001600160a01b0392909216919091179055506102f3915050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381168114610284575f5ffd5b50565b5f5f5f60608486031215610299575f5ffd5b83516102a481610270565b60208501519093506102b581610270565b60408501519092506102c681610270565b809150509250925092565b5f602082840312156102e1575f5ffd5b81516102ec81610270565b9392505050565b613107806103005f395ff3fe60806040526004361061032b575f3560e01c8063853828b6116101a4578063b6507250116100eb578063e775cac611610094578063f2fde38b1161006e578063f2fde38b14610a13578063f93e879f14610a32578063fc07749714610a51578063feecf6ed14610a7d576103cf565b8063e775cac6146109b6578063ebae9281146109d5578063f04f2707146109f4576103cf565b8063c867b0bc116100c5578063c867b0bc14610959578063c8b4169f14610978578063d733cfd014610997576103cf565b8063b6507250146108fc578063bb6a37f01461091b578063c7e42b1b1461093a576103cf565b80639be571df1161014d578063a9d3643f11610127578063a9d3643f1461089f578063b06279b7146108be578063b315b265146108dd576103cf565b80639be571df1461084d5780639c3674fc1461086c578063a0ef91df1461088b576103cf565b806394585a041161017e57806394585a04146107d857806395550a3e146107fa5780639a8bfa2b14610819576103cf565b8063853828b61461078957806389c8c4c01461079d5780638da5cb5b146107bc576103cf565b806337a7b7d81161027357806353d06f941161021c578063715018a6116101f6578063715018a61461071857806378edd8101461072c5780637a4050911461074b5780637e900de41461076a576103cf565b806353d06f94146106bb5780635b84e9c3146106da57806362b34c26146106f9576103cf565b80633fc8cef31161024d5780633fc8cef31461065e57806342c02a4b1461067d5780634eab0d271461069c576103cf565b806337a7b7d81461060157806339821949146106205780633ab1a4941461063f576103cf565b80632a5efac8116102d55780632e1c5849116102af5780632e1c5849146105a457806330c571e4146105c357806336cf7c87146105e2576103cf565b80632a5efac8146105475780632a9cde12146105665780632e1a7d4d14610585576103cf565b80631581b600116103065780631581b600146104cd5780631c582cf71461050957806322e3bf7814610528576103cf565b8062f714ce1461047057806304270b2b1461048f5780630757b89d146104ae576103cf565b366103cf57600c546001600160a01b0316331480159061035657506002546001600160a01b03163314155b156103cd5760405162461bcd60e51b8152602060048201526024808201527f596f752063616e27742073656e642045544820746f207468697320636f6e747260448201527f616374210000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b005b3480156103da575f5ffd5b50600c546001600160a01b0316331480159061035657506002546001600160a01b031633146103cd5760405162461bcd60e51b8152602060048201526024808201527f596f752063616e27742073656e642045544820746f207468697320636f6e747260448201527f616374210000000000000000000000000000000000000000000000000000000060648201526084016103c4565b34801561047b575f5ffd5b506103cd61048a366004612909565b610a9c565b34801561049a575f5ffd5b506103cd6104a9366004612937565b610aab565b3480156104b9575f5ffd5b506103cd6104c8366004612937565b610ac6565b3480156104d8575f5ffd5b50600b546104ec906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610514575f5ffd5b506007546104ec906001600160a01b031681565b348015610533575f5ffd5b506103cd610542366004612937565b610ade565b348015610552575f5ffd5b506103cd610561366004612937565b610af6565b348015610571575f5ffd5b506103cd610580366004612937565b610b0e565b348015610590575f5ffd5b506103cd61059f366004612937565b610b26565b3480156105af575f5ffd5b506103cd6105be36600461294e565b6111b8565b3480156105ce575f5ffd5b506103cd6105dd366004612937565b6112d1565b3480156105ed575f5ffd5b506006546104ec906001600160a01b031681565b34801561060c575f5ffd5b506008546104ec906001600160a01b031681565b34801561062b575f5ffd5b506103cd61063a366004612937565b6112e9565b34801561064a575f5ffd5b506103cd610659366004612983565b6112f4565b348015610669575f5ffd5b506002546104ec906001600160a01b031681565b348015610688575f5ffd5b506103cd610697366004612937565b611388565b3480156106a7575f5ffd5b506103cd6106b6366004612937565b6113a0565b3480156106c6575f5ffd5b506009546104ec906001600160a01b031681565b3480156106e5575f5ffd5b506003546104ec906001600160a01b031681565b348015610704575f5ffd5b506103cd610713366004612937565b6113b8565b348015610723575f5ffd5b506103cd6113d0565b348015610737575f5ffd5b506103cd610746366004612937565b6113e3565b348015610756575f5ffd5b506103cd6107653660046129a5565b6113fb565b348015610775575f5ffd5b506005546104ec906001600160a01b031681565b348015610794575f5ffd5b506103cd611554565b3480156107a8575f5ffd5b506103cd6107b73660046129cf565b6115ec565b3480156107c7575f5ffd5b505f546001600160a01b03166104ec565b3480156107e3575f5ffd5b506107ec6117fa565b604051610500929190612a29565b348015610805575f5ffd5b506103cd610814366004612937565b611b65565b348015610824575f5ffd5b506104ec610833366004612937565b600d6020525f90815260409020546001600160a01b031681565b348015610858575f5ffd5b506103cd610867366004612937565b611b7d565b348015610877575f5ffd5b50600a546104ec906001600160a01b031681565b348015610896575f5ffd5b506103cd611b88565b3480156108aa575f5ffd5b506004546104ec906001600160a01b031681565b3480156108c9575f5ffd5b506103cd6108d8366004612937565b611c18565b3480156108e8575f5ffd5b506001546104ec906001600160a01b031681565b348015610907575f5ffd5b506103cd6109163660046129a5565b611c30565b348015610926575f5ffd5b506103cd6109353660046129cf565b611c88565b348015610945575f5ffd5b506103cd610954366004612983565b611dea565b348015610964575f5ffd5b506103cd6109733660046129a5565b611f56565b348015610983575f5ffd5b506103cd610992366004612937565b611fde565b3480156109a2575f5ffd5b506103cd6109b1366004612a8a565b611ff6565b3480156109c1575f5ffd5b506103cd6109d0366004612937565b6120a4565b3480156109e0575f5ffd5b506103cd6109ef366004612937565b6120bc565b3480156109ff575f5ffd5b506103cd610a0e366004612cc1565b6121bb565b348015610a1e575f5ffd5b506103cd610a2d366004612983565b61238e565b348015610a3d575f5ffd5b506103cd610a4c366004612937565b6123e1565b348015610a5c575f5ffd5b50610a70610a6b366004612983565b6123f9565b6040516105009190612dda565b348015610a88575f5ffd5b506103cd610a97366004612937565b612562565b610aa782823361257a565b5050565b600754610ac39082906001600160a01b03163361257a565b50565b600954610ac39082906001600160a01b0316336126d3565b600554610ac39082906001600160a01b03163361257a565b600554610ac39082906001600160a01b0316336126d3565b600a54610ac39082906001600160a01b03163361257a565b6001546040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810183905230916001600160a01b031690636352211e90602401602060405180830381865afa158015610b86573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610baa9190612dec565b6001600160a01b031603610bc357610ac381303361257a565b6003546001546040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b039283169290911690636352211e90602401602060405180830381865afa158015610c2a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c4e9190612dec565b6001600160a01b031603610c7457600354610ac39082906001600160a01b03163361257a565b600480546001546040517f6352211e0000000000000000000000000000000000000000000000000000000081529283018490526001600160a01b0391821692911690636352211e90602401602060405180830381865afa158015610cda573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cfe9190612dec565b6001600160a01b031603610d2457600454610ac39082906001600160a01b03163361257a565b6005546001546040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b039283169290911690636352211e90602401602060405180830381865afa158015610d8b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610daf9190612dec565b6001600160a01b031603610dd557600554610ac39082906001600160a01b03163361257a565b6006546001546040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b039283169290911690636352211e90602401602060405180830381865afa158015610e3c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e609190612dec565b6001600160a01b031603610e8657600654610ac39082906001600160a01b03163361257a565b6007546001546040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b039283169290911690636352211e90602401602060405180830381865afa158015610eed573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f119190612dec565b6001600160a01b031603610f3757600754610ac39082906001600160a01b03163361257a565b6008546001546040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b039283169290911690636352211e90602401602060405180830381865afa158015610f9e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fc29190612dec565b6001600160a01b031603610fe857600854610ac39082906001600160a01b03163361257a565b6009546001546040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b039283169290911690636352211e90602401602060405180830381865afa15801561104f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110739190612dec565b6001600160a01b03160361109957600954610ac39082906001600160a01b03163361257a565b600a546001546040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b039283169290911690636352211e90602401602060405180830381865afa158015611100573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111249190612dec565b6001600160a01b03160361114a57600a54610ac39082906001600160a01b03163361257a565b60405162461bcd60e51b815260206004820152602660248201527f546f6b656e206e6f7420666f756e6420696e20616e79207370656369616c206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016103c4565b6001546040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03848116602483015260448201849052909116906323b872dd906064015f604051808303815f87803b158015611222575f5ffd5b505af1158015611234573d5f5f3e3d5ffd5b505050505f60644244604051602001611257929190918252602082015260400190565b604051602081830303815290604052805190602001205f1c6112799190612e07565b9050838111156112cb5760405162461bcd60e51b815260206004820152600f60248201527f596f752061726520756e6c75636b79000000000000000000000000000000000060448201526064016103c4565b50505050565b600654610ac39082906001600160a01b0316336126d3565b610ac38130336126d3565b600b546001600160a01b0316331461134e5760405162461bcd60e51b815260206004820152601560248201527f4f6e6c792077697468647261772061646472657373000000000000000000000060448201526064016103c4565b600b80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600754610ac39082906001600160a01b0316336126d3565b600854610ac39082906001600160a01b03163361257a565b600954610ac39082906001600160a01b03163361257a565b6113d8612849565b6113e15f61288e565b565b600654610ac39082906001600160a01b03163361257a565b600b546001600160a01b031633146114555760405162461bcd60e51b815260206004820152601560248201527f4f6e6c792077697468647261772061646472657373000000000000000000000060448201526064016103c4565b6001546001600160a01b03908116908316036114cf575f818152600d60205260409020546001600160a01b0316156114cf5760405162461bcd60e51b815260206004820152600c60248201527f4f776e657220657869737473000000000000000000000000000000000000000060448201526064016103c4565b600b546040517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03918216602482015260448101839052908316906323b872dd906064015b5f604051808303815f87803b15801561153a575f5ffd5b505af115801561154c573d5f5f3e3d5ffd5b505050505050565b5f61155e336123f9565b80519091505f8190036115b35760405162461bcd60e51b815260206004820152601360248201527f4e6f20746f6b656e73206465706f73697465640000000000000000000000000060448201526064016103c4565b5f5b818110156115e7576115df8382815181106115d2576115d2612e3f565b6020026020010151610b26565b6001016115b5565b505050565b5f5b8181101561171157611601600282612e07565b5f0361168a576001546040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018590526001600160a01b03909116906323b872dd906064015f604051808303815f87803b15801561166f575f5ffd5b505af1158015611681573d5f5f3e3d5ffd5b50505050611709565b6001546040517f23b872dd000000000000000000000000000000000000000000000000000000008152306004820152336024820152604481018590526001600160a01b03909116906323b872dd906064015f604051808303815f87803b1580156116f2575f5ffd5b505af1158015611704573d5f5f3e3d5ffd5b505050505b6001016115ee565b506001546040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810184905230916001600160a01b031690636352211e90602401602060405180830381865afa158015611772573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117969190612dec565b6001600160a01b031603610aa7576001546040517f23b872dd000000000000000000000000000000000000000000000000000000008152306004820152336024820152604481018490526001600160a01b03909116906323b872dd90606401611523565b60408051610120810182523081526004546001600160a01b039081166020830152600554811692820192909252600654821660608281019190915260075483166080830152600854831660a0830152600954831660c0830152600a54831660e083015260035490921661010082015281905f805b6009811015611952576001546001600160a01b0316635a3f267284836009811061189a5761189a612e3f565b60200201516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b0390911660048201526024015f60405180830381865afa1580156118f8573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261193d9190810190612e6c565b516119489083612f2a565b915060010161186e565b505f8167ffffffffffffffff81111561196d5761196d612b2e565b604051908082528060200260200182016040528015611996578160200160208202803683370190505b5090505f8267ffffffffffffffff8111156119b3576119b3612b2e565b6040519080825280602002602001820160405280156119dc578160200160208202803683370190505b5090505f805b6009811015611b58576001545f906001600160a01b0316635a3f2672888460098110611a1057611a10612e3f565b60200201516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b0390911660048201526024015f60405180830381865afa158015611a6e573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611ab39190810190612e6c565b90505f5b8151811015611b4e57818181518110611ad257611ad2612e3f565b6020026020010151868581518110611aec57611aec612e3f565b602002602001018181525050878360098110611b0a57611b0a612e3f565b6020020151858581518110611b2157611b21612e3f565b6001600160a01b039092166020928302919091019091015283611b4381612f43565b945050600101611ab7565b50506001016119e2565b5091969095509350505050565b600854610ac39082906001600160a01b0316336126d3565b610ac381303361257a565b600b546001600160a01b03163314611be25760405162461bcd60e51b815260206004820152601560248201527f4f6e6c792077697468647261772061646472657373000000000000000000000060448201526064016103c4565b600b546040516001600160a01b03909116904780156108fc02915f818181858888f19350505050158015610ac3573d5f5f3e3d5ffd5b600354610ac39082906001600160a01b03163361257a565b6001546040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03848116602483015260448201849052909116906323b872dd90606401611523565b6040805160018082528183019092525f9160208083019080368337505060025482519293506001600160a01b0316918391505f90611cc857611cc8612e3f565b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092525f9181602001602082028036833701905050905082815f81518110611d1757611d17612e3f565b6020026020010181815250505f3385604051602001611d4b9291906001600160a01b03929092168252602082015260400190565b6040516020818303038152906040529050611d678530336126d3565b600c546040517f5c38449e0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690635c38449e90611db6903090879087908790600401612fdb565b5f604051808303815f87803b158015611dcd575f5ffd5b505af1158015611ddf573d5f5f3e3d5ffd5b505050505050505050565b600b546001600160a01b03163314611e445760405162461bcd60e51b815260206004820152601560248201527f4f6e6c792077697468647261772061646472657373000000000000000000000060448201526064016103c4565b600b546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038381169263a9059cbb9291169083906370a0823190602401602060405180830381865afa158015611eae573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ed29190613062565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af1158015611f32573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aa79190613079565b600154604080517f70617373776f726400000000000000000000000000000000000000000000000060208201528151600881830301815260288201928390527fb88d4fde000000000000000000000000000000000000000000000000000000009092526001600160a01b039092169163b88d4fde916115239133918791879190602c01613098565b600454610ac39082906001600160a01b0316336126d3565b611ffe612849565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b039a8b1617909155600480548216988a1698909817909755600580548816968916969096179095556006805487169488169490941790935560078054861692871692909217909155600880548516918616919091179055600980548416918516919091179055600a80549092169216919091179055565b600a54610ac39082906001600160a01b0316336126d3565b6001546040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018390526001600160a01b03909116906323b872dd906064015f604051808303815f87803b158015612124575f5ffd5b505af1158015612136573d5f5f3e3d5ffd5b50506001546040517f23b872dd000000000000000000000000000000000000000000000000000000008152306004820152336024820152604481018590526001600160a01b0390911692506323b872dd91506064015f604051808303815f87803b1580156121a2575f5ffd5b505af11580156121b4573d5f5f3e3d5ffd5b5050505050565b600c546001600160a01b031633146121d1575f5ffd5b5f5f828060200190518101906121e791906130ce565b60025487519294509092506001600160a01b031690632e1a7d4d9087905f9061221257612212612e3f565b60200260200101516040518263ffffffff1660e01b815260040161223891815260200190565b5f604051808303815f87803b15801561224f575f5ffd5b505af1158015612261573d5f5f3e3d5ffd5b5050505061227081308461257a565b60025485516001600160a01b039091169063d0e30db09087905f9061229757612297612e3f565b60200260200101516040518263ffffffff1660e01b81526004015f604051808303818588803b1580156122c8575f5ffd5b505af11580156122da573d5f5f3e3d5ffd5b5050600254600c5489516001600160a01b03928316955063a9059cbb94509116915088905f9061230c5761230c612e3f565b60200260200101516040518363ffffffff1660e01b81526004016123459291906001600160a01b03929092168252602082015260400190565b6020604051808303815f875af1158015612361573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123859190613079565b50505050505050565b612396612849565b6001600160a01b0381166123d8576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024016103c4565b610ac38161288e565b600454610ac39082906001600160a01b03163361257a565b60605f6124046117fa565b5090505f805b825181101561247057846001600160a01b0316600d5f85848151811061243257612432612e3f565b60209081029190910181015182528101919091526040015f20546001600160a01b031603612468578161246481612f43565b9250505b60010161240a565b505f8167ffffffffffffffff81111561248b5761248b612b2e565b6040519080825280602002602001820160405280156124b4578160200160208202803683370190505b5090505f805b845181101561255757866001600160a01b0316600d5f8784815181106124e2576124e2612e3f565b60209081029190910181015182528101919091526040015f20546001600160a01b03160361254f5784818151811061251c5761251c612e3f565b602002602001015183838151811061253657612536612e3f565b60209081029190910101528161254b81612f43565b9250505b6001016124ba565b509095945050505050565b600354610ac39082906001600160a01b0316336126d3565b5f838152600d60205260409020546001600160a01b038281169116146125e25760405162461bcd60e51b815260206004820152601560248201527f596f7520617265206e6f7420746865206f776e6572000000000000000000000060448201526064016103c4565b6001546040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152838116602483015260448201869052909116906323b872dd906064015f604051808303815f87803b15801561264e575f5ffd5b505af1158015612660573d5f5f3e3d5ffd5b5050505f848152600d602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055516001600160a01b03858116935084169186917f565c65832ac6093eff9de1c5177fbfdb38aca147f3aaaace6abd500d4f98732d9190a4505050565b5f546001600160a01b0316156127515760405162461bcd60e51b815260206004820152603b60248201527f4465706f7369742066756e6374696f6e7320646f206e6f7420776f726b20626560448201527f666f7265206f776e6572736869702069732072656e6f756e636564000000000060648201526084016103c4565b6001546040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152848116602483015260448201869052909116906323b872dd906064015f604051808303815f87803b1580156127bd575f5ffd5b505af11580156127cf573d5f5f3e3d5ffd5b5050505f848152600d602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0386811691821790925591519086169350909186917f922904fc53bfb672c24e84a4677c68c1401935a4290e6f92888d8657487359979190a4505050565b5f546001600160a01b031633146113e1576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016103c4565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381168114610ac3575f5ffd5b5f5f6040838503121561291a575f5ffd5b82359150602083013561292c816128f5565b809150509250929050565b5f60208284031215612947575f5ffd5b5035919050565b5f5f5f60608486031215612960575f5ffd5b833592506020840135612972816128f5565b929592945050506040919091013590565b5f60208284031215612993575f5ffd5b813561299e816128f5565b9392505050565b5f5f604083850312156129b6575f5ffd5b82356129c1816128f5565b946020939093013593505050565b5f5f604083850312156129e0575f5ffd5b50508035926020909101359150565b5f8151808452602084019350602083015f5b82811015612a1f578151865260209586019590910190600101612a01565b5093949350505050565b604081525f612a3b60408301856129ef565b82810360208401528084518083526020830191506020860192505f5b81811015612a7e5783516001600160a01b0316835260209384019390920191600101612a57565b50909695505050505050565b5f5f5f5f5f5f5f5f610100898b031215612aa2575f5ffd5b8835612aad816128f5565b97506020890135612abd816128f5565b96506040890135612acd816128f5565b95506060890135612add816128f5565b94506080890135612aed816128f5565b935060a0890135612afd816128f5565b925060c0890135612b0d816128f5565b915060e0890135612b1d816128f5565b809150509295985092959890939650565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612ba257612ba2612b2e565b604052919050565b5f67ffffffffffffffff821115612bc357612bc3612b2e565b5060051b60200190565b5f82601f830112612bdc575f5ffd5b8135612bef612bea82612baa565b612b5b565b8082825260208201915060208360051b860101925085831115612c10575f5ffd5b602085015b83811015612c2d578035835260209283019201612c15565b5095945050505050565b5f82601f830112612c46575f5ffd5b813567ffffffffffffffff811115612c6057612c60612b2e565b612c9160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612b5b565b818152846020838601011115612ca5575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f5f60808587031215612cd4575f5ffd5b843567ffffffffffffffff811115612cea575f5ffd5b8501601f81018713612cfa575f5ffd5b8035612d08612bea82612baa565b8082825260208201915060208360051b850101925089831115612d29575f5ffd5b6020840193505b82841015612d54578335612d43816128f5565b825260209384019390910190612d30565b9650505050602085013567ffffffffffffffff811115612d72575f5ffd5b612d7e87828801612bcd565b935050604085013567ffffffffffffffff811115612d9a575f5ffd5b612da687828801612bcd565b925050606085013567ffffffffffffffff811115612dc2575f5ffd5b612dce87828801612c37565b91505092959194509250565b602081525f61299e60208301846129ef565b5f60208284031215612dfc575f5ffd5b815161299e816128f5565b5f82612e3a577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500690565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215612e7c575f5ffd5b815167ffffffffffffffff811115612e92575f5ffd5b8201601f81018413612ea2575f5ffd5b8051612eb0612bea82612baa565b8082825260208201915060208360051b850101925086831115612ed1575f5ffd5b6020840193505b82841015612ef3578351825260209384019390910190612ed8565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115612f3d57612f3d612efd565b92915050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612f7357612f73612efd565b5060010190565b5f81518084525f5b81811015612f9e57602081850181015186830182015201612f82565b505f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b5f608082016001600160a01b03871683526080602084015280865180835260a0850191506020880192505f5b8181101561302e5783516001600160a01b0316835260209384019390920191600101613007565b5050838103604085015261304281876129ef565b91505082810360608401526130578185612f7a565b979650505050505050565b5f60208284031215613072575f5ffd5b5051919050565b5f60208284031215613089575f5ffd5b8151801515811461299e575f5ffd5b6001600160a01b03851681526001600160a01b0384166020820152826040820152608060608201525f612ef36080830184612f7a565b5f5f604083850312156130df575f5ffd5b82516130ea816128f5565b602093909301519294929350505056fea164736f6c634300081b000a000000000000000000000000cfed1cc741f68af4778c2eb8efdcfc0f9ab28466000000000000000000000000352628ece5f47a3daffe4c38ff92ba1748bbb5ce000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c8
Deployed Bytecode
0x60806040526004361061032b575f3560e01c8063853828b6116101a4578063b6507250116100eb578063e775cac611610094578063f2fde38b1161006e578063f2fde38b14610a13578063f93e879f14610a32578063fc07749714610a51578063feecf6ed14610a7d576103cf565b8063e775cac6146109b6578063ebae9281146109d5578063f04f2707146109f4576103cf565b8063c867b0bc116100c5578063c867b0bc14610959578063c8b4169f14610978578063d733cfd014610997576103cf565b8063b6507250146108fc578063bb6a37f01461091b578063c7e42b1b1461093a576103cf565b80639be571df1161014d578063a9d3643f11610127578063a9d3643f1461089f578063b06279b7146108be578063b315b265146108dd576103cf565b80639be571df1461084d5780639c3674fc1461086c578063a0ef91df1461088b576103cf565b806394585a041161017e57806394585a04146107d857806395550a3e146107fa5780639a8bfa2b14610819576103cf565b8063853828b61461078957806389c8c4c01461079d5780638da5cb5b146107bc576103cf565b806337a7b7d81161027357806353d06f941161021c578063715018a6116101f6578063715018a61461071857806378edd8101461072c5780637a4050911461074b5780637e900de41461076a576103cf565b806353d06f94146106bb5780635b84e9c3146106da57806362b34c26146106f9576103cf565b80633fc8cef31161024d5780633fc8cef31461065e57806342c02a4b1461067d5780634eab0d271461069c576103cf565b806337a7b7d81461060157806339821949146106205780633ab1a4941461063f576103cf565b80632a5efac8116102d55780632e1c5849116102af5780632e1c5849146105a457806330c571e4146105c357806336cf7c87146105e2576103cf565b80632a5efac8146105475780632a9cde12146105665780632e1a7d4d14610585576103cf565b80631581b600116103065780631581b600146104cd5780631c582cf71461050957806322e3bf7814610528576103cf565b8062f714ce1461047057806304270b2b1461048f5780630757b89d146104ae576103cf565b366103cf57600c546001600160a01b0316331480159061035657506002546001600160a01b03163314155b156103cd5760405162461bcd60e51b8152602060048201526024808201527f596f752063616e27742073656e642045544820746f207468697320636f6e747260448201527f616374210000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b005b3480156103da575f5ffd5b50600c546001600160a01b0316331480159061035657506002546001600160a01b031633146103cd5760405162461bcd60e51b8152602060048201526024808201527f596f752063616e27742073656e642045544820746f207468697320636f6e747260448201527f616374210000000000000000000000000000000000000000000000000000000060648201526084016103c4565b34801561047b575f5ffd5b506103cd61048a366004612909565b610a9c565b34801561049a575f5ffd5b506103cd6104a9366004612937565b610aab565b3480156104b9575f5ffd5b506103cd6104c8366004612937565b610ac6565b3480156104d8575f5ffd5b50600b546104ec906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610514575f5ffd5b506007546104ec906001600160a01b031681565b348015610533575f5ffd5b506103cd610542366004612937565b610ade565b348015610552575f5ffd5b506103cd610561366004612937565b610af6565b348015610571575f5ffd5b506103cd610580366004612937565b610b0e565b348015610590575f5ffd5b506103cd61059f366004612937565b610b26565b3480156105af575f5ffd5b506103cd6105be36600461294e565b6111b8565b3480156105ce575f5ffd5b506103cd6105dd366004612937565b6112d1565b3480156105ed575f5ffd5b506006546104ec906001600160a01b031681565b34801561060c575f5ffd5b506008546104ec906001600160a01b031681565b34801561062b575f5ffd5b506103cd61063a366004612937565b6112e9565b34801561064a575f5ffd5b506103cd610659366004612983565b6112f4565b348015610669575f5ffd5b506002546104ec906001600160a01b031681565b348015610688575f5ffd5b506103cd610697366004612937565b611388565b3480156106a7575f5ffd5b506103cd6106b6366004612937565b6113a0565b3480156106c6575f5ffd5b506009546104ec906001600160a01b031681565b3480156106e5575f5ffd5b506003546104ec906001600160a01b031681565b348015610704575f5ffd5b506103cd610713366004612937565b6113b8565b348015610723575f5ffd5b506103cd6113d0565b348015610737575f5ffd5b506103cd610746366004612937565b6113e3565b348015610756575f5ffd5b506103cd6107653660046129a5565b6113fb565b348015610775575f5ffd5b506005546104ec906001600160a01b031681565b348015610794575f5ffd5b506103cd611554565b3480156107a8575f5ffd5b506103cd6107b73660046129cf565b6115ec565b3480156107c7575f5ffd5b505f546001600160a01b03166104ec565b3480156107e3575f5ffd5b506107ec6117fa565b604051610500929190612a29565b348015610805575f5ffd5b506103cd610814366004612937565b611b65565b348015610824575f5ffd5b506104ec610833366004612937565b600d6020525f90815260409020546001600160a01b031681565b348015610858575f5ffd5b506103cd610867366004612937565b611b7d565b348015610877575f5ffd5b50600a546104ec906001600160a01b031681565b348015610896575f5ffd5b506103cd611b88565b3480156108aa575f5ffd5b506004546104ec906001600160a01b031681565b3480156108c9575f5ffd5b506103cd6108d8366004612937565b611c18565b3480156108e8575f5ffd5b506001546104ec906001600160a01b031681565b348015610907575f5ffd5b506103cd6109163660046129a5565b611c30565b348015610926575f5ffd5b506103cd6109353660046129cf565b611c88565b348015610945575f5ffd5b506103cd610954366004612983565b611dea565b348015610964575f5ffd5b506103cd6109733660046129a5565b611f56565b348015610983575f5ffd5b506103cd610992366004612937565b611fde565b3480156109a2575f5ffd5b506103cd6109b1366004612a8a565b611ff6565b3480156109c1575f5ffd5b506103cd6109d0366004612937565b6120a4565b3480156109e0575f5ffd5b506103cd6109ef366004612937565b6120bc565b3480156109ff575f5ffd5b506103cd610a0e366004612cc1565b6121bb565b348015610a1e575f5ffd5b506103cd610a2d366004612983565b61238e565b348015610a3d575f5ffd5b506103cd610a4c366004612937565b6123e1565b348015610a5c575f5ffd5b50610a70610a6b366004612983565b6123f9565b6040516105009190612dda565b348015610a88575f5ffd5b506103cd610a97366004612937565b612562565b610aa782823361257a565b5050565b600754610ac39082906001600160a01b03163361257a565b50565b600954610ac39082906001600160a01b0316336126d3565b600554610ac39082906001600160a01b03163361257a565b600554610ac39082906001600160a01b0316336126d3565b600a54610ac39082906001600160a01b03163361257a565b6001546040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810183905230916001600160a01b031690636352211e90602401602060405180830381865afa158015610b86573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610baa9190612dec565b6001600160a01b031603610bc357610ac381303361257a565b6003546001546040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b039283169290911690636352211e90602401602060405180830381865afa158015610c2a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c4e9190612dec565b6001600160a01b031603610c7457600354610ac39082906001600160a01b03163361257a565b600480546001546040517f6352211e0000000000000000000000000000000000000000000000000000000081529283018490526001600160a01b0391821692911690636352211e90602401602060405180830381865afa158015610cda573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cfe9190612dec565b6001600160a01b031603610d2457600454610ac39082906001600160a01b03163361257a565b6005546001546040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b039283169290911690636352211e90602401602060405180830381865afa158015610d8b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610daf9190612dec565b6001600160a01b031603610dd557600554610ac39082906001600160a01b03163361257a565b6006546001546040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b039283169290911690636352211e90602401602060405180830381865afa158015610e3c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e609190612dec565b6001600160a01b031603610e8657600654610ac39082906001600160a01b03163361257a565b6007546001546040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b039283169290911690636352211e90602401602060405180830381865afa158015610eed573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f119190612dec565b6001600160a01b031603610f3757600754610ac39082906001600160a01b03163361257a565b6008546001546040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b039283169290911690636352211e90602401602060405180830381865afa158015610f9e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fc29190612dec565b6001600160a01b031603610fe857600854610ac39082906001600160a01b03163361257a565b6009546001546040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b039283169290911690636352211e90602401602060405180830381865afa15801561104f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110739190612dec565b6001600160a01b03160361109957600954610ac39082906001600160a01b03163361257a565b600a546001546040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b039283169290911690636352211e90602401602060405180830381865afa158015611100573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111249190612dec565b6001600160a01b03160361114a57600a54610ac39082906001600160a01b03163361257a565b60405162461bcd60e51b815260206004820152602660248201527f546f6b656e206e6f7420666f756e6420696e20616e79207370656369616c206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016103c4565b6001546040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03848116602483015260448201849052909116906323b872dd906064015f604051808303815f87803b158015611222575f5ffd5b505af1158015611234573d5f5f3e3d5ffd5b505050505f60644244604051602001611257929190918252602082015260400190565b604051602081830303815290604052805190602001205f1c6112799190612e07565b9050838111156112cb5760405162461bcd60e51b815260206004820152600f60248201527f596f752061726520756e6c75636b79000000000000000000000000000000000060448201526064016103c4565b50505050565b600654610ac39082906001600160a01b0316336126d3565b610ac38130336126d3565b600b546001600160a01b0316331461134e5760405162461bcd60e51b815260206004820152601560248201527f4f6e6c792077697468647261772061646472657373000000000000000000000060448201526064016103c4565b600b80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b600754610ac39082906001600160a01b0316336126d3565b600854610ac39082906001600160a01b03163361257a565b600954610ac39082906001600160a01b03163361257a565b6113d8612849565b6113e15f61288e565b565b600654610ac39082906001600160a01b03163361257a565b600b546001600160a01b031633146114555760405162461bcd60e51b815260206004820152601560248201527f4f6e6c792077697468647261772061646472657373000000000000000000000060448201526064016103c4565b6001546001600160a01b03908116908316036114cf575f818152600d60205260409020546001600160a01b0316156114cf5760405162461bcd60e51b815260206004820152600c60248201527f4f776e657220657869737473000000000000000000000000000000000000000060448201526064016103c4565b600b546040517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03918216602482015260448101839052908316906323b872dd906064015b5f604051808303815f87803b15801561153a575f5ffd5b505af115801561154c573d5f5f3e3d5ffd5b505050505050565b5f61155e336123f9565b80519091505f8190036115b35760405162461bcd60e51b815260206004820152601360248201527f4e6f20746f6b656e73206465706f73697465640000000000000000000000000060448201526064016103c4565b5f5b818110156115e7576115df8382815181106115d2576115d2612e3f565b6020026020010151610b26565b6001016115b5565b505050565b5f5b8181101561171157611601600282612e07565b5f0361168a576001546040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018590526001600160a01b03909116906323b872dd906064015f604051808303815f87803b15801561166f575f5ffd5b505af1158015611681573d5f5f3e3d5ffd5b50505050611709565b6001546040517f23b872dd000000000000000000000000000000000000000000000000000000008152306004820152336024820152604481018590526001600160a01b03909116906323b872dd906064015f604051808303815f87803b1580156116f2575f5ffd5b505af1158015611704573d5f5f3e3d5ffd5b505050505b6001016115ee565b506001546040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810184905230916001600160a01b031690636352211e90602401602060405180830381865afa158015611772573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117969190612dec565b6001600160a01b031603610aa7576001546040517f23b872dd000000000000000000000000000000000000000000000000000000008152306004820152336024820152604481018490526001600160a01b03909116906323b872dd90606401611523565b60408051610120810182523081526004546001600160a01b039081166020830152600554811692820192909252600654821660608281019190915260075483166080830152600854831660a0830152600954831660c0830152600a54831660e083015260035490921661010082015281905f805b6009811015611952576001546001600160a01b0316635a3f267284836009811061189a5761189a612e3f565b60200201516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b0390911660048201526024015f60405180830381865afa1580156118f8573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261193d9190810190612e6c565b516119489083612f2a565b915060010161186e565b505f8167ffffffffffffffff81111561196d5761196d612b2e565b604051908082528060200260200182016040528015611996578160200160208202803683370190505b5090505f8267ffffffffffffffff8111156119b3576119b3612b2e565b6040519080825280602002602001820160405280156119dc578160200160208202803683370190505b5090505f805b6009811015611b58576001545f906001600160a01b0316635a3f2672888460098110611a1057611a10612e3f565b60200201516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b0390911660048201526024015f60405180830381865afa158015611a6e573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611ab39190810190612e6c565b90505f5b8151811015611b4e57818181518110611ad257611ad2612e3f565b6020026020010151868581518110611aec57611aec612e3f565b602002602001018181525050878360098110611b0a57611b0a612e3f565b6020020151858581518110611b2157611b21612e3f565b6001600160a01b039092166020928302919091019091015283611b4381612f43565b945050600101611ab7565b50506001016119e2565b5091969095509350505050565b600854610ac39082906001600160a01b0316336126d3565b610ac381303361257a565b600b546001600160a01b03163314611be25760405162461bcd60e51b815260206004820152601560248201527f4f6e6c792077697468647261772061646472657373000000000000000000000060448201526064016103c4565b600b546040516001600160a01b03909116904780156108fc02915f818181858888f19350505050158015610ac3573d5f5f3e3d5ffd5b600354610ac39082906001600160a01b03163361257a565b6001546040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03848116602483015260448201849052909116906323b872dd90606401611523565b6040805160018082528183019092525f9160208083019080368337505060025482519293506001600160a01b0316918391505f90611cc857611cc8612e3f565b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092525f9181602001602082028036833701905050905082815f81518110611d1757611d17612e3f565b6020026020010181815250505f3385604051602001611d4b9291906001600160a01b03929092168252602082015260400190565b6040516020818303038152906040529050611d678530336126d3565b600c546040517f5c38449e0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690635c38449e90611db6903090879087908790600401612fdb565b5f604051808303815f87803b158015611dcd575f5ffd5b505af1158015611ddf573d5f5f3e3d5ffd5b505050505050505050565b600b546001600160a01b03163314611e445760405162461bcd60e51b815260206004820152601560248201527f4f6e6c792077697468647261772061646472657373000000000000000000000060448201526064016103c4565b600b546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038381169263a9059cbb9291169083906370a0823190602401602060405180830381865afa158015611eae573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ed29190613062565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af1158015611f32573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aa79190613079565b600154604080517f70617373776f726400000000000000000000000000000000000000000000000060208201528151600881830301815260288201928390527fb88d4fde000000000000000000000000000000000000000000000000000000009092526001600160a01b039092169163b88d4fde916115239133918791879190602c01613098565b600454610ac39082906001600160a01b0316336126d3565b611ffe612849565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b039a8b1617909155600480548216988a1698909817909755600580548816968916969096179095556006805487169488169490941790935560078054861692871692909217909155600880548516918616919091179055600980548416918516919091179055600a80549092169216919091179055565b600a54610ac39082906001600160a01b0316336126d3565b6001546040517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018390526001600160a01b03909116906323b872dd906064015f604051808303815f87803b158015612124575f5ffd5b505af1158015612136573d5f5f3e3d5ffd5b50506001546040517f23b872dd000000000000000000000000000000000000000000000000000000008152306004820152336024820152604481018590526001600160a01b0390911692506323b872dd91506064015f604051808303815f87803b1580156121a2575f5ffd5b505af11580156121b4573d5f5f3e3d5ffd5b5050505050565b600c546001600160a01b031633146121d1575f5ffd5b5f5f828060200190518101906121e791906130ce565b60025487519294509092506001600160a01b031690632e1a7d4d9087905f9061221257612212612e3f565b60200260200101516040518263ffffffff1660e01b815260040161223891815260200190565b5f604051808303815f87803b15801561224f575f5ffd5b505af1158015612261573d5f5f3e3d5ffd5b5050505061227081308461257a565b60025485516001600160a01b039091169063d0e30db09087905f9061229757612297612e3f565b60200260200101516040518263ffffffff1660e01b81526004015f604051808303818588803b1580156122c8575f5ffd5b505af11580156122da573d5f5f3e3d5ffd5b5050600254600c5489516001600160a01b03928316955063a9059cbb94509116915088905f9061230c5761230c612e3f565b60200260200101516040518363ffffffff1660e01b81526004016123459291906001600160a01b03929092168252602082015260400190565b6020604051808303815f875af1158015612361573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123859190613079565b50505050505050565b612396612849565b6001600160a01b0381166123d8576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024016103c4565b610ac38161288e565b600454610ac39082906001600160a01b03163361257a565b60605f6124046117fa565b5090505f805b825181101561247057846001600160a01b0316600d5f85848151811061243257612432612e3f565b60209081029190910181015182528101919091526040015f20546001600160a01b031603612468578161246481612f43565b9250505b60010161240a565b505f8167ffffffffffffffff81111561248b5761248b612b2e565b6040519080825280602002602001820160405280156124b4578160200160208202803683370190505b5090505f805b845181101561255757866001600160a01b0316600d5f8784815181106124e2576124e2612e3f565b60209081029190910181015182528101919091526040015f20546001600160a01b03160361254f5784818151811061251c5761251c612e3f565b602002602001015183838151811061253657612536612e3f565b60209081029190910101528161254b81612f43565b9250505b6001016124ba565b509095945050505050565b600354610ac39082906001600160a01b0316336126d3565b5f838152600d60205260409020546001600160a01b038281169116146125e25760405162461bcd60e51b815260206004820152601560248201527f596f7520617265206e6f7420746865206f776e6572000000000000000000000060448201526064016103c4565b6001546040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152838116602483015260448201869052909116906323b872dd906064015f604051808303815f87803b15801561264e575f5ffd5b505af1158015612660573d5f5f3e3d5ffd5b5050505f848152600d602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055516001600160a01b03858116935084169186917f565c65832ac6093eff9de1c5177fbfdb38aca147f3aaaace6abd500d4f98732d9190a4505050565b5f546001600160a01b0316156127515760405162461bcd60e51b815260206004820152603b60248201527f4465706f7369742066756e6374696f6e7320646f206e6f7420776f726b20626560448201527f666f7265206f776e6572736869702069732072656e6f756e636564000000000060648201526084016103c4565b6001546040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152848116602483015260448201869052909116906323b872dd906064015f604051808303815f87803b1580156127bd575f5ffd5b505af11580156127cf573d5f5f3e3d5ffd5b5050505f848152600d602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0386811691821790925591519086169350909186917f922904fc53bfb672c24e84a4677c68c1401935a4290e6f92888d8657487359979190a4505050565b5f546001600160a01b031633146113e1576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016103c4565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381168114610ac3575f5ffd5b5f5f6040838503121561291a575f5ffd5b82359150602083013561292c816128f5565b809150509250929050565b5f60208284031215612947575f5ffd5b5035919050565b5f5f5f60608486031215612960575f5ffd5b833592506020840135612972816128f5565b929592945050506040919091013590565b5f60208284031215612993575f5ffd5b813561299e816128f5565b9392505050565b5f5f604083850312156129b6575f5ffd5b82356129c1816128f5565b946020939093013593505050565b5f5f604083850312156129e0575f5ffd5b50508035926020909101359150565b5f8151808452602084019350602083015f5b82811015612a1f578151865260209586019590910190600101612a01565b5093949350505050565b604081525f612a3b60408301856129ef565b82810360208401528084518083526020830191506020860192505f5b81811015612a7e5783516001600160a01b0316835260209384019390920191600101612a57565b50909695505050505050565b5f5f5f5f5f5f5f5f610100898b031215612aa2575f5ffd5b8835612aad816128f5565b97506020890135612abd816128f5565b96506040890135612acd816128f5565b95506060890135612add816128f5565b94506080890135612aed816128f5565b935060a0890135612afd816128f5565b925060c0890135612b0d816128f5565b915060e0890135612b1d816128f5565b809150509295985092959890939650565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612ba257612ba2612b2e565b604052919050565b5f67ffffffffffffffff821115612bc357612bc3612b2e565b5060051b60200190565b5f82601f830112612bdc575f5ffd5b8135612bef612bea82612baa565b612b5b565b8082825260208201915060208360051b860101925085831115612c10575f5ffd5b602085015b83811015612c2d578035835260209283019201612c15565b5095945050505050565b5f82601f830112612c46575f5ffd5b813567ffffffffffffffff811115612c6057612c60612b2e565b612c9160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612b5b565b818152846020838601011115612ca5575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f5f60808587031215612cd4575f5ffd5b843567ffffffffffffffff811115612cea575f5ffd5b8501601f81018713612cfa575f5ffd5b8035612d08612bea82612baa565b8082825260208201915060208360051b850101925089831115612d29575f5ffd5b6020840193505b82841015612d54578335612d43816128f5565b825260209384019390910190612d30565b9650505050602085013567ffffffffffffffff811115612d72575f5ffd5b612d7e87828801612bcd565b935050604085013567ffffffffffffffff811115612d9a575f5ffd5b612da687828801612bcd565b925050606085013567ffffffffffffffff811115612dc2575f5ffd5b612dce87828801612c37565b91505092959194509250565b602081525f61299e60208301846129ef565b5f60208284031215612dfc575f5ffd5b815161299e816128f5565b5f82612e3a577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500690565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215612e7c575f5ffd5b815167ffffffffffffffff811115612e92575f5ffd5b8201601f81018413612ea2575f5ffd5b8051612eb0612bea82612baa565b8082825260208201915060208360051b850101925086831115612ed1575f5ffd5b6020840193505b82841015612ef3578351825260209384019390910190612ed8565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115612f3d57612f3d612efd565b92915050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612f7357612f73612efd565b5060010190565b5f81518084525f5b81811015612f9e57602081850181015186830182015201612f82565b505f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b5f608082016001600160a01b03871683526080602084015280865180835260a0850191506020880192505f5b8181101561302e5783516001600160a01b0316835260209384019390920191600101613007565b5050838103604085015261304281876129ef565b91505082810360608401526130578185612f7a565b979650505050505050565b5f60208284031215613072575f5ffd5b5051919050565b5f60208284031215613089575f5ffd5b8151801515811461299e575f5ffd5b6001600160a01b03851681526001600160a01b0384166020820152826040820152608060608201525f612ef36080830184612f7a565b5f5f604083850312156130df575f5ffd5b82516130ea816128f5565b602093909301519294929350505056fea164736f6c634300081b000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000cfed1cc741f68af4778c2eb8efdcfc0f9ab28466000000000000000000000000352628ece5f47a3daffe4c38ff92ba1748bbb5ce000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c8
-----Decoded View---------------
Arg [0] : _honestWork (address): 0xCfED1cC741F68AF4778c2Eb8efDcFc0F9ab28466
Arg [1] : _withdrawAddress (address): 0x352628EcE5f47A3daFFE4c38FF92Ba1748bBB5cE
Arg [2] : _vault (address): 0xBA12222222228d8Ba445958a75a0704d566BF2C8
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000cfed1cc741f68af4778c2eb8efdcfc0f9ab28466
Arg [1] : 000000000000000000000000352628ece5f47a3daffe4c38ff92ba1748bbb5ce
Arg [2] : 000000000000000000000000ba12222222228d8ba445958a75a0704d566bf2c8
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
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.