Source Code
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers.
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | ||||
|---|---|---|---|---|---|---|---|
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH | |||||
| 18221380 | 2 days ago | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
AuctionMiddleMan
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import {Governance} from "@periphery/utils/Governance.sol";
import {IAuction} from "./interfaces/IAuction.sol";
import {IStrategyInterface} from "./interfaces/IStrategyInterface.sol";
import {IDistributionCreator, CampaignParameters} from "./interfaces/IDistributionCreator.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
interface IAuctionFactory {
function createNewAuction(
address _want,
address _receiver,
address _governance
) external returns (address);
}
/// @title AuctionMiddleMan
/// @dev Serves as the `auction` contract for strategies that receive KAT tokens.
/// Will simply forward any kicks to a real auction contract for non-KAT tokens.
/// For KAT tokens, it will create a campaign with MERKL for the amount kicked.
contract AuctionMiddleMan is Governance {
using SafeERC20 for ERC20;
event StrategyAdded(address indexed strategy);
event StrategyRemoved(address indexed strategy);
event CampaignDurationSet(uint32 campaignDuration);
event KatFeeSet(uint256 katFee);
event FeeRecipientSet(address feeRecipient);
struct Strategy {
address auction;
bytes campaignData;
}
modifier onlyAddedStrategy() {
require(
_isAddedStrategy(msg.sender),
"AuctionMiddleMan: Not a strategy"
);
_;
}
function _isAddedStrategy(address _strategy) internal view returns (bool) {
return strategies[_strategy].auction != address(0);
}
IAuctionFactory public constant AUCTION_FACTORY =
IAuctionFactory(0xCfA510188884F199fcC6e750764FAAbE6e56ec40);
IDistributionCreator public constant DISTRIBUTION_CREATOR =
IDistributionCreator(0x8BB4C975Ff3c250e0ceEA271728547f3802B36Fd);
address public constant KAT = 0x7F1f4b4b29f5058fA32CC7a97141b8D7e5ABDC2d;
address public constant WKAT = 0x6E9C1F88a960fE63387eb4b71BC525a9313d8461;
mapping(address => Strategy) public strategies;
uint256 public lastKatBalance;
uint32 public campaignDuration;
uint256 public katFee;
address public feeRecipient;
constructor(
address _governance,
address _feeRecipient
) Governance(_governance) {
campaignDuration = 1 weeks;
DISTRIBUTION_CREATOR.acceptConditions();
katFee = 500;
feeRecipient = _feeRecipient;
}
function addStrategy(
address _strategy,
bytes calldata _campaignData
) external onlyGovernance {
require(
!_isAddedStrategy(_strategy),
"AuctionMiddleMan: Strategy already added"
);
require(_campaignData.length > 0, "AuctionMiddleMan: campaign data");
address asset = IStrategyInterface(_strategy).asset();
address management = IStrategyInterface(_strategy).management();
address auction = AUCTION_FACTORY.createNewAuction(
asset, // want
_strategy, // receiver
management // governance
);
strategies[_strategy] = Strategy({
auction: auction,
campaignData: _campaignData
});
emit StrategyAdded(_strategy);
}
function removeStrategy(address _strategy) external onlyGovernance {
require(
_isAddedStrategy(_strategy),
"AuctionMiddleMan: Strategy not added"
);
delete strategies[_strategy];
emit StrategyRemoved(_strategy);
}
function setAuction(
address _strategy,
address _auction
) external onlyGovernance {
require(
_isAddedStrategy(_strategy),
"AuctionMiddleMan: Strategy not added"
);
require(_auction != address(0), "AuctionMiddleMan: zero address");
strategies[_strategy].auction = _auction;
}
function setCampaignData(
address _strategy,
bytes calldata _campaignData
) external onlyGovernance {
require(
_isAddedStrategy(_strategy),
"AuctionMiddleMan: Strategy not added"
);
require(_campaignData.length > 0, "AuctionMiddleMan: campaign data");
strategies[_strategy].campaignData = _campaignData;
}
function setCampaignDuration(
uint32 _campaignDuration
) external onlyGovernance {
require(
_campaignDuration > 1 days,
"AuctionMiddleMan: Campaign duration"
);
campaignDuration = _campaignDuration;
emit CampaignDurationSet(_campaignDuration);
}
function setKatFee(uint256 _katFee) external onlyGovernance {
require(_katFee <= 1000, "AuctionMiddleMan: kat fee");
katFee = _katFee;
emit KatFeeSet(_katFee);
}
function setFeeRecipient(address _feeRecipient) external onlyGovernance {
require(_feeRecipient != address(0), "AuctionMiddleMan: zero address");
feeRecipient = _feeRecipient;
emit FeeRecipientSet(_feeRecipient);
}
function want() external view returns (address) {
return IStrategyInterface(msg.sender).asset();
}
function receiver() external view returns (address) {
return msg.sender;
}
function isActive(address _token) external view returns (bool) {
return IAuction(strategies[msg.sender].auction).isActive(_token);
}
function available(address _token) external view returns (uint256) {
return IAuction(strategies[msg.sender].auction).available(_token);
}
function kick(address _token) external onlyAddedStrategy returns (uint256) {
if (_token == KAT || _token == WKAT) {
return _createCampaign(strategies[msg.sender].campaignData);
} else {
uint256 _kicked = ERC20(_token).balanceOf(address(this));
address auction = strategies[msg.sender].auction;
if (_kicked > 0) {
ERC20(_token).safeTransfer(auction, _kicked);
}
return IAuction(auction).kick(_token);
}
}
function _createCampaign(
bytes memory _campaignData
) internal returns (uint256) {
uint256 katBalance = ERC20(KAT).balanceOf(address(this));
uint256 kicked = katBalance - lastKatBalance;
if (kicked == 0) return 0;
require(
ERC20(WKAT).balanceOf(address(this)) >= kicked,
"AuctionMiddleMan: not enough WKAT"
);
if (katFee > 0) {
uint256 fee = (kicked * katFee) / 10_000;
kicked -= fee;
katBalance -= fee;
ERC20(KAT).safeTransfer(feeRecipient, fee);
}
// Update lastKatBalance for next kick
lastKatBalance = katBalance;
ERC20(WKAT).forceApprove(address(DISTRIBUTION_CREATOR), kicked);
DISTRIBUTION_CREATOR.createCampaign(
CampaignParameters({
campaignId: bytes32(0),
creator: address(0),
rewardToken: WKAT,
amount: kicked,
campaignType: 18,
startTimestamp: uint32(block.timestamp),
duration: campaignDuration,
campaignData: _campaignData
})
);
return kicked;
}
function wrapKat(uint256 _amount) external onlyGovernance {
require(
ERC20(KAT).balanceOf(address(this)) >= _amount,
"AuctionMiddleMan: not enough KAT"
);
ERC20(KAT).safeTransfer(WKAT, _amount);
lastKatBalance -= _amount;
}
function syncKatBalance() external onlyGovernance {
lastKatBalance = ERC20(KAT).balanceOf(address(this));
}
function sweep(
address _token,
uint256 _amount,
address _to
) external onlyGovernance {
uint256 balance = ERC20(_token).balanceOf(address(this));
if (balance < _amount) {
_amount = balance;
}
if (_token == KAT) {
lastKatBalance -= _amount;
}
ERC20(_token).safeTransfer(_to, _amount);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/IERC4626.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";
/**
* @dev Interface of the ERC-4626 "Tokenized Vault Standard", as defined in
* https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
*/
interface IERC4626 is IERC20, IERC20Metadata {
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed sender,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
/**
* @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function asset() external view returns (address assetTokenAddress);
/**
* @dev Returns the total amount of the underlying asset that is “managed” by Vault.
*
* - SHOULD include any compounding that occurs from yield.
* - MUST be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT revert.
*/
function totalAssets() external view returns (uint256 totalManagedAssets);
/**
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
/**
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
* through a deposit call.
*
* - MUST return a limited value if receiver is subject to some deposit limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
* - MUST NOT revert.
*/
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
* call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
* in the same transaction.
* - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
* deposit would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/**
* @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* deposit execution, and are accounted for during deposit.
* - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
* - MUST return a limited value if receiver is subject to some mint limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
* - MUST NOT revert.
*/
function maxMint(address receiver) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
* in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
* same transaction.
* - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
* would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by minting.
*/
function previewMint(uint256 shares) external view returns (uint256 assets);
/**
* @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
* execution, and are accounted for during mint.
* - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
* call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
* called
* in the same transaction.
* - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
* the withdrawal would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/**
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* withdraw execution, and are accounted for during withdraw.
* - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
* through a redeem call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxRedeem(address owner) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
* in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
* same transaction.
* - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
* redemption would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by redeeming.
*/
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/**
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* redeem execution, and are accounted for during redeem.
* - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard ERC-20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC-721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC-1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC-20
* applications.
*/
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
mapping(address account => uint256) private _balances;
mapping(address account => mapping(address spender => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* Both values are immutable: they can only be set once during construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `value`.
*/
function transfer(address to, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_transfer(owner, to, value);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, value);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Skips emitting an {Approval} event indicating an allowance update. This is not
* required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `value`.
* - the caller must have allowance for ``from``'s tokens of at least
* `value`.
*/
function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, value);
_transfer(from, to, value);
return true;
}
/**
* @dev Moves a `value` amount of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _transfer(address from, address to, uint256 value) internal {
if (from == address(0)) {
revert ERC20InvalidSender(address(0));
}
if (to == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(from, to, value);
}
/**
* @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
* (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
* this function.
*
* Emits a {Transfer} event.
*/
function _update(address from, address to, uint256 value) internal virtual {
if (from == address(0)) {
// Overflow check required: The rest of the code assumes that totalSupply never overflows
_totalSupply += value;
} else {
uint256 fromBalance = _balances[from];
if (fromBalance < value) {
revert ERC20InsufficientBalance(from, fromBalance, value);
}
unchecked {
// Overflow not possible: value <= fromBalance <= totalSupply.
_balances[from] = fromBalance - value;
}
}
if (to == address(0)) {
unchecked {
// Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
_totalSupply -= value;
}
} else {
unchecked {
// Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
_balances[to] += value;
}
}
emit Transfer(from, to, value);
}
/**
* @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
* Relies on the `_update` mechanism
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _mint(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(address(0), account, value);
}
/**
* @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
* Relies on the `_update` mechanism.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead
*/
function _burn(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidSender(address(0));
}
_update(account, address(0), value);
}
/**
* @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address owner, address spender, uint256 value) internal {
_approve(owner, spender, value, true);
}
/**
* @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
*
* By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
* `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
* `Approval` event during `transferFrom` operations.
*
* Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
* true using the following override:
*
* ```solidity
* function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
* super._approve(owner, spender, value, true);
* }
* ```
*
* Requirements are the same as {_approve}.
*/
function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
if (owner == address(0)) {
revert ERC20InvalidApprover(address(0));
}
if (spender == address(0)) {
revert ERC20InvalidSpender(address(0));
}
_allowances[owner][spender] = value;
if (emitEvent) {
emit Approval(owner, spender, value);
}
}
/**
* @dev Updates `owner`'s allowance for `spender` based on spent `value`.
*
* Does not update the allowance value in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Does not emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance < type(uint256).max) {
if (currentAllowance < value) {
revert ERC20InsufficientAllowance(spender, currentAllowance, value);
}
unchecked {
_approve(owner, spender, currentAllowance - value, false);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) 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 a `value` amount of tokens 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 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC-20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// 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
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* 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[ERC 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);
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.18;
import {IStrategy} from "@tokenized-strategy/interfaces/IStrategy.sol";
interface IBaseHealthCheck is IStrategy {
function doHealthCheck() external view returns (bool);
function profitLimitRatio() external view returns (uint256);
function lossLimitRatio() external view returns (uint256);
function setProfitLimitRatio(uint256 _newProfitLimitRatio) external;
function setLossLimitRatio(uint256 _newLossLimitRatio) external;
function setDoHealthCheck(bool _doHealthCheck) external;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.18;
contract Governance {
/// @notice Emitted when the governance address is updated.
event GovernanceTransferred(
address indexed previousGovernance,
address indexed newGovernance
);
modifier onlyGovernance() {
_checkGovernance();
_;
}
/// @notice Checks if the msg sender is the governance.
function _checkGovernance() internal view virtual {
require(governance == msg.sender, "!governance");
}
/// @notice Address that can set the default base fee and provider
address public governance;
constructor(address _governance) {
governance = _governance;
emit GovernanceTransferred(address(0), _governance);
}
/**
* @notice Sets a new address as the governance of the contract.
* @dev Throws if the caller is not current governance.
* @param _newGovernance The new governance address.
*/
function transferGovernance(
address _newGovernance
) external virtual onlyGovernance {
require(_newGovernance != address(0), "ZERO ADDRESS");
address oldGovernance = governance;
governance = _newGovernance;
emit GovernanceTransferred(oldGovernance, _newGovernance);
}
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.18;
interface IBaseStrategy {
function tokenizedStrategyAddress() external view returns (address);
/*//////////////////////////////////////////////////////////////
IMMUTABLE FUNCTIONS
//////////////////////////////////////////////////////////////*/
function availableDepositLimit(
address _owner
) external view returns (uint256);
function availableWithdrawLimit(
address _owner
) external view returns (uint256);
function deployFunds(uint256 _assets) external;
function freeFunds(uint256 _amount) external;
function harvestAndReport() external returns (uint256);
function tendThis(uint256 _totalIdle) external;
function shutdownWithdraw(uint256 _amount) external;
function tendTrigger() external view returns (bool, bytes memory);
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.18;
import {ITokenizedStrategy} from "./ITokenizedStrategy.sol";
import {IBaseStrategy} from "./IBaseStrategy.sol";
interface IStrategy is IBaseStrategy, ITokenizedStrategy {}// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.18;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import {IERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";
// Interface that implements the 4626 standard and the implementation functions
interface ITokenizedStrategy is IERC4626, IERC20Permit {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event StrategyShutdown();
event NewTokenizedStrategy(
address indexed strategy,
address indexed asset,
string apiVersion
);
event Reported(
uint256 profit,
uint256 loss,
uint256 protocolFees,
uint256 performanceFees
);
event UpdatePerformanceFeeRecipient(
address indexed newPerformanceFeeRecipient
);
event UpdateKeeper(address indexed newKeeper);
event UpdatePerformanceFee(uint16 newPerformanceFee);
event UpdateManagement(address indexed newManagement);
event UpdateEmergencyAdmin(address indexed newEmergencyAdmin);
event UpdateProfitMaxUnlockTime(uint256 newProfitMaxUnlockTime);
event UpdatePendingManagement(address indexed newPendingManagement);
/*//////////////////////////////////////////////////////////////
INITIALIZATION
//////////////////////////////////////////////////////////////*/
function initialize(
address _asset,
string memory _name,
address _management,
address _performanceFeeRecipient,
address _keeper
) external;
/*//////////////////////////////////////////////////////////////
NON-STANDARD 4626 OPTIONS
//////////////////////////////////////////////////////////////*/
function withdraw(
uint256 assets,
address receiver,
address owner,
uint256 maxLoss
) external returns (uint256);
function redeem(
uint256 shares,
address receiver,
address owner,
uint256 maxLoss
) external returns (uint256);
function maxWithdraw(
address owner,
uint256 /*maxLoss*/
) external view returns (uint256);
function maxRedeem(
address owner,
uint256 /*maxLoss*/
) external view returns (uint256);
/*//////////////////////////////////////////////////////////////
MODIFIER HELPERS
//////////////////////////////////////////////////////////////*/
function requireManagement(address _sender) external view;
function requireKeeperOrManagement(address _sender) external view;
function requireEmergencyAuthorized(address _sender) external view;
/*//////////////////////////////////////////////////////////////
KEEPERS FUNCTIONS
//////////////////////////////////////////////////////////////*/
function tend() external;
function report() external returns (uint256 _profit, uint256 _loss);
/*//////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////*/
function MAX_FEE() external view returns (uint16);
function FACTORY() external view returns (address);
/*//////////////////////////////////////////////////////////////
GETTERS
//////////////////////////////////////////////////////////////*/
function apiVersion() external view returns (string memory);
function pricePerShare() external view returns (uint256);
function management() external view returns (address);
function pendingManagement() external view returns (address);
function keeper() external view returns (address);
function emergencyAdmin() external view returns (address);
function performanceFee() external view returns (uint16);
function performanceFeeRecipient() external view returns (address);
function fullProfitUnlockDate() external view returns (uint256);
function profitUnlockingRate() external view returns (uint256);
function profitMaxUnlockTime() external view returns (uint256);
function lastReport() external view returns (uint256);
function isShutdown() external view returns (bool);
function unlockedShares() external view returns (uint256);
/*//////////////////////////////////////////////////////////////
SETTERS
//////////////////////////////////////////////////////////////*/
function setPendingManagement(address) external;
function acceptManagement() external;
function setKeeper(address _keeper) external;
function setEmergencyAdmin(address _emergencyAdmin) external;
function setPerformanceFee(uint16 _performanceFee) external;
function setPerformanceFeeRecipient(
address _performanceFeeRecipient
) external;
function setProfitMaxUnlockTime(uint256 _profitMaxUnlockTime) external;
function setName(string calldata _newName) external;
function shutdownStrategy() external;
function emergencyWithdraw(uint256 _amount) external;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.18;
interface IAuction {
event AuctionDisabled(address indexed from, address indexed to);
event AuctionEnabled(address indexed from, address indexed to);
event AuctionKicked(address from, uint256 available);
event GovernanceTransferred(
address indexed previousGovernance,
address indexed newGovernance
);
event UpdatePendingGovernance(address indexed newPendingGovernance);
event UpdatedStartingPrice(uint256 startingPrice);
struct AuctionInfo {
uint64 kicked;
uint64 scaler;
uint128 initialAvailable;
}
function acceptGovernance() external;
function auctionLength() external view returns (uint256);
function auctions(address) external view returns (AuctionInfo memory);
function available(address _from) external view returns (uint256);
function disable(address _from) external;
function disable(address _from, uint256 _index) external;
function enable(address _from) external;
function enabledAuctions(uint256) external view returns (address);
function getAllEnabledAuctions() external view returns (address[] memory);
function getAmountNeeded(address _from) external view returns (uint256);
function getAmountNeeded(
address _from,
uint256 _amountToTake,
uint256 _timestamp
) external view returns (uint256);
function getAmountNeeded(
address _from,
uint256 _amountToTake
) external view returns (uint256);
function governance() external view returns (address);
function initialize(
address _want,
address _receiver,
address _governance,
uint256 _auctionLength,
uint256 _startingPrice
) external;
function isActive(address _from) external view returns (bool);
function isValidSignature(
bytes32 _hash,
bytes calldata signature
) external view returns (bytes4);
function kick(address _from) external returns (uint256 _available);
function kickable(address _from) external view returns (uint256);
function kicked(address _from) external view returns (uint256);
function pendingGovernance() external view returns (address);
function price(
address _from,
uint256 _timestamp
) external view returns (uint256);
function price(address _from) external view returns (uint256);
function receiver() external view returns (address);
function setStartingPrice(uint256 _startingPrice) external;
function settle(address _from) external;
function startingPrice() external view returns (uint256);
function sweep(address _token) external;
function take(address _from) external returns (uint256);
function take(address _from, uint256 _maxAmount) external returns (uint256);
function take(
address _from,
uint256 _maxAmount,
address _receiver,
bytes calldata _data
) external returns (uint256);
function take(
address _from,
uint256 _maxAmount,
address _receiver
) external returns (uint256);
function transferGovernance(address _newGovernance) external;
function want() external view returns (address);
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
struct CampaignParameters {
// POPULATED ONCE CREATED
// ID of the campaign. This can be left as a null bytes32 when creating campaigns
// on Merkl.
bytes32 campaignId;
// CHOSEN BY CAMPAIGN CREATOR
// Address of the campaign creator, if marked as address(0), it will be overriden with the
// address of the `msg.sender` creating the campaign
address creator;
// Address of the token used as a reward
address rewardToken;
// Amount of `rewardToken` to distribute across all the epochs
// Amount distributed per epoch is `amount/numEpoch`
uint256 amount;
// Type of campaign
uint32 campaignType;
// Timestamp at which the campaign should start
uint32 startTimestamp;
// Duration of the campaign in seconds. Has to be a multiple of EPOCH = 3600
uint32 duration;
// Extra data to pass to specify the campaign
bytes campaignData;
}
interface IDistributionCreator {
function createCampaign(
CampaignParameters calldata _campaignParameters
) external returns (bytes32);
function acceptConditions() external;
}pragma solidity ^0.8.18;
interface IMerklDistributor {
/// @notice Claims rewards for a given set of users
/// @dev Anyone may call this function for anyone else, funds go to destination regardless, it's just a question of
/// who provides the proof and pays the gas: `msg.sender` is used only for addresses that require a trusted operator
/// @param users Recipient of tokens
/// @param tokens ERC20 claimed
/// @param amounts Amount of tokens that will be sent to the corresponding users
/// @param proofs Array of hashes bridging from a leaf `(hash of user | token | amount)` to the Merkle root
function claim(
address[] calldata users,
address[] calldata tokens,
uint256[] calldata amounts,
bytes32[][] calldata proofs
) external;
}// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.18;
import {IBaseHealthCheck} from "@periphery/Bases/HealthCheck/IBaseHealthCheck.sol";
import {IMerklDistributor} from "./IMerklDistributor.sol";
interface IStrategyInterface is IBaseHealthCheck {
function lpValueInAsset()
external
view
returns (uint256 valueLpInAssetTerms);
function STEER_LP() external view returns (address);
function MERKL_DISTRIBUTOR() external view returns (IMerklDistributor);
function estimatedTotalAsset() external view returns (uint256);
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata _data
) external;
// Management parameters
function targetIdleAssetBps() external view returns (uint16);
function targetIdleBufferBps() external view returns (uint16);
function pairedTokenDiscountBps() external view returns (uint16);
function depositLimit() external view returns (uint256);
function maxSwapValue() external view returns (uint256);
function minAsset() external view returns (uint128);
function useAuctions() external view returns (bool);
function auction() external view returns (address);
function minTendWait() external view returns (uint24);
function maxTendBaseFeeGwei() external view returns (uint8);
function lastTend() external view returns (uint64);
// Management functions
function setAuction(address _auction) external;
function setDepositLimit(uint256 _depositLimit) external;
function setTargetIdleAssetBps(uint16 _targetIdleAssetBps) external;
function setTargetIdleBufferBps(uint16 _targetIdleBufferBps) external;
function setPairedTokenDiscountBps(uint16 _pairedTokenDiscountBps) external;
function setMinAsset(uint128 _minAsset) external;
function setMaxSwapValue(uint256 _maxSwapValue) external;
function setUseAuctions(bool _useAuctions) external;
function setMinTendWait(uint24 _minTendWait) external;
function setMaxTendBaseFee(uint8 _maxTendBaseFeeGwei) external;
function manualSwapPairedTokenToAsset(uint256 _amount) external;
function manualWithdrawFromLp(uint256 _amount) external;
// Auction functions
function kickAuction(address _from) external returns (uint256);
function claim(
address[] calldata users,
address[] calldata tokens,
uint256[] calldata amounts,
bytes32[][] calldata proofs
) external;
}{
"evmVersion": "shanghai",
"libraries": {},
"metadata": {
"appendCBOR": true,
"bytecodeHash": "ipfs",
"useLiteralContent": false
},
"optimizer": {
"enabled": true,
"runs": 1000000
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": [
"@openzeppelin/=lib/openzeppelin-contracts/",
"forge-std/=lib/forge-std/src/",
"@tokenized-strategy/=lib/tokenized-strategy/src/",
"@periphery/=lib/tokenized-strategy-periphery/src/",
"@uniswap-v3-core/=lib/uniswap-v3-core/contracts/",
"@yearn-vaults/=lib/tokenized-strategy-periphery/lib/yearn-vaults-v3/contracts/",
"createx-forge/=lib/createx-forge/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/tokenized-strategy/lib/erc4626-tests/",
"halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"openzeppelin/=lib/tokenized-strategy/lib/openzeppelin-contracts/contracts/",
"tokenized-strategy-periphery/=lib/tokenized-strategy-periphery/",
"tokenized-strategy/=lib/tokenized-strategy/",
"uniswap-v3-core/=lib/uniswap-v3-core/contracts/",
"yearn-vaults-v3/=lib/tokenized-strategy-periphery/lib/yearn-vaults-v3/"
],
"viaIR": true
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_governance","type":"address"},{"internalType":"address","name":"_feeRecipient","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"campaignDuration","type":"uint32"}],"name":"CampaignDurationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeRecipient","type":"address"}],"name":"FeeRecipientSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousGovernance","type":"address"},{"indexed":true,"internalType":"address","name":"newGovernance","type":"address"}],"name":"GovernanceTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"katFee","type":"uint256"}],"name":"KatFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategy","type":"address"}],"name":"StrategyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategy","type":"address"}],"name":"StrategyRemoved","type":"event"},{"inputs":[],"name":"AUCTION_FACTORY","outputs":[{"internalType":"contract IAuctionFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DISTRIBUTION_CREATOR","outputs":[{"internalType":"contract IDistributionCreator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"KAT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WKAT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"bytes","name":"_campaignData","type":"bytes"}],"name":"addStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"available","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"campaignDuration","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"isActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"katFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"kick","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastKatBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"receiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"}],"name":"removeStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"address","name":"_auction","type":"address"}],"name":"setAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"bytes","name":"_campaignData","type":"bytes"}],"name":"setCampaignData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_campaignDuration","type":"uint32"}],"name":"setCampaignDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeRecipient","type":"address"}],"name":"setFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_katFee","type":"uint256"}],"name":"setKatFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"strategies","outputs":[{"internalType":"address","name":"auction","type":"address"},{"internalType":"bytes","name":"campaignData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"syncKatBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newGovernance","type":"address"}],"name":"transferGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"want","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"wrapKat","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60803462000145576200263d906001600160401b0390601f38849003908101601f19168201908382118383101762000127578083916040968794855283398101031262000145576200005f6020620000578362000149565b920162000149565b5f80546001600160a01b039384166001600160a01b0319918216811783558651919591927f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce808180a362093a8063ffffffff196003541617600355738bb4c975ff3c250e0ceea271728547f3802b36fd803b156200014557826004815f809463063b87bf60e41b83525af180156200013b5762000116575b50506101f460045516906005541617600555516124de90816200015f8239f35b8111620001275784525f80620000f6565b634e487b7160e01b5f52604160045260245ffd5b86513d5f823e3d90fd5b5f80fd5b51906001600160a01b0382168203620001455756fe6080604090808252600480361015610015575f80fd5b5f3560e01c91826310098ad5146116ad57508163175188e8146115a15781631f1fcd51146114df57816321d2e9c21461140e5781632af5e92a1461133857816339ebf823146112b3578163412ceaaa1461127957816346904840146112275781634a58265e146111eb5781635aa6e6751461119a5781635ad3009014610fff578163670b827114610fb357816368df239514610f675781636f96c62e14610f1b5781637aeedf2a14610a93578163849fd6f7146109655781638561253e1461091957816396c551751461083c5781639f8a13d714610751578163b7612fff14610580578163c398d56d1461053e578163d2ebe32f14610477578163d38bfff414610367578163dc2c256f1461023057508063e74b981b146101795763f7260d3e1461013e575f80fd5b34610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755760209051338152f35b5f80fd5b50346101755760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755760207fbf9a9534339a9d6b81696e05dcfb614b7dc518a31d48be3cfb757988381fb3239173ffffffffffffffffffffffffffffffffffffffff6101ea61177f565b6101f2611dd2565b16906101ff821515611aee565b817fffffffffffffffffffffffff0000000000000000000000000000000000000000600554161760055551908152a1005b82346101755760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755761026861177f565b906024356044359173ffffffffffffffffffffffffffffffffffffffff808416840361017557610296611dd2565b829416918151957f70a082310000000000000000000000000000000000000000000000000000000087523090870152602086602481865afa91821561035e57505f91610328575b61030a95508110610320575b50737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d811461030c57611e50565b005b61031883600254611b53565b600255611e50565b9250846102e9565b90506020853d602011610356575b816103436020938361183c565b810103126101755761030a9451906102dd565b3d9150610336565b513d5f823e3d90fd5b9050346101755760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610175576103a061177f565b906103a9611dd2565b73ffffffffffffffffffffffffffffffffffffffff80921692831561041a5750505f54827fffffffffffffffffffffffff00000000000000000000000000000000000000008216175f55167f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce805f80a3005b90602060649251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152600c60248201527f5a45524f204144445245535300000000000000000000000000000000000000006044820152fd5b905034610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610175576104af611dd2565b8151907f70a082310000000000000000000000000000000000000000000000000000000082523090820152602081602481737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d5afa91821561035e57505f9161050c575b50600255005b90506020813d602011610536575b816105276020938361183c565b8101031261017557515f610506565b3d915061051a565b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755760209063ffffffff600354169051908152f35b9050346101755773ffffffffffffffffffffffffffffffffffffffff6105a53661199a565b9290916105b0611dd2565b6105e66105e18273ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b611a22565b6105f1841515611b8d565b165f526001906001602095816020525f20019367ffffffffffffffff841161072557506106288361062286546117a2565b86611bf2565b5f91601f841160011461068757506106789394509082915f9261067c575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b9055005b013590505f80610646565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616979094925b88831061070e575050508360019596106106d6575b505050811b019055005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88560031b161c199101351690555f80806106cc565b8484013586559485019492810192918101916106b7565b6041907f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b90503461017557602091827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610175578261078d61177f565b335f5260018252602473ffffffffffffffffffffffffffffffffffffffff9182855f205416855196879485937f9f8a13d700000000000000000000000000000000000000000000000000000000855216908301525afa918215610832575f926107fa575b50519015158152f35b9091508281813d831161082b575b610812818361183c565b810103126101755751801515810361017557905f6107f1565b503d610808565b50513d5f823e3d90fd5b9050346101755760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755761087561177f565b906108a43373ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b156108bc576020836108b584611c35565b9051908152f35b60649060208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602060248201527f41756374696f6e4d6964646c654d616e3a204e6f7420612073747261746567796044820152fd5b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755760209051736e9c1f88a960fe63387eb4b71bc525a9313d84618152f35b9050346101755760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755780359063ffffffff8216809203610175576109af611dd2565b62015180821115610a10577fe570f66abd3e707c8ca3441f975afd46fda1f068e338c2af1b93abe412ae658d60208385817fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000600354161760035551908152a1005b60849060208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602360248201527f41756374696f6e4d6964646c654d616e3a2043616d706169676e20647572617460448201527f696f6e00000000000000000000000000000000000000000000000000000000006064820152fd5b823461017557610aa23661199a565b91610aae939193611dd2565b610adc8173ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b610e9857610aeb831515611b8d565b73ffffffffffffffffffffffffffffffffffffffff809116938251927f38d52e0f000000000000000000000000000000000000000000000000000000008452602091828589818a5afa948515610e48575f95610e79575b5081517f88a8d60200000000000000000000000000000000000000000000000000000000815283818a818b5afa908115610e6f579085915f91610e52575b50818451977f8ed5e3a3000000000000000000000000000000000000000000000000000000008952168a88015288602488015216604486015282856064815f73cfa510188884f199fcc6e750764faabe6e56ec405af1948515610e48575f95610e19575b50815167ffffffffffffffff9581840187811183821017610ded57845285168152858711610dc1577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe094835197610c428688601f840116018a61183c565b80895236818501116101755785815f92600196838d01378a010152848201978852885f5282938386525f209151167fffffffffffffffffffffffff00000000000000000000000000000000000000008254161781550194519687519485116107255750610cb984610cb387546117a2565b87611bf2565b8192601f8511600114610d3d575050508190610d099394955f92610d325750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b7f3f008fd510eae7a9e7bee13513d7b83bef8003d488b5a3d0b0da4de71d6846f15f80a2005b015190508580610646565b849791979392931696855f52835f20935f915b898310610daa5750505083600195969710610d73575b505050811b019055610d0c565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055848080610d66565b838501518655948501949381019391810191610d50565b6041897f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b60418b7f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b610e3a919550833d8511610e41575b610e32818361183c565b810190611ac2565b9388610be4565b503d610e28565b82513d5f823e3d90fd5b610e699150853d8711610e4157610e32818361183c565b8a610b80565b83513d5f823e3d90fd5b610e91919550833d8511610e4157610e32818361183c565b9388610b42565b60848560208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602860248201527f41756374696f6e4d6964646c654d616e3a20537472617465677920616c72656160448201527f64792061646465640000000000000000000000000000000000000000000000006064820152fd5b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755760209051738bb4c975ff3c250e0ceea271728547f3802b36fd8152f35b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755760209051737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d8152f35b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610175576020905173cfa510188884f199fcc6e750764faabe6e56ec408152f35b905034610175576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755781359161103c611dd2565b83517f70a0823100000000000000000000000000000000000000000000000000000000815230828201528281602481737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d5afa80156111905784915f9161115f575b501061110557506110f8907fa9059cbb00000000000000000000000000000000000000000000000000000000611100945191820152736e9c1f88a960fe63387eb4b71bc525a9313d84616024820152826044820152604481526110f3816117f3565b612470565b600254611b53565b600255005b816064928551927f08c379a000000000000000000000000000000000000000000000000000000000845283015260248201527f41756374696f6e4d6964646c654d616e3a206e6f7420656e6f756768204b41546044820152fd5b809250848092503d8311611189575b611178818361183c565b81010312610175578390515f611091565b503d61116e565b85513d5f823e3d90fd5b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755760209073ffffffffffffffffffffffffffffffffffffffff5f54169051908152f35b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610175576020906002549051908152f35b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755760209073ffffffffffffffffffffffffffffffffffffffff600554169051908152f35b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261017557602091549051908152f35b82346101755760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755773ffffffffffffffffffffffffffffffffffffffff8061130161177f565b165f52600160205261133461131f6001845f2093845416930161187d565b8351938493845280602085015283019061193e565b0390f35b823461017557807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755761136f61177f565b906024359173ffffffffffffffffffffffffffffffffffffffff908184168094036101755761139c611dd2565b6113cd6105e18273ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b6113d8841515611aee565b165f5260016020525f20907fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790555f80f35b9050346101755760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755780359061144a611dd2565b6103e8821161148257907f5e737898ddbd1f3490e56ee5e6fa392c8916a59bdd5714fbe5f8c7ef9a9f273f92816020935551908152a1005b60649060208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601960248201527f41756374696f6e4d6964646c654d616e3a206b617420666565000000000000006044820152fd5b905034610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610175576020825180927f38d52e0f00000000000000000000000000000000000000000000000000000000825281335afa908115610e4857916020925f9261156c575b5073ffffffffffffffffffffffffffffffffffffffff905191168152f35b73ffffffffffffffffffffffffffffffffffffffff91925061159a90843d8611610e4157610e32818361183c565b919061154e565b82346101755760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261017557600173ffffffffffffffffffffffffffffffffffffffff6115f061177f565b6115f8611dd2565b6116296105e18273ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b1691825f52816020525f205f81550161164281546117a2565b9081611670575b827f09a1db4b80c32706328728508c941a6b954f31eb5affd32f236c1fd405f8fea45f80a2005b81601f5f93116001146116875750555b8180611649565b9080839182526116a6601f60208420940160051c840160018501611aac565b5555611680565b833461017557602092837ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610175578260248186936116ed61177f565b90335f526001865273ffffffffffffffffffffffffffffffffffffffff80885f205416927f10098ad500000000000000000000000000000000000000000000000000000000855216908301525afa918215610832575f92611750575b5051908152f35b9091508281813d8311611778575b611768818361183c565b8101031261017557519083611749565b503d61175e565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361017557565b90600182811c921680156117e9575b60208310146117bc57565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b91607f16916117b1565b6080810190811067ffffffffffffffff82111761180f57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761180f57604052565b9060405191825f825461188f816117a2565b908184526020946001916001811690815f146118fd57506001146118bf575b5050506118bd9250038361183c565b565b5f90815285812095935091905b8183106118e55750506118bd93508201015f80806118ae565b855488840185015294850194879450918301916118cc565b9150506118bd9593507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201015f80806118ae565b91908251928382525f5b8481106119865750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6020809697860101520116010190565b602081830181015184830182015201611948565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126101755760043573ffffffffffffffffffffffffffffffffffffffff81168103610175579160243567ffffffffffffffff9283821161017557806023830112156101755781600401359384116101755760248483010111610175576024019190565b15611a2957565b60846040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f41756374696f6e4d6964646c654d616e3a205374726174656779206e6f74206160448201527f64646564000000000000000000000000000000000000000000000000000000006064820152fd5b818110611ab7575050565b5f8155600101611aac565b90816020910312610175575173ffffffffffffffffffffffffffffffffffffffff811681036101755790565b15611af557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f41756374696f6e4d6964646c654d616e3a207a65726f206164647265737300006044820152fd5b91908203918211611b6057565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b15611b9457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41756374696f6e4d6964646c654d616e3a2063616d706169676e2064617461006044820152fd5b9190601f8111611c0157505050565b6118bd925f5260205f20906020601f840160051c83019310611c2b575b601f0160051c0190611aac565b9091508190611c1e565b73ffffffffffffffffffffffffffffffffffffffff809116737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d81148015611db5575b15611c94575050335f526001602052611c91611c8c600160405f200161187d565b611f5e565b90565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526020928382602481865afa908115611d645784925f92611d80575b505f93602491338652600185526040862054169280611d6f575b5060405194859384927f96c5517500000000000000000000000000000000000000000000000000000000845260048401525af1918215611d64575f92611d3a57505090565b90809250813d8311611d5d575b611d51818361183c565b81010312610175575190565b503d611d47565b6040513d5f823e3d90fd5b611d7a908483611e50565b5f611cf5565b838195949293503d8311611dae575b611d99818361183c565b8101031261017557915190918391905f611cdb565b503d611d8f565b50736e9c1f88a960fe63387eb4b71bc525a9313d84618114611c6b565b73ffffffffffffffffffffffffffffffffffffffff5f54163303611df257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f21676f7665726e616e63650000000000000000000000000000000000000000006044820152fd5b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000602082810191825273ffffffffffffffffffffffffffffffffffffffff9094166024830152604482019490945290925f91611eda81606481015b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261183c565b519082855af115611d64575f513d611f55575073ffffffffffffffffffffffffffffffffffffffff81163b155b611f0e5750565b60249073ffffffffffffffffffffffffffffffffffffffff604051917f5274afe7000000000000000000000000000000000000000000000000000000008352166004820152fd5b60011415611f07565b604051907f70a0823100000000000000000000000000000000000000000000000000000000808352306004840152602083602481737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d5afa928315611d64575f936123c9575b5082611fc560025485611b53565b9384156123c057604051928352306004840152736e9c1f88a960fe63387eb4b71bc525a9313d846192602081602481875afa8015611d645786915f9161238b575b50106123075760045480612273575b5050600255604051602081019060205f7f095ea7b30000000000000000000000000000000000000000000000000000000093848152738bb4c975ff3c250e0ceea271728547f3802b36fd602485015287604485015260448452612077846117f3565b83519082875af15f513d82612257575b5050156121f7575b505063ffffffff600354169160405161010081019181831067ffffffffffffffff84111761180f576121a79460209460e0946040525f84525f8685015260408401528660608401526012608084015263ffffffff421660a084015260c08301528282015260405193849283927fa63f05ad000000000000000000000000000000000000000000000000000000008452856004850152805160248501528581015173ffffffffffffffffffffffffffffffffffffffff809116604486015260408201511660648501526060810151608485015263ffffffff60808201511660a485015263ffffffff60a08201511660c485015263ffffffff60c08201511660e4850152015161010061010484015261012483019061193e565b03815f738bb4c975ff3c250e0ceea271728547f3802b36fd5af18015611d64576121cf575090565b602090813d83116121f0575b6121e5818361183c565b810103126101755790565b503d6121db565b604051916020830152738bb4c975ff3c250e0ceea271728547f3802b36fd60248301525f6044830152604482526080820182811067ffffffffffffffff82111761180f576122509261224b916040526123fd565b6123fd565b5f8061208f565b90915061226b5750823b15155b5f80612087565b600114612264565b809250859195029181830403611b60576122a16123009161271061229b940493848092611b53565b96611b53565b6005546040517fa9059cbb00000000000000000000000000000000000000000000000000000000602082015273ffffffffffffffffffffffffffffffffffffffff90911660248201526044810193909352916110f38160648101611eae565b5f80612015565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f41756374696f6e4d6964646c654d616e3a206e6f7420656e6f75676820574b4160448201527f54000000000000000000000000000000000000000000000000000000000000006064820152fd5b9150506020813d6020116123b8575b816123a76020938361183c565b81010312610175578590515f612006565b3d915061239a565b50505050505f90565b9092506020813d6020116123f5575b816123e56020938361183c565b810103126101755751915f611fb7565b3d91506123d8565b60205f825182736e9c1f88a960fe63387eb4b71bc525a9313d8461940182855af115611d64575f513d6124675750803b155b6124365750565b602490604051907f5274afe70000000000000000000000000000000000000000000000000000000082526004820152fd5b6001141561242f565b60205f825182737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d940182855af115611d64575f513d6124675750803b15612436575056fea2646970667358221220c6f3a4d8f25cf2bf72350f7d1d5ed28b9b572d2eeb66527db871a036b83bb51c64736f6c63430008170033000000000000000000000000be7c7efc1ef3245d37e3157f76a512108d6d7ae6000000000000000000000000be7c7efc1ef3245d37e3157f76a512108d6d7ae6
Deployed Bytecode
0x6080604090808252600480361015610015575f80fd5b5f3560e01c91826310098ad5146116ad57508163175188e8146115a15781631f1fcd51146114df57816321d2e9c21461140e5781632af5e92a1461133857816339ebf823146112b3578163412ceaaa1461127957816346904840146112275781634a58265e146111eb5781635aa6e6751461119a5781635ad3009014610fff578163670b827114610fb357816368df239514610f675781636f96c62e14610f1b5781637aeedf2a14610a93578163849fd6f7146109655781638561253e1461091957816396c551751461083c5781639f8a13d714610751578163b7612fff14610580578163c398d56d1461053e578163d2ebe32f14610477578163d38bfff414610367578163dc2c256f1461023057508063e74b981b146101795763f7260d3e1461013e575f80fd5b34610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755760209051338152f35b5f80fd5b50346101755760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755760207fbf9a9534339a9d6b81696e05dcfb614b7dc518a31d48be3cfb757988381fb3239173ffffffffffffffffffffffffffffffffffffffff6101ea61177f565b6101f2611dd2565b16906101ff821515611aee565b817fffffffffffffffffffffffff0000000000000000000000000000000000000000600554161760055551908152a1005b82346101755760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755761026861177f565b906024356044359173ffffffffffffffffffffffffffffffffffffffff808416840361017557610296611dd2565b829416918151957f70a082310000000000000000000000000000000000000000000000000000000087523090870152602086602481865afa91821561035e57505f91610328575b61030a95508110610320575b50737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d811461030c57611e50565b005b61031883600254611b53565b600255611e50565b9250846102e9565b90506020853d602011610356575b816103436020938361183c565b810103126101755761030a9451906102dd565b3d9150610336565b513d5f823e3d90fd5b9050346101755760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610175576103a061177f565b906103a9611dd2565b73ffffffffffffffffffffffffffffffffffffffff80921692831561041a5750505f54827fffffffffffffffffffffffff00000000000000000000000000000000000000008216175f55167f5f56bee8cffbe9a78652a74a60705edede02af10b0bbb888ca44b79a0d42ce805f80a3005b90602060649251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152600c60248201527f5a45524f204144445245535300000000000000000000000000000000000000006044820152fd5b905034610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610175576104af611dd2565b8151907f70a082310000000000000000000000000000000000000000000000000000000082523090820152602081602481737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d5afa91821561035e57505f9161050c575b50600255005b90506020813d602011610536575b816105276020938361183c565b8101031261017557515f610506565b3d915061051a565b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755760209063ffffffff600354169051908152f35b9050346101755773ffffffffffffffffffffffffffffffffffffffff6105a53661199a565b9290916105b0611dd2565b6105e66105e18273ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b611a22565b6105f1841515611b8d565b165f526001906001602095816020525f20019367ffffffffffffffff841161072557506106288361062286546117a2565b86611bf2565b5f91601f841160011461068757506106789394509082915f9261067c575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b9055005b013590505f80610646565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616979094925b88831061070e575050508360019596106106d6575b505050811b019055005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88560031b161c199101351690555f80806106cc565b8484013586559485019492810192918101916106b7565b6041907f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b90503461017557602091827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610175578261078d61177f565b335f5260018252602473ffffffffffffffffffffffffffffffffffffffff9182855f205416855196879485937f9f8a13d700000000000000000000000000000000000000000000000000000000855216908301525afa918215610832575f926107fa575b50519015158152f35b9091508281813d831161082b575b610812818361183c565b810103126101755751801515810361017557905f6107f1565b503d610808565b50513d5f823e3d90fd5b9050346101755760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755761087561177f565b906108a43373ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b156108bc576020836108b584611c35565b9051908152f35b60649060208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602060248201527f41756374696f6e4d6964646c654d616e3a204e6f7420612073747261746567796044820152fd5b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755760209051736e9c1f88a960fe63387eb4b71bc525a9313d84618152f35b9050346101755760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755780359063ffffffff8216809203610175576109af611dd2565b62015180821115610a10577fe570f66abd3e707c8ca3441f975afd46fda1f068e338c2af1b93abe412ae658d60208385817fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000600354161760035551908152a1005b60849060208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602360248201527f41756374696f6e4d6964646c654d616e3a2043616d706169676e20647572617460448201527f696f6e00000000000000000000000000000000000000000000000000000000006064820152fd5b823461017557610aa23661199a565b91610aae939193611dd2565b610adc8173ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b610e9857610aeb831515611b8d565b73ffffffffffffffffffffffffffffffffffffffff809116938251927f38d52e0f000000000000000000000000000000000000000000000000000000008452602091828589818a5afa948515610e48575f95610e79575b5081517f88a8d60200000000000000000000000000000000000000000000000000000000815283818a818b5afa908115610e6f579085915f91610e52575b50818451977f8ed5e3a3000000000000000000000000000000000000000000000000000000008952168a88015288602488015216604486015282856064815f73cfa510188884f199fcc6e750764faabe6e56ec405af1948515610e48575f95610e19575b50815167ffffffffffffffff9581840187811183821017610ded57845285168152858711610dc1577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe094835197610c428688601f840116018a61183c565b80895236818501116101755785815f92600196838d01378a010152848201978852885f5282938386525f209151167fffffffffffffffffffffffff00000000000000000000000000000000000000008254161781550194519687519485116107255750610cb984610cb387546117a2565b87611bf2565b8192601f8511600114610d3d575050508190610d099394955f92610d325750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b7f3f008fd510eae7a9e7bee13513d7b83bef8003d488b5a3d0b0da4de71d6846f15f80a2005b015190508580610646565b849791979392931696855f52835f20935f915b898310610daa5750505083600195969710610d73575b505050811b019055610d0c565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055848080610d66565b838501518655948501949381019391810191610d50565b6041897f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b60418b7f4e487b71000000000000000000000000000000000000000000000000000000005f525260245ffd5b610e3a919550833d8511610e41575b610e32818361183c565b810190611ac2565b9388610be4565b503d610e28565b82513d5f823e3d90fd5b610e699150853d8711610e4157610e32818361183c565b8a610b80565b83513d5f823e3d90fd5b610e91919550833d8511610e4157610e32818361183c565b9388610b42565b60848560208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602860248201527f41756374696f6e4d6964646c654d616e3a20537472617465677920616c72656160448201527f64792061646465640000000000000000000000000000000000000000000000006064820152fd5b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755760209051738bb4c975ff3c250e0ceea271728547f3802b36fd8152f35b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755760209051737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d8152f35b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610175576020905173cfa510188884f199fcc6e750764faabe6e56ec408152f35b905034610175576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755781359161103c611dd2565b83517f70a0823100000000000000000000000000000000000000000000000000000000815230828201528281602481737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d5afa80156111905784915f9161115f575b501061110557506110f8907fa9059cbb00000000000000000000000000000000000000000000000000000000611100945191820152736e9c1f88a960fe63387eb4b71bc525a9313d84616024820152826044820152604481526110f3816117f3565b612470565b600254611b53565b600255005b816064928551927f08c379a000000000000000000000000000000000000000000000000000000000845283015260248201527f41756374696f6e4d6964646c654d616e3a206e6f7420656e6f756768204b41546044820152fd5b809250848092503d8311611189575b611178818361183c565b81010312610175578390515f611091565b503d61116e565b85513d5f823e3d90fd5b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755760209073ffffffffffffffffffffffffffffffffffffffff5f54169051908152f35b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610175576020906002549051908152f35b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755760209073ffffffffffffffffffffffffffffffffffffffff600554169051908152f35b8234610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261017557602091549051908152f35b82346101755760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755773ffffffffffffffffffffffffffffffffffffffff8061130161177f565b165f52600160205261133461131f6001845f2093845416930161187d565b8351938493845280602085015283019061193e565b0390f35b823461017557807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755761136f61177f565b906024359173ffffffffffffffffffffffffffffffffffffffff908184168094036101755761139c611dd2565b6113cd6105e18273ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b6113d8841515611aee565b165f5260016020525f20907fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790555f80f35b9050346101755760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101755780359061144a611dd2565b6103e8821161148257907f5e737898ddbd1f3490e56ee5e6fa392c8916a59bdd5714fbe5f8c7ef9a9f273f92816020935551908152a1005b60649060208451917f08c379a0000000000000000000000000000000000000000000000000000000008352820152601960248201527f41756374696f6e4d6964646c654d616e3a206b617420666565000000000000006044820152fd5b905034610175575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610175576020825180927f38d52e0f00000000000000000000000000000000000000000000000000000000825281335afa908115610e4857916020925f9261156c575b5073ffffffffffffffffffffffffffffffffffffffff905191168152f35b73ffffffffffffffffffffffffffffffffffffffff91925061159a90843d8611610e4157610e32818361183c565b919061154e565b82346101755760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261017557600173ffffffffffffffffffffffffffffffffffffffff6115f061177f565b6115f8611dd2565b6116296105e18273ffffffffffffffffffffffffffffffffffffffff8091165f52600160205260405f205416151590565b1691825f52816020525f205f81550161164281546117a2565b9081611670575b827f09a1db4b80c32706328728508c941a6b954f31eb5affd32f236c1fd405f8fea45f80a2005b81601f5f93116001146116875750555b8180611649565b9080839182526116a6601f60208420940160051c840160018501611aac565b5555611680565b833461017557602092837ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610175578260248186936116ed61177f565b90335f526001865273ffffffffffffffffffffffffffffffffffffffff80885f205416927f10098ad500000000000000000000000000000000000000000000000000000000855216908301525afa918215610832575f92611750575b5051908152f35b9091508281813d8311611778575b611768818361183c565b8101031261017557519083611749565b503d61175e565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361017557565b90600182811c921680156117e9575b60208310146117bc57565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b91607f16916117b1565b6080810190811067ffffffffffffffff82111761180f57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761180f57604052565b9060405191825f825461188f816117a2565b908184526020946001916001811690815f146118fd57506001146118bf575b5050506118bd9250038361183c565b565b5f90815285812095935091905b8183106118e55750506118bd93508201015f80806118ae565b855488840185015294850194879450918301916118cc565b9150506118bd9593507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201015f80806118ae565b91908251928382525f5b8481106119865750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6020809697860101520116010190565b602081830181015184830182015201611948565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126101755760043573ffffffffffffffffffffffffffffffffffffffff81168103610175579160243567ffffffffffffffff9283821161017557806023830112156101755781600401359384116101755760248483010111610175576024019190565b15611a2957565b60846040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f41756374696f6e4d6964646c654d616e3a205374726174656779206e6f74206160448201527f64646564000000000000000000000000000000000000000000000000000000006064820152fd5b818110611ab7575050565b5f8155600101611aac565b90816020910312610175575173ffffffffffffffffffffffffffffffffffffffff811681036101755790565b15611af557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f41756374696f6e4d6964646c654d616e3a207a65726f206164647265737300006044820152fd5b91908203918211611b6057565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b15611b9457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41756374696f6e4d6964646c654d616e3a2063616d706169676e2064617461006044820152fd5b9190601f8111611c0157505050565b6118bd925f5260205f20906020601f840160051c83019310611c2b575b601f0160051c0190611aac565b9091508190611c1e565b73ffffffffffffffffffffffffffffffffffffffff809116737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d81148015611db5575b15611c94575050335f526001602052611c91611c8c600160405f200161187d565b611f5e565b90565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526020928382602481865afa908115611d645784925f92611d80575b505f93602491338652600185526040862054169280611d6f575b5060405194859384927f96c5517500000000000000000000000000000000000000000000000000000000845260048401525af1918215611d64575f92611d3a57505090565b90809250813d8311611d5d575b611d51818361183c565b81010312610175575190565b503d611d47565b6040513d5f823e3d90fd5b611d7a908483611e50565b5f611cf5565b838195949293503d8311611dae575b611d99818361183c565b8101031261017557915190918391905f611cdb565b503d611d8f565b50736e9c1f88a960fe63387eb4b71bc525a9313d84618114611c6b565b73ffffffffffffffffffffffffffffffffffffffff5f54163303611df257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f21676f7665726e616e63650000000000000000000000000000000000000000006044820152fd5b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000602082810191825273ffffffffffffffffffffffffffffffffffffffff9094166024830152604482019490945290925f91611eda81606481015b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261183c565b519082855af115611d64575f513d611f55575073ffffffffffffffffffffffffffffffffffffffff81163b155b611f0e5750565b60249073ffffffffffffffffffffffffffffffffffffffff604051917f5274afe7000000000000000000000000000000000000000000000000000000008352166004820152fd5b60011415611f07565b604051907f70a0823100000000000000000000000000000000000000000000000000000000808352306004840152602083602481737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d5afa928315611d64575f936123c9575b5082611fc560025485611b53565b9384156123c057604051928352306004840152736e9c1f88a960fe63387eb4b71bc525a9313d846192602081602481875afa8015611d645786915f9161238b575b50106123075760045480612273575b5050600255604051602081019060205f7f095ea7b30000000000000000000000000000000000000000000000000000000093848152738bb4c975ff3c250e0ceea271728547f3802b36fd602485015287604485015260448452612077846117f3565b83519082875af15f513d82612257575b5050156121f7575b505063ffffffff600354169160405161010081019181831067ffffffffffffffff84111761180f576121a79460209460e0946040525f84525f8685015260408401528660608401526012608084015263ffffffff421660a084015260c08301528282015260405193849283927fa63f05ad000000000000000000000000000000000000000000000000000000008452856004850152805160248501528581015173ffffffffffffffffffffffffffffffffffffffff809116604486015260408201511660648501526060810151608485015263ffffffff60808201511660a485015263ffffffff60a08201511660c485015263ffffffff60c08201511660e4850152015161010061010484015261012483019061193e565b03815f738bb4c975ff3c250e0ceea271728547f3802b36fd5af18015611d64576121cf575090565b602090813d83116121f0575b6121e5818361183c565b810103126101755790565b503d6121db565b604051916020830152738bb4c975ff3c250e0ceea271728547f3802b36fd60248301525f6044830152604482526080820182811067ffffffffffffffff82111761180f576122509261224b916040526123fd565b6123fd565b5f8061208f565b90915061226b5750823b15155b5f80612087565b600114612264565b809250859195029181830403611b60576122a16123009161271061229b940493848092611b53565b96611b53565b6005546040517fa9059cbb00000000000000000000000000000000000000000000000000000000602082015273ffffffffffffffffffffffffffffffffffffffff90911660248201526044810193909352916110f38160648101611eae565b5f80612015565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f41756374696f6e4d6964646c654d616e3a206e6f7420656e6f75676820574b4160448201527f54000000000000000000000000000000000000000000000000000000000000006064820152fd5b9150506020813d6020116123b8575b816123a76020938361183c565b81010312610175578590515f612006565b3d915061239a565b50505050505f90565b9092506020813d6020116123f5575b816123e56020938361183c565b810103126101755751915f611fb7565b3d91506123d8565b60205f825182736e9c1f88a960fe63387eb4b71bc525a9313d8461940182855af115611d64575f513d6124675750803b155b6124365750565b602490604051907f5274afe70000000000000000000000000000000000000000000000000000000082526004820152fd5b6001141561242f565b60205f825182737f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d940182855af115611d64575f513d6124675750803b15612436575056fea2646970667358221220c6f3a4d8f25cf2bf72350f7d1d5ed28b9b572d2eeb66527db871a036b83bb51c64736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000be7c7efc1ef3245d37e3157f76a512108d6d7ae6000000000000000000000000be7c7efc1ef3245d37e3157f76a512108d6d7ae6
-----Decoded View---------------
Arg [0] : _governance (address): 0xBe7c7efc1ef3245d37E3157F76A512108D6D7aE6
Arg [1] : _feeRecipient (address): 0xBe7c7efc1ef3245d37E3157F76A512108D6D7aE6
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000be7c7efc1ef3245d37e3157f76a512108d6d7ae6
Arg [1] : 000000000000000000000000be7c7efc1ef3245d37e3157f76a512108d6d7ae6
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.