Source Code
Latest 1 internal transaction
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 22951346 | 506 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AgentKey
Compiler Version
v0.8.27+commit.40a35a09
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Unlicense
pragma solidity =0.8.27;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "contracts/interfaces/IAgentNameService.sol";
import "contracts/interfaces/IFeeHandler.sol";
import "contracts/lib/AgentKeyToolkit.sol";
import "contracts/utils/SafeETHTransfer.sol";
contract AgentKey is ERC20BurnableUpgradeable, ReentrancyGuard, SafeETHTransfer {
struct Cooldown {
uint256 amount;
uint64 claimableAt;
}
uint256 private constant TWO_WEEKS = 14 days;
address private immutable _weth;
IFeeHandler private immutable _feeHandler;
IAgentNameService private immutable _agentNameService;
address private immutable _factory;
IUniswapV2Router02 public router;
address public pair;
uint256 public ansTokenID;
address public treasury;
address public bondingCurve;
uint8 public adminSellFeePercent;
uint8 public creatorSellFeePercent;
bool public hasLaunched;
bool private _instantTransfer;
mapping(address => uint256) private _membership;
mapping(address => Cooldown[]) private _cooldowns;
event Initialized();
event Launched();
event PairUpdated(address pair);
event FeesCollected(uint256 tokensSwapped, uint256 adminAmount, uint256 creatorAmount);
event Subscribed(address indexed account, uint256 ak);
event Unsubscribed(address indexed account, uint256 cooldownIndex, Cooldown cooldown);
event Claimed(address indexed account, uint256 cooldownIndex, Cooldown cooldown);
event Cancelled(address indexed account, uint256 cooldownIndex, Cooldown cooldown);
modifier instantTransfer() {
_instantTransfer = true;
_;
_instantTransfer = false;
}
/**
* @param factory_ Factory address.
* @param weth_ WETH address.
* @param feeHandler_ Fee handler address.
* @param agentNameService_ Agent Name Service NFT address.
*/
constructor(
address factory_,
address weth_,
IFeeHandler feeHandler_,
IAgentNameService agentNameService_
) {
if (
factory_ == address(0) ||
weth_ == address(0) ||
address(feeHandler_) == address(0) ||
address(agentNameService_) == address(0)
) revert Errors.InvalidAddress();
_factory = factory_;
_weth = weth_;
_feeHandler = feeHandler_;
_agentNameService = agentNameService_;
}
/**
* @notice Initialize the Agent Key (only the Agent Key factory can call this function).
* @param _bondingCurve Bonding curve.
* @param _router Router.
* @param name_ Name.
* @param _ansTokenID Agent Name Service token ID.
* @param _treasury Gnosis treasury.
* @param _adminSellFeePercent Admin sell fee percent.
* @param _creatorSellFeePercent Creator sell fee percent.
*/
function initialize(
address _bondingCurve,
IUniswapV2Router02 _router,
string memory name_,
uint256 _ansTokenID,
address _treasury,
uint8 _adminSellFeePercent,
uint8 _creatorSellFeePercent
) external initializer {
if (msg.sender != _factory) revert Errors.Unauthorized();
bondingCurve = _bondingCurve;
router = _router;
ansTokenID = _ansTokenID;
treasury = _treasury;
adminSellFeePercent = _adminSellFeePercent;
creatorSellFeePercent = _creatorSellFeePercent;
__ERC20_init(name_, _agentNameService.tokenSymbol(ansTokenID));
_mint(_bondingCurve, AgentKeyToolkit.INITIAL_REAL_TOKEN);
emit Initialized();
}
/// @notice Called just before liquidity is added in the AgentKeyBondingCurve contract.
function launch() external {
if (msg.sender != bondingCurve) revert Errors.Unauthorized();
hasLaunched = true;
emit Launched();
}
/**
* @notice Update the pair.
* @param _pair Pair address.
*/
function setPair(address _pair) external {
if (msg.sender != bondingCurve) revert Errors.Unauthorized();
pair = _pair;
emit PairUpdated(_pair);
}
/**
* @notice Become a member of the Agent Key by subscribing tokens to it.
* @param _amount Amount of AK to subscribe.
*/
function subscribe(uint256 _amount) external nonReentrant {
/// @dev no approvals required to login
if (_amount == 0 || balanceOf(msg.sender) < _amount) revert Errors.InvalidAmount();
_membership[msg.sender] += _amount;
_update(msg.sender, address(this), _amount);
emit Subscribed(msg.sender, _amount);
}
/**
* @notice Unsubscribe tokens from the Agent Key, there is a 2 week cooldown then the user needs to call claim(uint256 _cooldownIndex).
* @param _amount Amount of AK to unsubscribe.
*/
function unsubscribe(uint256 _amount) external nonReentrant {
if (_amount == 0 || _membership[msg.sender] < _amount) revert Errors.InvalidAmount();
_membership[msg.sender] -= _amount;
uint64 claimableAt = uint64(block.timestamp + TWO_WEEKS);
Cooldown memory cooldown = Cooldown(_amount, claimableAt);
uint256 cooldownIndex = _cooldowns[msg.sender].length;
_cooldowns[msg.sender].push(cooldown);
emit Unsubscribed(msg.sender, cooldownIndex, cooldown);
}
/**
* @notice Claim unsubscribed tokens after the 2 week cooldown ends.
* @param _cooldownIndex Cooldown index.
*/
function claim(uint256 _cooldownIndex) external nonReentrant {
uint256 totalCooldowns = _cooldowns[msg.sender].length;
if (totalCooldowns <= _cooldownIndex) revert Errors.InvalidIndex();
Cooldown memory cooldown = _cooldowns[msg.sender][_cooldownIndex];
if (block.timestamp < cooldown.claimableAt) revert Errors.PrematureExecution();
_cooldowns[msg.sender][_cooldownIndex] = _cooldowns[msg.sender][totalCooldowns - 1];
_cooldowns[msg.sender].pop();
_update(address(this), msg.sender, cooldown.amount);
emit Claimed(msg.sender, _cooldownIndex, cooldown);
}
/**
* @notice Cancel a cooldown for unsubscribed tokens before the 2 week cooldown ends.
* @param _cooldownIndex Cooldown index.
*/
function cancel(uint256 _cooldownIndex) external nonReentrant {
uint256 totalCooldowns = _cooldowns[msg.sender].length;
if (totalCooldowns <= _cooldownIndex) revert Errors.InvalidIndex();
Cooldown memory cooldown = _cooldowns[msg.sender][_cooldownIndex];
if (cooldown.claimableAt <= block.timestamp) revert Errors.Unavailable();
_cooldowns[msg.sender][_cooldownIndex] = _cooldowns[msg.sender][totalCooldowns - 1];
_cooldowns[msg.sender].pop();
_membership[msg.sender] += cooldown.amount;
emit Cancelled(msg.sender, _cooldownIndex, cooldown);
}
/**
* @notice Get the membership amount of a given user.
* @param _user User address.
* @return uint256 Amount of AK subscribed.
*/
function getMembership(address _user) external view returns (uint256) {
if (_user == address(0)) revert Errors.InvalidAddress();
return _membership[_user];
}
/**
* @notice Get the total cooldowns for a given user.
* @param _user User address.
* @return uint256 Total cooldowns.
*/
function getTotalCooldowns(address _user) public view returns (uint256) {
if (_user == address(0)) revert Errors.InvalidAddress();
return _cooldowns[_user].length;
}
/**
* @notice Get cooldown details for a given user and cooldown index.
* @param _user User address.
* @param _cooldownIndex Cooldown index.
* @return Cooldown Cooldown details.
*/
function getCooldown(
address _user,
uint256 _cooldownIndex
) external view returns (Cooldown memory) {
if (getTotalCooldowns(_user) <= _cooldownIndex) revert Errors.InvalidIndex();
return _cooldowns[_user][_cooldownIndex];
}
/**
* @param _from From address.
* @param _to To address.
* @param _value Value.
* @return bool Always True to support legacy contracts.
*/
function transferFrom(
address _from,
address _to,
uint256 _value
) public override returns (bool) {
/**
* @dev the contract uses the original transferFrom function (which requires approval), in two scenarios:
* - the token has already launched
* - the creator of a token is distributing tokens to NFT holders (which is allowed pre and post bonding curve)
*/
if (hasLaunched) return super.transferFrom(_from, _to, _value);
/**
* @dev approvals are not required to sell via the bonding curve to improve UX, therefore the only the
* bonding curve has permission to use this function safely, because it transfers from only the sellers wallet
*/
if (msg.sender != bondingCurve) revert Errors.Unauthorized();
_transfer(_from, _to, _value);
return true;
}
/**
* @param _from From address.
* @param _to To address.
* @param _value Value.
*/
function _update(address _from, address _to, uint256 _value) internal override {
if (!hasLaunched && !_isTransferAllowed(_from, _to)) revert Errors.Unavailable();
if (!_instantTransfer && _to == pair && pair != address(0)) {
uint256 fee = (_value * (adminSellFeePercent + creatorSellFeePercent)) /
AgentKeyToolkit.PERCENT_DENOMINATOR;
if (fee > 0) {
super._update(_from, address(this), fee);
_handleFee(fee);
}
super._update(_from, _to, _value - fee);
return;
}
super._update(_from, _to, _value);
}
/// @param _fee Fee amount
function _handleFee(uint256 _fee) private nonReentrant {
uint256 eth = _swapToETH(_fee);
uint256 adminAmount = (eth * adminSellFeePercent) /
(adminSellFeePercent + creatorSellFeePercent);
uint256 creatorAmount = eth - adminAmount;
if (adminAmount > 0) {
_feeHandler.pay{value: adminAmount}();
}
if (creatorAmount > 0) {
_safeETHTransfer(treasury, creatorAmount);
}
emit FeesCollected(_fee, adminAmount, creatorAmount);
}
/**
* @param _amount Amount of tokens to swap for ETH.
* @return uint256 ETH received.
*/
function _swapToETH(uint256 _amount) private instantTransfer returns (uint256) {
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = _weth;
_approve(address(this), address(router), _amount, false);
uint256[] memory amounts = router.swapExactTokensForETH(
_amount,
0,
path,
address(this),
block.timestamp
);
return amounts[1];
}
/**
* @param _from From address.
* @param _to To address.
* @return bool True - Transferring is allowed, False - Transferring is not allowed.
*/
function _isTransferAllowed(address _from, address _to) private view returns (bool) {
/**
* @dev subscribing/unsubscribing
*/
if (_to == address(this) || _from == address(this)) return true;
/**
* @dev tokens are only allowed to be sent to the bonding curve when selling tokens, via transferFrom()
* this prevents users from sending their tokens to the bonding curve via transfer()
*/
if (_to == bondingCurve && msg.sender == bondingCurve) return true;
/**
* @dev Tokens can only be transferred from the bonding curve when purchasing tokens. This can happen in two scenarios:
* - A user buys tokens (the receiver of the tokens cannot be a contract, it must be an EOA)
* - The creator of the token performs an initial buy when creating their token
*/
if (_from == bondingCurve && (!_isContract(_to) || _to == _factory)) return true;
/// @dev tokens can only be minted to the bonding curve (via initialize())
if (_from == address(0) && _to == bondingCurve) return true;
/**
* @dev Tokens can only be transferred from the factory during an initial buy:
* - The creator of the token cannot be a contract, it must be an EOA
*/
if (_from == _factory && !_isContract(_to)) return true;
/**
* @dev A user may decide to burn tokens via the burn or burnFrom function. _to can never equal the zero address
* from the transfer, transferFrom and mint functions
*/
if (_to == address(0)) return true;
return false;
}
/**
* @dev Checks if an address is a smart contract.
* @param _account Account.
* @return bool True - is a smart contract, False - is not a smart contract.
*/
function _isContract(address _account) private view returns (bool) {
/**
* @dev This method relies on extcodesize, which returns 0 for contracts in
* construction, since the code is only stored at the end of the constructor execution.
*/
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly {
size := extcodesize(_account)
}
return size != 0;
}
receive() external payable {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.20;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Storage of the initializable contract.
*
* It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
* when using with upgradeable contracts.
*
* @custom:storage-location erc7201:openzeppelin.storage.Initializable
*/
struct InitializableStorage {
/**
* @dev Indicates that the contract has been initialized.
*/
uint64 _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
/**
* @dev The contract is already initialized.
*/
error InvalidInitialization();
/**
* @dev The contract is not initializing.
*/
error NotInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint64 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
* number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
* production.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
// Cache values to avoid duplicated sloads
bool isTopLevelCall = !$._initializing;
uint64 initialized = $._initialized;
// Allowed calls:
// - initialSetup: the contract is not in the initializing state and no previous version was
// initialized
// - construction: the contract is initialized at version 1 (no reininitialization) and the
// current contract is just being deployed
bool initialSetup = initialized == 0 && isTopLevelCall;
bool construction = initialized == 1 && address(this).code.length == 0;
if (!initialSetup && !construction) {
revert InvalidInitialization();
}
$._initialized = 1;
if (isTopLevelCall) {
$._initializing = true;
}
_;
if (isTopLevelCall) {
$._initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint64 version) {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing || $._initialized >= version) {
revert InvalidInitialization();
}
$._initialized = version;
$._initializing = true;
_;
$._initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
_checkInitializing();
_;
}
/**
* @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
*/
function _checkInitializing() internal view virtual {
if (!_isInitializing()) {
revert NotInitializing();
}
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing) {
revert InvalidInitialization();
}
if ($._initialized != type(uint64).max) {
$._initialized = type(uint64).max;
emit Initialized(type(uint64).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint64) {
return _getInitializableStorage()._initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _getInitializableStorage()._initializing;
}
/**
* @dev Returns a pointer to the storage namespace.
*/
// solhint-disable-next-line var-name-mixedcase
function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
assembly {
$.slot := INITIALIZABLE_STORAGE
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {ContextUpgradeable} from "../../utils/ContextUpgradeable.sol";
import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol";
import {Initializable} from "../../proxy/utils/Initializable.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 ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*/
abstract contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors {
/// @custom:storage-location erc7201:openzeppelin.storage.ERC20
struct ERC20Storage {
mapping(address account => uint256) _balances;
mapping(address account => mapping(address spender => uint256)) _allowances;
uint256 _totalSupply;
string _name;
string _symbol;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC20")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00;
function _getERC20Storage() private pure returns (ERC20Storage storage $) {
assembly {
$.slot := ERC20StorageLocation
}
}
/**
* @dev Sets the values for {name} and {symbol}.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {
__ERC20_init_unchained(name_, symbol_);
}
function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {
ERC20Storage storage $ = _getERC20Storage();
$._name = name_;
$._symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
ERC20Storage storage $ = _getERC20Storage();
return $._name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
ERC20Storage storage $ = _getERC20Storage();
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) {
ERC20Storage storage $ = _getERC20Storage();
return $._totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual returns (uint256) {
ERC20Storage storage $ = _getERC20Storage();
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) {
ERC20Storage storage $ = _getERC20Storage();
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}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* 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 {
ERC20Storage storage $ = _getERC20Storage();
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:
* ```
* 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 {
ERC20Storage storage $ = _getERC20Storage();
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.0.0) (token/ERC20/extensions/ERC20Burnable.sol)
pragma solidity ^0.8.20;
import {ERC20Upgradeable} from "../ERC20Upgradeable.sol";
import {ContextUpgradeable} from "../../../utils/ContextUpgradeable.sol";
import {Initializable} from "../../../proxy/utils/Initializable.sol";
/**
* @dev Extension of {ERC20} that allows token holders to destroy both their own
* tokens and those that they have an allowance for, in a way that can be
* recognized off-chain (via event analysis).
*/
abstract contract ERC20BurnableUpgradeable is Initializable, ContextUpgradeable, ERC20Upgradeable {
function __ERC20Burnable_init() internal onlyInitializing {
}
function __ERC20Burnable_init_unchained() internal onlyInitializing {
}
/**
* @dev Destroys a `value` amount of tokens from the caller.
*
* See {ERC20-_burn}.
*/
function burn(uint256 value) public virtual {
_burn(_msgSender(), value);
}
/**
* @dev Destroys a `value` amount of tokens from `account`, deducting from
* the caller's allowance.
*
* See {ERC20-_burn} and {ERC20-allowance}.
*
* Requirements:
*
* - the caller must have allowance for ``accounts``'s tokens of at least
* `value`.
*/
function burnFrom(address account, uint256 value) public virtual {
_spendAllowance(account, _msgSender(), value);
_burn(account, value);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @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 ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
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.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard ERC20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 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 ERC721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-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 ERC1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 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.0.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 ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*/
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}.
*
* All two of these 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}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* 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:
* ```
* 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.0.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 ERC20 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.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the 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.0.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
* {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.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.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}pragma solidity >=0.6.2;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}pragma solidity >=0.6.2;
import './IUniswapV2Router01.sol';
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}// SPDX-License-Identifier: Unlicense
pragma solidity =0.8.27;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "contracts/lib/EIP712Lib.sol";
/// @title Interface for AgentNameService.
interface IAgentNameService is IERC721 {
function create(
EIP712Lib.Signature calldata _signature
) external payable returns (uint256 tokenID);
function setToken(address _token, uint256 _tokenID) external;
function isAgentKey(address _token) external view returns (bool);
function cost() external view returns (uint256);
function tokenSymbol(uint256 _tokenID) external view returns (string memory);
}// SPDX-License-Identifier: Unlicense
pragma solidity =0.8.27;
/// @title Interface for FeeHandler.
interface IFeeHandler {
function pay() external payable;
}// SPDX-License-Identifier: Unlicense
pragma solidity =0.8.27;
/// @title AgentKeyToolkit: A library that stores common variables for Agent Key tokens.
library AgentKeyToolkit {
/// @dev 100% to 1 d.p.
uint256 public constant PERCENT_DENOMINATOR = 1000;
/// @dev Maximum trade fee of 5%
uint8 public constant MAX_TRADE_FEE_PERCENT = 50;
/// @dev Maximum success fee of 5%
uint8 public constant MAX_SUCCESS_FEE = 50;
/// @dev Maximum value for the maximum % initial buy
uint16 public constant MAX_INITIAL_BUY_PERCENT = 900;
uint256 public constant INITIAL_REAL_TOKEN = 21_000_000 ether;
uint256 public constant FINAL_REAL_TOKEN = 4_344_900 ether;
uint256 private constant OFFSET = 1_533_000 ether;
uint256 public constant INITIAL_VIRTUAL_TOKEN = INITIAL_REAL_TOKEN + OFFSET;
uint256 public constant FINAL_VIRTUAL_TOKEN = FINAL_REAL_TOKEN + OFFSET;
}// SPDX-License-Identifier: Unlicense
pragma solidity =0.8.27;
/// @title EIP712Lib: A library that stores the signature related types
library EIP712Lib {
struct Signature {
bytes signature;
bytes data;
uint256 expiresAt;
}
struct SignatureWithNonce {
bytes signature;
bytes data;
uint256 expiresAt;
uint256 nonce;
}
bytes32 public constant SIGNATURE_TYPE =
keccak256("Signature(address account,bytes32 data,uint256 expiresAt)");
bytes32 public constant SIGNATURE_TYPE_WITH_NONCE =
keccak256(
"SignatureWithNonce(address account,bytes32 data,uint256 expiresAt,uint256 nonce)"
);
}// SPDX-License-Identifier: Unlicense
pragma solidity =0.8.27;
/// @title Errors: A library that stores common errors.
library Errors {
error InvalidAddress();
error InvalidAmount();
error InvalidIndex();
error InvalidPayment();
error Unauthorized();
error PrematureExecution();
error InsufficientFunds();
error Unavailable();
}// SPDX-License-Identifier: Unlicense
pragma solidity =0.8.27;
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "contracts/lib/Errors.sol";
/// @title SafeETHTransfer: Safely transfers ETH.
contract SafeETHTransfer is ReentrancyGuard {
mapping(address => uint256) private _stuckETH;
error TransferFailed(address account, uint256 amount);
error NothingStuck();
event StuckETHClaimed(address indexed account, address indexed receiver, uint256 amount);
event ETHTransferFailed(address indexed account, uint256 amount);
/**
* @notice Claim stuck ETH.
* @param _receiver Address to receive the ETH.
*/
function claimStuckETH(address _receiver) external nonReentrant {
if (_receiver == address(0)) revert Errors.InvalidAddress();
uint256 amount = _stuckETH[msg.sender];
if (amount == 0) revert NothingStuck();
/// @dev clear balance prior to transferring to prevent reentrancy in receive() function.
_stuckETH[msg.sender] = 0;
_safeETHTransferWithRevert(_receiver, amount);
emit StuckETHClaimed(msg.sender, _receiver, amount);
}
/**
* @notice Get the amount of stuck ETH for a given address.
* @param _address Address.
* @return uint256 ETH stuck.
*/
function getStuckETHTokens(address _address) external view returns (uint256) {
if (_address == address(0)) revert Errors.InvalidAddress();
return _stuckETH[_address];
}
/**
* @param _account Address to transfer _amount to.
* @param _amount Amount of the ETH to transfer.
*/
function _safeETHTransfer(address _account, uint256 _amount) internal {
(bool success, ) = _account.call{value: _amount}("");
if (!success) {
_stuckETH[_account] += _amount;
emit ETHTransferFailed(_account, _amount);
}
}
/**
* @param _account Address.
* @param _amount Amount of the ETH to transfer.
*/
function _safeETHTransferWithRevert(address _account, uint256 _amount) internal {
(bool success, ) = _account.call{value: _amount}("");
if (!success) revert TransferFailed(_account, _amount);
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"factory_","type":"address"},{"internalType":"address","name":"weth_","type":"address"},{"internalType":"contract IFeeHandler","name":"feeHandler_","type":"address"},{"internalType":"contract IAgentNameService","name":"agentNameService_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidIndex","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"NothingStuck","type":"error"},{"inputs":[],"name":"PrematureExecution","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"Unavailable","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"cooldownIndex","type":"uint256"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"claimableAt","type":"uint64"}],"indexed":false,"internalType":"struct AgentKey.Cooldown","name":"cooldown","type":"tuple"}],"name":"Cancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"cooldownIndex","type":"uint256"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"claimableAt","type":"uint64"}],"indexed":false,"internalType":"struct AgentKey.Cooldown","name":"cooldown","type":"tuple"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ETHTransferFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokensSwapped","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"adminAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"creatorAmount","type":"uint256"}],"name":"FeesCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[],"name":"Launched","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pair","type":"address"}],"name":"PairUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StuckETHClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"ak","type":"uint256"}],"name":"Subscribed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"cooldownIndex","type":"uint256"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"claimableAt","type":"uint64"}],"indexed":false,"internalType":"struct AgentKey.Cooldown","name":"cooldown","type":"tuple"}],"name":"Unsubscribed","type":"event"},{"inputs":[],"name":"adminSellFeePercent","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ansTokenID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bondingCurve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cooldownIndex","type":"uint256"}],"name":"cancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cooldownIndex","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"claimStuckETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"creatorSellFeePercent","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_cooldownIndex","type":"uint256"}],"name":"getCooldown","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"claimableAt","type":"uint64"}],"internalType":"struct AgentKey.Cooldown","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getMembership","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getStuckETHTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getTotalCooldowns","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hasLaunched","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_bondingCurve","type":"address"},{"internalType":"contract IUniswapV2Router02","name":"_router","type":"address"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"uint256","name":"_ansTokenID","type":"uint256"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"uint8","name":"_adminSellFeePercent","type":"uint8"},{"internalType":"uint8","name":"_creatorSellFeePercent","type":"uint8"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"launch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pair","type":"address"}],"name":"setPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"subscribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unsubscribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
61010060405234801561001157600080fd5b5060405161272e38038061272e833981016040819052610030916100ce565b60016000556001600160a01b038416158061005257506001600160a01b038316155b8061006457506001600160a01b038216155b8061007657506001600160a01b038116155b156100945760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b0393841660e052918316608052821660a0521660c05261012d565b6001600160a01b03811681146100cb57600080fd5b50565b600080600080608085870312156100e457600080fd5b84516100ef816100b6565b6020860151909450610100816100b6565b6040860151909350610111816100b6565b6060860151909250610122816100b6565b939692955090935050565b60805160a05160c05160e0516125ba610174600039600081816110c70152818161188a01526118fe015260006111bc01526000611b1c01526000611d0301526125ba6000f3fe6080604052600436106101dc5760003560e01c806363a2b3ab11610102578063a9059cbb11610095578063e47517e011610064578063e47517e01461058c578063e75473d9146105ad578063eff1d50e146105cd578063f887ea40146105ed57600080fd5b8063a9059cbb1461050c578063ad0b27fb1461052c578063b8320fab1461054c578063dd62ed3e1461056c57600080fd5b80638cbfd1f8116100d15780638cbfd1f8146104a157806395d89b41146104b7578063971f6ba4146104cc578063a8aa1b31146104ec57600080fd5b806363a2b3ab1461042057806370a082311461044157806379cc6790146104615780638187f5161461048157600080fd5b806323b872dd1161017a57806340e58ee51161014957806340e58ee51461038757806342966c68146103a757806361d027b3146103c7578063631d0b49146103ff57600080fd5b806323b872dd14610305578063313ce5671461032557806334c5a04414610347578063379607f51461036757600080fd5b8063095ea7b3116101b6578063095ea7b3146102575780630f574ba71461028757806318160ddd146102a75780631f15d256146102e557600080fd5b806301339c21146101e857806306e67cbc146101ff57806306fdde031461023557600080fd5b366101e357005b600080fd5b3480156101f457600080fd5b506101fd61060d565b005b34801561020b57600080fd5b5061021f61021a366004611f00565b610675565b60405161022c9190611f2c565b60405180910390f35b34801561024157600080fd5b5061024a610717565b60405161022c9190611f70565b34801561026357600080fd5b50610277610272366004611f00565b6107da565b604051901515815260200161022c565b34801561029357600080fd5b506101fd6102a2366004611fa3565b6107f2565b3480156102b357600080fd5b507f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b60405190815260200161022c565b3480156102f157600080fd5b506102d7610300366004611fbc565b61089e565b34801561031157600080fd5b50610277610320366004611fd9565b6108e3565b34801561033157600080fd5b5060125b60405160ff909116815260200161022c565b34801561035357600080fd5b506102d7610362366004611fbc565b610946565b34801561037357600080fd5b506101fd610382366004611fa3565b61098b565b34801561039357600080fd5b506101fd6103a2366004611fa3565b610b89565b3480156103b357600080fd5b506101fd6103c2366004611fa3565b610d83565b3480156103d357600080fd5b506005546103e7906001600160a01b031681565b6040516001600160a01b03909116815260200161022c565b34801561040b57600080fd5b5060065461033590600160a81b900460ff1681565b34801561042c57600080fd5b5060065461027790600160b01b900460ff1681565b34801561044d57600080fd5b506102d761045c366004611fbc565b610d8d565b34801561046d57600080fd5b506101fd61047c366004611f00565b610db5565b34801561048d57600080fd5b506101fd61049c366004611fbc565b610dce565b3480156104ad57600080fd5b506102d760045481565b3480156104c357600080fd5b5061024a610e4c565b3480156104d857600080fd5b506102d76104e7366004611fbc565b610e8b565b3480156104f857600080fd5b506003546103e7906001600160a01b031681565b34801561051857600080fd5b50610277610527366004611f00565b610ed0565b34801561053857600080fd5b506101fd610547366004611fa3565b610ede565b34801561055857600080fd5b506101fd610567366004612098565b611005565b34801561057857600080fd5b506102d7610587366004612178565b6112e6565b34801561059857600080fd5b5060065461033590600160a01b900460ff1681565b3480156105b957600080fd5b506101fd6105c8366004611fbc565b611330565b3480156105d957600080fd5b506006546103e7906001600160a01b031681565b3480156105f957600080fd5b506002546103e7906001600160a01b031681565b6006546001600160a01b03163314610637576040516282b42960e81b815260040160405180910390fd5b6006805460ff60b01b1916600160b01b1790556040517fba61a96074b3d636edeee92caddc86293c917d5b6818b7d3698bb52e02ec86c890600090a1565b6040805180820190915260008082526020820152816106938461089e565b116106b1576040516363df817160e01b815260040160405180910390fd5b6001600160a01b03831660009081526008602052604090208054839081106106db576106db6121b1565b60009182526020918290206040805180820190915260029092020180548252600101546001600160401b03169181019190915290505b92915050565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03805460609160008051602061256583398151915291610756906121c7565b80601f0160208091040260200160405190810160405280929190818152602001828054610782906121c7565b80156107cf5780601f106107a4576101008083540402835291602001916107cf565b820191906000526020600020905b8154815290600101906020018083116107b257829003601f168201915b505050505091505090565b6000336107e88185856113f5565b5060019392505050565b6107fa611407565b80158061080e57508061080c33610d8d565b105b1561082c5760405163162908e360e11b815260040160405180910390fd5b336000908152600760205260408120805483929061084b908490612217565b9091555061085c9050333083611431565b60405181815233907f4b90d6788928d63c1821907a6a8b95f40d26562d8fe41b105f7489db9966dfcb9060200160405180910390a261089b6001600055565b50565b60006001600160a01b0382166108c75760405163e6c4247b60e01b815260040160405180910390fd5b506001600160a01b031660009081526008602052604090205490565b600654600090600160b01b900460ff161561090a57610903848484611531565b905061093f565b6006546001600160a01b03163314610934576040516282b42960e81b815260040160405180910390fd5b6107e8848484611555565b9392505050565b60006001600160a01b03821661096f5760405163e6c4247b60e01b815260040160405180910390fd5b506001600160a01b031660009081526007602052604090205490565b610993611407565b336000908152600860205260409020548181116109c3576040516363df817160e01b815260040160405180910390fd5b3360009081526008602052604081208054849081106109e4576109e46121b1565b60009182526020918290206040805180820190915260029092020180548252600101546001600160401b03169181018290529150421015610a3857604051630b20b78160e21b815260040160405180910390fd5b336000908152600860205260409020610a5260018461222a565b81548110610a6257610a626121b1565b906000526020600020906002020160086000336001600160a01b03166001600160a01b031681526020019081526020016000208481548110610aa657610aa66121b1565b60009182526020808320845460029093020191825560019384015493909101805467ffffffffffffffff19166001600160401b0390941693909317909255338152600890915260409020805480610aff57610aff61223d565b600082815260208120600260001990930192830201908155600101805467ffffffffffffffff1916905590558051610b3a9030903390611431565b336001600160a01b03167ffe87524983023b305b62c951a20ce614fdd20a03f0ad63190a82e7f04eb281f58483604051610b75929190612253565b60405180910390a2505061089b6001600055565b610b91611407565b33600090815260086020526040902054818111610bc1576040516363df817160e01b815260040160405180910390fd5b336000908152600860205260408120805484908110610be257610be26121b1565b60009182526020918290206040805180820190915260029092020180548252600101546001600160401b031691810182905291504210610c355760405163a3b8915f60e01b815260040160405180910390fd5b336000908152600860205260409020610c4f60018461222a565b81548110610c5f57610c5f6121b1565b906000526020600020906002020160086000336001600160a01b03166001600160a01b031681526020019081526020016000208481548110610ca357610ca36121b1565b60009182526020808320845460029093020191825560019384015493909101805467ffffffffffffffff19166001600160401b0390941693909317909255338152600890915260409020805480610cfc57610cfc61223d565b60008281526020808220600260001990940193840201828155600101805467ffffffffffffffff19169055919092558251338352600790915260408220805491929091610d4a908490612217565b909155505060405133907f135ef071be5fba513f29bc4c11d5fb001674c6cbcb7aa9eadfda0ffae5361b7590610b759086908590612253565b61089b33826115b9565b6001600160a01b03166000908152600080516020612565833981519152602052604090205490565b610dc08233836115ef565b610dca82826115b9565b5050565b6006546001600160a01b03163314610df8576040516282b42960e81b815260040160405180910390fd5b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527f1d288f7aba265e8b154b112bbb631ceca5df5fe93a750b2fe042fd1cc826647f9060200160405180910390a150565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace04805460609160008051602061256583398151915291610756906121c7565b60006001600160a01b038216610eb45760405163e6c4247b60e01b815260040160405180910390fd5b506001600160a01b031660009081526001602052604090205490565b6000336107e8818585611555565b610ee6611407565b801580610f0157503360009081526007602052604090205481115b15610f1f5760405163162908e360e11b815260040160405180910390fd5b3360009081526007602052604081208054839290610f3e90849061222a565b9091555060009050610f536212750042612217565b6040805180820182528481526001600160401b038381166020808401918252336000818152600883528681208054600180820183559183529390912086516002850290910190815593519301805467ffffffffffffffff19169390941692909217909255925193945090929091907f6e6a83d8c37bdab65fdd82e413fc68d0dcdb44130552b4acda219f7de250a61f90610ff09084908690612253565b60405180910390a250505061089b6001600055565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b031660008115801561104a5750825b90506000826001600160401b031660011480156110665750303b155b905081158015611074575080155b156110925760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff1916600117855583156110bc57845460ff60401b1916600160401b1785555b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611104576040516282b42960e81b815260040160405180910390fd5b8b600660006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a600260006101000a8154816001600160a01b0302191690836001600160a01b031602179055508860048190555087600560006101000a8154816001600160a01b0302191690836001600160a01b0316021790555086600660146101000a81548160ff021916908360ff16021790555085600660156101000a81548160ff021916908360ff1602179055506112548a7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166317fd1d806004546040518263ffffffff1660e01b815260040161120a91815260200190565b600060405180830381865afa158015611227573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261124f919081019061227a565b61164f565b6112698c6a115eec47f6cf7e35000000611661565b6040517f5daa87a0e9463431830481fd4b6e3403442dfb9a12b9c07597e9f61d50b633c890600090a183156112d857845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050505050565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b611338611407565b6001600160a01b03811661135f5760405163e6c4247b60e01b815260040160405180910390fd5b33600090815260016020526040812054908190036113905760405163fc5606d360e01b815260040160405180910390fd5b336000908152600160205260408120556113aa8282611697565b6040518181526001600160a01b0383169033907f6ae2b28445c1b0a012dd5a2918d117313e2e8bc4aa561365e42c52643fca7ad39060200160405180910390a35061089b6001600055565b611402838383600161171d565b505050565b60026000540361142a57604051633ee5aeb560e01b815260040160405180910390fd5b6002600055565b600654600160b01b900460ff1615801561145257506114508383611805565b155b156114705760405163a3b8915f60e01b815260040160405180910390fd5b600654600160b81b900460ff1615801561149757506003546001600160a01b038381169116145b80156114ad57506003546001600160a01b031615155b15611526576006546000906103e8906114d99060ff600160a81b8204811691600160a01b9004166122f0565b6114e69060ff1684612309565b6114f09190612320565b9050801561150c57611503843083611968565b61150c81611aa6565b611520848461151b848661222a565b611968565b50505050565b611402838383611968565b60003361153f8582856115ef565b61154a858585611555565b506001949350505050565b6001600160a01b03831661158457604051634b637e8f60e11b8152600060048201526024015b60405180910390fd5b6001600160a01b0382166115ae5760405163ec442f0560e01b81526000600482015260240161157b565b611402838383611431565b6001600160a01b0382166115e357604051634b637e8f60e11b81526000600482015260240161157b565b610dca82600083611431565b60006115fb84846112e6565b90506000198114611520578181101561164057604051637dc7a0d960e11b81526001600160a01b0384166004820152602481018290526044810183905260640161157b565b6115208484848403600061171d565b611657611bf9565b610dca8282611c44565b6001600160a01b03821661168b5760405163ec442f0560e01b81526000600482015260240161157b565b610dca60008383611431565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146116e4576040519150601f19603f3d011682016040523d82523d6000602084013e6116e9565b606091505b505090508061140257604051630e21dcbb60e11b81526001600160a01b03841660048201526024810183905260440161157b565b6000805160206125658339815191526001600160a01b0385166117565760405163e602df0560e01b81526000600482015260240161157b565b6001600160a01b03841661178057604051634a1406b160e11b81526000600482015260240161157b565b6001600160a01b038086166000908152600183016020908152604080832093881683529290522083905581156117fe57836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925856040516117f591815260200190565b60405180910390a35b5050505050565b60006001600160a01b03821630148061182657506001600160a01b03831630145b1561183357506001610711565b6006546001600160a01b03838116911614801561185a57506006546001600160a01b031633145b1561186757506001610711565b6006546001600160a01b0384811691161480156118be5750813b15806118be57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316145b156118cb57506001610711565b6001600160a01b0383161580156118ef57506006546001600160a01b038381169116145b156118fc57506001610711565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614801561193c5750813b155b1561194957506001610711565b6001600160a01b03821661195f57506001610711565b50600092915050565b6000805160206125658339815191526001600160a01b0384166119a457818160020160008282546119999190612217565b90915550611a169050565b6001600160a01b038416600090815260208290526040902054828110156119f75760405163391434e360e21b81526001600160a01b0386166004820152602481018290526044810184905260640161157b565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b038316611a34576002810180548390039055611a53565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611a9891815260200190565b60405180910390a350505050565b611aae611407565b6000611ab982611c95565b600654909150600090611adf9060ff600160a81b8204811691600160a01b9004166122f0565b60065460ff91821691611afa91600160a01b90041684612309565b611b049190612320565b90506000611b12828461222a565b90508115611b8f577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631b9265b8836040518263ffffffff1660e01b81526004016000604051808303818588803b158015611b7557600080fd5b505af1158015611b89573d6000803e3d6000fd5b50505050505b8015611bab57600554611bab906001600160a01b031682611e10565b60408051858152602081018490529081018290527fa54e6c2fc0861aa9c991b26891d71059d517983b9e84b91020f42609c452eb9d9060600160405180910390a150505061089b6001600055565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16611c4257604051631afcd79f60e31b815260040160405180910390fd5b565b611c4c611bf9565b6000805160206125658339815191527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03611c868482612389565b50600481016115208382612389565b6006805460ff60b81b1916600160b81b179055604080516002808252606082018352600092839291906020830190803683370190505090503081600081518110611ce157611ce16121b1565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000000000000000000000000000000000000000000081600181518110611d3557611d356121b1565b6001600160a01b039283166020918202929092010152600254611d5d9130911685600061171d565b6002546040516318cbafe560e01b81526000916001600160a01b0316906318cbafe590611d969087908590879030904290600401612447565b6000604051808303816000875af1158015611db5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ddd91908101906124b9565b905080600181518110611df257611df26121b1565b6020026020010151925050506006805460ff60b81b19169055919050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611e5d576040519150601f19603f3d011682016040523d82523d6000602084013e611e62565b606091505b5050905080611402576001600160a01b03831660009081526001602052604081208054849290611e93908490612217565b90915550506040518281526001600160a01b038416907f5e0a829b064110e9c05dca83263ffb77f1674250e6704ec97887b3ae53c5b18f9060200160405180910390a2505050565b6001600160a01b038116811461089b57600080fd5b8035611efb81611edb565b919050565b60008060408385031215611f1357600080fd5b8235611f1e81611edb565b946020939093013593505050565b815181526020808301516001600160401b03169082015260408101610711565b60005b83811015611f67578181015183820152602001611f4f565b50506000910152565b6020815260008251806020840152611f8f816040850160208701611f4c565b601f01601f19169190910160400192915050565b600060208284031215611fb557600080fd5b5035919050565b600060208284031215611fce57600080fd5b813561093f81611edb565b600080600060608486031215611fee57600080fd5b8335611ff981611edb565b9250602084013561200981611edb565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156120585761205861201a565b604052919050565b60006001600160401b038211156120795761207961201a565b50601f01601f191660200190565b803560ff81168114611efb57600080fd5b600080600080600080600060e0888a0312156120b357600080fd5b87356120be81611edb565b965060208801356120ce81611edb565b955060408801356001600160401b038111156120e957600080fd5b8801601f81018a136120fa57600080fd5b803561210d61210882612060565b612030565b8181528b602083850101111561212257600080fd5b816020840160208301376000918101602001919091529550506060880135935061214e60808901611ef0565b925061215c60a08901612087565b915061216a60c08901612087565b905092959891949750929550565b6000806040838503121561218b57600080fd5b823561219681611edb565b915060208301356121a681611edb565b809150509250929050565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806121db57607f821691505b6020821081036121fb57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561071157610711612201565b8181038181111561071157610711612201565b634e487b7160e01b600052603160045260246000fd5b8281526060810161093f6020830184805182526020908101516001600160401b0316910152565b60006020828403121561228c57600080fd5b81516001600160401b038111156122a257600080fd5b8201601f810184136122b357600080fd5b80516122c161210882612060565b8181528560208385010111156122d657600080fd5b6122e7826020830160208601611f4c565b95945050505050565b60ff818116838216019081111561071157610711612201565b808202811582820484141761071157610711612201565b60008261233d57634e487b7160e01b600052601260045260246000fd5b500490565b601f82111561140257806000526020600020601f840160051c810160208510156123695750805b601f840160051c820191505b818110156117fe5760008155600101612375565b81516001600160401b038111156123a2576123a261201a565b6123b6816123b084546121c7565b84612342565b6020601f8211600181146123ea57600083156123d25750848201515b600019600385901b1c1916600184901b1784556117fe565b600084815260208120601f198516915b8281101561241a57878501518255602094850194600190920191016123fa565b50848210156124385786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b600060a0820187835286602084015260a0604084015280865180835260c08501915060208801925060005b818110156124995783516001600160a01b0316835260209384019390920191600101612472565b50506001600160a01b039590951660608401525050608001529392505050565b6000602082840312156124cb57600080fd5b81516001600160401b038111156124e157600080fd5b8201601f810184136124f257600080fd5b80516001600160401b0381111561250b5761250b61201a565b8060051b61251b60208201612030565b9182526020818401810192908101908784111561253757600080fd5b6020850194505b8385101561255957845182526020948501949091019061253e565b97965050505050505056fe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00a2646970667358221220b45e08f4eeed1f1de630f74c81ccec4c823a136ccd67ebd9784e3fd15cc1639e64736f6c634300081b00330000000000000000000000009e711dd562dd7c84127780949ac3fd5a831366760000000000000000000000004200000000000000000000000000000000000006000000000000000000000000e794f7eb7e644eb49056133373fb9b1ea39f22ad0000000000000000000000006623206875c37bcecf67c362d4dd1c96bd5c34d8
Deployed Bytecode
0x6080604052600436106101dc5760003560e01c806363a2b3ab11610102578063a9059cbb11610095578063e47517e011610064578063e47517e01461058c578063e75473d9146105ad578063eff1d50e146105cd578063f887ea40146105ed57600080fd5b8063a9059cbb1461050c578063ad0b27fb1461052c578063b8320fab1461054c578063dd62ed3e1461056c57600080fd5b80638cbfd1f8116100d15780638cbfd1f8146104a157806395d89b41146104b7578063971f6ba4146104cc578063a8aa1b31146104ec57600080fd5b806363a2b3ab1461042057806370a082311461044157806379cc6790146104615780638187f5161461048157600080fd5b806323b872dd1161017a57806340e58ee51161014957806340e58ee51461038757806342966c68146103a757806361d027b3146103c7578063631d0b49146103ff57600080fd5b806323b872dd14610305578063313ce5671461032557806334c5a04414610347578063379607f51461036757600080fd5b8063095ea7b3116101b6578063095ea7b3146102575780630f574ba71461028757806318160ddd146102a75780631f15d256146102e557600080fd5b806301339c21146101e857806306e67cbc146101ff57806306fdde031461023557600080fd5b366101e357005b600080fd5b3480156101f457600080fd5b506101fd61060d565b005b34801561020b57600080fd5b5061021f61021a366004611f00565b610675565b60405161022c9190611f2c565b60405180910390f35b34801561024157600080fd5b5061024a610717565b60405161022c9190611f70565b34801561026357600080fd5b50610277610272366004611f00565b6107da565b604051901515815260200161022c565b34801561029357600080fd5b506101fd6102a2366004611fa3565b6107f2565b3480156102b357600080fd5b507f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b60405190815260200161022c565b3480156102f157600080fd5b506102d7610300366004611fbc565b61089e565b34801561031157600080fd5b50610277610320366004611fd9565b6108e3565b34801561033157600080fd5b5060125b60405160ff909116815260200161022c565b34801561035357600080fd5b506102d7610362366004611fbc565b610946565b34801561037357600080fd5b506101fd610382366004611fa3565b61098b565b34801561039357600080fd5b506101fd6103a2366004611fa3565b610b89565b3480156103b357600080fd5b506101fd6103c2366004611fa3565b610d83565b3480156103d357600080fd5b506005546103e7906001600160a01b031681565b6040516001600160a01b03909116815260200161022c565b34801561040b57600080fd5b5060065461033590600160a81b900460ff1681565b34801561042c57600080fd5b5060065461027790600160b01b900460ff1681565b34801561044d57600080fd5b506102d761045c366004611fbc565b610d8d565b34801561046d57600080fd5b506101fd61047c366004611f00565b610db5565b34801561048d57600080fd5b506101fd61049c366004611fbc565b610dce565b3480156104ad57600080fd5b506102d760045481565b3480156104c357600080fd5b5061024a610e4c565b3480156104d857600080fd5b506102d76104e7366004611fbc565b610e8b565b3480156104f857600080fd5b506003546103e7906001600160a01b031681565b34801561051857600080fd5b50610277610527366004611f00565b610ed0565b34801561053857600080fd5b506101fd610547366004611fa3565b610ede565b34801561055857600080fd5b506101fd610567366004612098565b611005565b34801561057857600080fd5b506102d7610587366004612178565b6112e6565b34801561059857600080fd5b5060065461033590600160a01b900460ff1681565b3480156105b957600080fd5b506101fd6105c8366004611fbc565b611330565b3480156105d957600080fd5b506006546103e7906001600160a01b031681565b3480156105f957600080fd5b506002546103e7906001600160a01b031681565b6006546001600160a01b03163314610637576040516282b42960e81b815260040160405180910390fd5b6006805460ff60b01b1916600160b01b1790556040517fba61a96074b3d636edeee92caddc86293c917d5b6818b7d3698bb52e02ec86c890600090a1565b6040805180820190915260008082526020820152816106938461089e565b116106b1576040516363df817160e01b815260040160405180910390fd5b6001600160a01b03831660009081526008602052604090208054839081106106db576106db6121b1565b60009182526020918290206040805180820190915260029092020180548252600101546001600160401b03169181019190915290505b92915050565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03805460609160008051602061256583398151915291610756906121c7565b80601f0160208091040260200160405190810160405280929190818152602001828054610782906121c7565b80156107cf5780601f106107a4576101008083540402835291602001916107cf565b820191906000526020600020905b8154815290600101906020018083116107b257829003601f168201915b505050505091505090565b6000336107e88185856113f5565b5060019392505050565b6107fa611407565b80158061080e57508061080c33610d8d565b105b1561082c5760405163162908e360e11b815260040160405180910390fd5b336000908152600760205260408120805483929061084b908490612217565b9091555061085c9050333083611431565b60405181815233907f4b90d6788928d63c1821907a6a8b95f40d26562d8fe41b105f7489db9966dfcb9060200160405180910390a261089b6001600055565b50565b60006001600160a01b0382166108c75760405163e6c4247b60e01b815260040160405180910390fd5b506001600160a01b031660009081526008602052604090205490565b600654600090600160b01b900460ff161561090a57610903848484611531565b905061093f565b6006546001600160a01b03163314610934576040516282b42960e81b815260040160405180910390fd5b6107e8848484611555565b9392505050565b60006001600160a01b03821661096f5760405163e6c4247b60e01b815260040160405180910390fd5b506001600160a01b031660009081526007602052604090205490565b610993611407565b336000908152600860205260409020548181116109c3576040516363df817160e01b815260040160405180910390fd5b3360009081526008602052604081208054849081106109e4576109e46121b1565b60009182526020918290206040805180820190915260029092020180548252600101546001600160401b03169181018290529150421015610a3857604051630b20b78160e21b815260040160405180910390fd5b336000908152600860205260409020610a5260018461222a565b81548110610a6257610a626121b1565b906000526020600020906002020160086000336001600160a01b03166001600160a01b031681526020019081526020016000208481548110610aa657610aa66121b1565b60009182526020808320845460029093020191825560019384015493909101805467ffffffffffffffff19166001600160401b0390941693909317909255338152600890915260409020805480610aff57610aff61223d565b600082815260208120600260001990930192830201908155600101805467ffffffffffffffff1916905590558051610b3a9030903390611431565b336001600160a01b03167ffe87524983023b305b62c951a20ce614fdd20a03f0ad63190a82e7f04eb281f58483604051610b75929190612253565b60405180910390a2505061089b6001600055565b610b91611407565b33600090815260086020526040902054818111610bc1576040516363df817160e01b815260040160405180910390fd5b336000908152600860205260408120805484908110610be257610be26121b1565b60009182526020918290206040805180820190915260029092020180548252600101546001600160401b031691810182905291504210610c355760405163a3b8915f60e01b815260040160405180910390fd5b336000908152600860205260409020610c4f60018461222a565b81548110610c5f57610c5f6121b1565b906000526020600020906002020160086000336001600160a01b03166001600160a01b031681526020019081526020016000208481548110610ca357610ca36121b1565b60009182526020808320845460029093020191825560019384015493909101805467ffffffffffffffff19166001600160401b0390941693909317909255338152600890915260409020805480610cfc57610cfc61223d565b60008281526020808220600260001990940193840201828155600101805467ffffffffffffffff19169055919092558251338352600790915260408220805491929091610d4a908490612217565b909155505060405133907f135ef071be5fba513f29bc4c11d5fb001674c6cbcb7aa9eadfda0ffae5361b7590610b759086908590612253565b61089b33826115b9565b6001600160a01b03166000908152600080516020612565833981519152602052604090205490565b610dc08233836115ef565b610dca82826115b9565b5050565b6006546001600160a01b03163314610df8576040516282b42960e81b815260040160405180910390fd5b600380546001600160a01b0319166001600160a01b0383169081179091556040519081527f1d288f7aba265e8b154b112bbb631ceca5df5fe93a750b2fe042fd1cc826647f9060200160405180910390a150565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace04805460609160008051602061256583398151915291610756906121c7565b60006001600160a01b038216610eb45760405163e6c4247b60e01b815260040160405180910390fd5b506001600160a01b031660009081526001602052604090205490565b6000336107e8818585611555565b610ee6611407565b801580610f0157503360009081526007602052604090205481115b15610f1f5760405163162908e360e11b815260040160405180910390fd5b3360009081526007602052604081208054839290610f3e90849061222a565b9091555060009050610f536212750042612217565b6040805180820182528481526001600160401b038381166020808401918252336000818152600883528681208054600180820183559183529390912086516002850290910190815593519301805467ffffffffffffffff19169390941692909217909255925193945090929091907f6e6a83d8c37bdab65fdd82e413fc68d0dcdb44130552b4acda219f7de250a61f90610ff09084908690612253565b60405180910390a250505061089b6001600055565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b031660008115801561104a5750825b90506000826001600160401b031660011480156110665750303b155b905081158015611074575080155b156110925760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff1916600117855583156110bc57845460ff60401b1916600160401b1785555b336001600160a01b037f0000000000000000000000009e711dd562dd7c84127780949ac3fd5a831366761614611104576040516282b42960e81b815260040160405180910390fd5b8b600660006101000a8154816001600160a01b0302191690836001600160a01b031602179055508a600260006101000a8154816001600160a01b0302191690836001600160a01b031602179055508860048190555087600560006101000a8154816001600160a01b0302191690836001600160a01b0316021790555086600660146101000a81548160ff021916908360ff16021790555085600660156101000a81548160ff021916908360ff1602179055506112548a7f0000000000000000000000006623206875c37bcecf67c362d4dd1c96bd5c34d86001600160a01b03166317fd1d806004546040518263ffffffff1660e01b815260040161120a91815260200190565b600060405180830381865afa158015611227573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261124f919081019061227a565b61164f565b6112698c6a115eec47f6cf7e35000000611661565b6040517f5daa87a0e9463431830481fd4b6e3403442dfb9a12b9c07597e9f61d50b633c890600090a183156112d857845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050505050565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b611338611407565b6001600160a01b03811661135f5760405163e6c4247b60e01b815260040160405180910390fd5b33600090815260016020526040812054908190036113905760405163fc5606d360e01b815260040160405180910390fd5b336000908152600160205260408120556113aa8282611697565b6040518181526001600160a01b0383169033907f6ae2b28445c1b0a012dd5a2918d117313e2e8bc4aa561365e42c52643fca7ad39060200160405180910390a35061089b6001600055565b611402838383600161171d565b505050565b60026000540361142a57604051633ee5aeb560e01b815260040160405180910390fd5b6002600055565b600654600160b01b900460ff1615801561145257506114508383611805565b155b156114705760405163a3b8915f60e01b815260040160405180910390fd5b600654600160b81b900460ff1615801561149757506003546001600160a01b038381169116145b80156114ad57506003546001600160a01b031615155b15611526576006546000906103e8906114d99060ff600160a81b8204811691600160a01b9004166122f0565b6114e69060ff1684612309565b6114f09190612320565b9050801561150c57611503843083611968565b61150c81611aa6565b611520848461151b848661222a565b611968565b50505050565b611402838383611968565b60003361153f8582856115ef565b61154a858585611555565b506001949350505050565b6001600160a01b03831661158457604051634b637e8f60e11b8152600060048201526024015b60405180910390fd5b6001600160a01b0382166115ae5760405163ec442f0560e01b81526000600482015260240161157b565b611402838383611431565b6001600160a01b0382166115e357604051634b637e8f60e11b81526000600482015260240161157b565b610dca82600083611431565b60006115fb84846112e6565b90506000198114611520578181101561164057604051637dc7a0d960e11b81526001600160a01b0384166004820152602481018290526044810183905260640161157b565b6115208484848403600061171d565b611657611bf9565b610dca8282611c44565b6001600160a01b03821661168b5760405163ec442f0560e01b81526000600482015260240161157b565b610dca60008383611431565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146116e4576040519150601f19603f3d011682016040523d82523d6000602084013e6116e9565b606091505b505090508061140257604051630e21dcbb60e11b81526001600160a01b03841660048201526024810183905260440161157b565b6000805160206125658339815191526001600160a01b0385166117565760405163e602df0560e01b81526000600482015260240161157b565b6001600160a01b03841661178057604051634a1406b160e11b81526000600482015260240161157b565b6001600160a01b038086166000908152600183016020908152604080832093881683529290522083905581156117fe57836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925856040516117f591815260200190565b60405180910390a35b5050505050565b60006001600160a01b03821630148061182657506001600160a01b03831630145b1561183357506001610711565b6006546001600160a01b03838116911614801561185a57506006546001600160a01b031633145b1561186757506001610711565b6006546001600160a01b0384811691161480156118be5750813b15806118be57507f0000000000000000000000009e711dd562dd7c84127780949ac3fd5a831366766001600160a01b0316826001600160a01b0316145b156118cb57506001610711565b6001600160a01b0383161580156118ef57506006546001600160a01b038381169116145b156118fc57506001610711565b7f0000000000000000000000009e711dd562dd7c84127780949ac3fd5a831366766001600160a01b0316836001600160a01b031614801561193c5750813b155b1561194957506001610711565b6001600160a01b03821661195f57506001610711565b50600092915050565b6000805160206125658339815191526001600160a01b0384166119a457818160020160008282546119999190612217565b90915550611a169050565b6001600160a01b038416600090815260208290526040902054828110156119f75760405163391434e360e21b81526001600160a01b0386166004820152602481018290526044810184905260640161157b565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b038316611a34576002810180548390039055611a53565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611a9891815260200190565b60405180910390a350505050565b611aae611407565b6000611ab982611c95565b600654909150600090611adf9060ff600160a81b8204811691600160a01b9004166122f0565b60065460ff91821691611afa91600160a01b90041684612309565b611b049190612320565b90506000611b12828461222a565b90508115611b8f577f000000000000000000000000e794f7eb7e644eb49056133373fb9b1ea39f22ad6001600160a01b0316631b9265b8836040518263ffffffff1660e01b81526004016000604051808303818588803b158015611b7557600080fd5b505af1158015611b89573d6000803e3d6000fd5b50505050505b8015611bab57600554611bab906001600160a01b031682611e10565b60408051858152602081018490529081018290527fa54e6c2fc0861aa9c991b26891d71059d517983b9e84b91020f42609c452eb9d9060600160405180910390a150505061089b6001600055565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16611c4257604051631afcd79f60e31b815260040160405180910390fd5b565b611c4c611bf9565b6000805160206125658339815191527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03611c868482612389565b50600481016115208382612389565b6006805460ff60b81b1916600160b81b179055604080516002808252606082018352600092839291906020830190803683370190505090503081600081518110611ce157611ce16121b1565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000420000000000000000000000000000000000000681600181518110611d3557611d356121b1565b6001600160a01b039283166020918202929092010152600254611d5d9130911685600061171d565b6002546040516318cbafe560e01b81526000916001600160a01b0316906318cbafe590611d969087908590879030904290600401612447565b6000604051808303816000875af1158015611db5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ddd91908101906124b9565b905080600181518110611df257611df26121b1565b6020026020010151925050506006805460ff60b81b19169055919050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611e5d576040519150601f19603f3d011682016040523d82523d6000602084013e611e62565b606091505b5050905080611402576001600160a01b03831660009081526001602052604081208054849290611e93908490612217565b90915550506040518281526001600160a01b038416907f5e0a829b064110e9c05dca83263ffb77f1674250e6704ec97887b3ae53c5b18f9060200160405180910390a2505050565b6001600160a01b038116811461089b57600080fd5b8035611efb81611edb565b919050565b60008060408385031215611f1357600080fd5b8235611f1e81611edb565b946020939093013593505050565b815181526020808301516001600160401b03169082015260408101610711565b60005b83811015611f67578181015183820152602001611f4f565b50506000910152565b6020815260008251806020840152611f8f816040850160208701611f4c565b601f01601f19169190910160400192915050565b600060208284031215611fb557600080fd5b5035919050565b600060208284031215611fce57600080fd5b813561093f81611edb565b600080600060608486031215611fee57600080fd5b8335611ff981611edb565b9250602084013561200981611edb565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156120585761205861201a565b604052919050565b60006001600160401b038211156120795761207961201a565b50601f01601f191660200190565b803560ff81168114611efb57600080fd5b600080600080600080600060e0888a0312156120b357600080fd5b87356120be81611edb565b965060208801356120ce81611edb565b955060408801356001600160401b038111156120e957600080fd5b8801601f81018a136120fa57600080fd5b803561210d61210882612060565b612030565b8181528b602083850101111561212257600080fd5b816020840160208301376000918101602001919091529550506060880135935061214e60808901611ef0565b925061215c60a08901612087565b915061216a60c08901612087565b905092959891949750929550565b6000806040838503121561218b57600080fd5b823561219681611edb565b915060208301356121a681611edb565b809150509250929050565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806121db57607f821691505b6020821081036121fb57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561071157610711612201565b8181038181111561071157610711612201565b634e487b7160e01b600052603160045260246000fd5b8281526060810161093f6020830184805182526020908101516001600160401b0316910152565b60006020828403121561228c57600080fd5b81516001600160401b038111156122a257600080fd5b8201601f810184136122b357600080fd5b80516122c161210882612060565b8181528560208385010111156122d657600080fd5b6122e7826020830160208601611f4c565b95945050505050565b60ff818116838216019081111561071157610711612201565b808202811582820484141761071157610711612201565b60008261233d57634e487b7160e01b600052601260045260246000fd5b500490565b601f82111561140257806000526020600020601f840160051c810160208510156123695750805b601f840160051c820191505b818110156117fe5760008155600101612375565b81516001600160401b038111156123a2576123a261201a565b6123b6816123b084546121c7565b84612342565b6020601f8211600181146123ea57600083156123d25750848201515b600019600385901b1c1916600184901b1784556117fe565b600084815260208120601f198516915b8281101561241a57878501518255602094850194600190920191016123fa565b50848210156124385786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b600060a0820187835286602084015260a0604084015280865180835260c08501915060208801925060005b818110156124995783516001600160a01b0316835260209384019390920191600101612472565b50506001600160a01b039590951660608401525050608001529392505050565b6000602082840312156124cb57600080fd5b81516001600160401b038111156124e157600080fd5b8201601f810184136124f257600080fd5b80516001600160401b0381111561250b5761250b61201a565b8060051b61251b60208201612030565b9182526020818401810192908101908784111561253757600080fd5b6020850194505b8385101561255957845182526020948501949091019061253e565b97965050505050505056fe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00a2646970667358221220b45e08f4eeed1f1de630f74c81ccec4c823a136ccd67ebd9784e3fd15cc1639e64736f6c634300081b0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009e711dd562dd7c84127780949ac3fd5a831366760000000000000000000000004200000000000000000000000000000000000006000000000000000000000000e794f7eb7e644eb49056133373fb9b1ea39f22ad0000000000000000000000006623206875c37bcecf67c362d4dd1c96bd5c34d8
-----Decoded View---------------
Arg [0] : factory_ (address): 0x9e711dD562DD7C84127780949Ac3FD5a83136676
Arg [1] : weth_ (address): 0x4200000000000000000000000000000000000006
Arg [2] : feeHandler_ (address): 0xE794f7eB7e644Eb49056133373fb9B1eA39f22Ad
Arg [3] : agentNameService_ (address): 0x6623206875C37bcEcF67c362d4dd1c96bD5C34d8
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000009e711dd562dd7c84127780949ac3fd5a83136676
Arg [1] : 0000000000000000000000004200000000000000000000000000000000000006
Arg [2] : 000000000000000000000000e794f7eb7e644eb49056133373fb9b1ea39f22ad
Arg [3] : 0000000000000000000000006623206875c37bcecf67c362d4dd1c96bd5c34d8
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 32 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.