Latest 25 from a total of 28 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Receive Asset | 60830723 | 157 days ago | IN | 0 BNB | 0.00000761 | ||||
| Mint Asset | 60830202 | 157 days ago | IN | 0 BNB | 0.0000067 | ||||
| Mint Asset | 60243577 | 162 days ago | IN | 0 BNB | 0.00000499 | ||||
| Mint Asset | 60243526 | 162 days ago | IN | 0 BNB | 0.00000499 | ||||
| Receive Asset | 60243444 | 162 days ago | IN | 0 BNB | 0.00000713 | ||||
| Mint Asset | 60230747 | 162 days ago | IN | 0 BNB | 0.00000499 | ||||
| Mint Asset | 60227566 | 162 days ago | IN | 0 BNB | 0.000005 | ||||
| Receive Asset | 60227348 | 162 days ago | IN | 0 BNB | 0.00000713 | ||||
| Receive Asset | 60227224 | 162 days ago | IN | 0 BNB | 0.00000713 | ||||
| Mint Asset | 60227126 | 162 days ago | IN | 0 BNB | 0.00000499 | ||||
| Mint Asset | 60226783 | 162 days ago | IN | 0 BNB | 0.00000499 | ||||
| Receive Asset | 60226597 | 162 days ago | IN | 0 BNB | 0.00000713 | ||||
| Receive Asset | 60226469 | 162 days ago | IN | 0 BNB | 0.00000884 | ||||
| Mint Asset | 60226319 | 162 days ago | IN | 0 BNB | 0.00000499 | ||||
| Mint Asset | 60222405 | 162 days ago | IN | 0 BNB | 0.00000499 | ||||
| Receive Asset | 54963073 | 208 days ago | IN | 0 BNB | 0.00000713 | ||||
| Receive Asset | 54962456 | 208 days ago | IN | 0 BNB | 0.00000713 | ||||
| Mint Asset | 54962009 | 208 days ago | IN | 0 BNB | 0.00000499 | ||||
| Mint Asset | 54961394 | 208 days ago | IN | 0 BNB | 0.00000499 | ||||
| Receive Asset | 54959111 | 208 days ago | IN | 0 BNB | 0.00000713 | ||||
| Receive Asset | 54955873 | 208 days ago | IN | 0 BNB | 0.00000884 | ||||
| Mint Asset | 54955792 | 208 days ago | IN | 0 BNB | 0.00000499 | ||||
| Mint Asset | 54955510 | 208 days ago | IN | 0 BNB | 0.00000499 | ||||
| Mint Asset | 54446304 | 212 days ago | IN | 0 BNB | 0.00000499 | ||||
| Mint Asset | 54275049 | 214 days ago | IN | 0 BNB | 0.00000499 |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Bridge
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0 <0.9.0;
import {TokenManager} from "./TokenManager.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/**
* @title Bridge
* @dev Manages cross-chain token transfers for the Project Merlin ecosystem
*
* This contract handles the bridging of tokens between different chains.
* It includes fee management, pausable operations, and integration with
* an offchain processor for cross-chain communication.
*
* Security considerations:
* - Only Oracle can control fees and pause operations
* - Only offchain processor can mint tokens
* - Fee calculations protected against overflow
* - Uses OpenZeppelin's Ownable and Pausable for security
*/
contract Bridge is Ownable, Pausable {
// Core state variables
address public tokenAddress;
uint256 public transferFee; // percentage (e.g., 100 = 1%)
uint256 public operationFee; // flat fee in tokens
uint256 private constant FEE_DENOMINATOR = 10000;
address public offchainProcessor;
// Maximum fee constraints
uint256 private constant MAX_TRANSFER_FEE = 1000; // 10%
uint256 private constant MAX_OPERATION_FEE = 1000 * 10 ** 18; // 1000 tokens
// Events for tracking bridge operations
event BridgeStarted(
address indexed user,
uint256 amount,
uint256 amountAfterFee,
string destinationChain,
address destinationAddress
);
event AssetMinted(
address indexed recipient,
uint256 amount
);
event FeeUpdated(
uint256 newTransferFee,
uint256 newOperationFee
);
event OffchainProcessorChanged(
address indexed oldProcessor,
address indexed newProcessor
);
event FeesWithdrawn(
address indexed to,
uint256 amount
);
/**
* @dev Modifier to restrict functions to offchain processor
*/
modifier onlyOffchain() {
require(msg.sender == offchainProcessor, "Only Offchain Processor allowed to call this method");
require(offchainProcessor != address(0), "Offchain processor not initialized");
_;
}
/**
* @dev Constructor initializes the bridge with token and fee settings
* @param _token Address of the token contract
* @param _transferFee Percentage fee for transfers (basis points)
* @param _operationFee Flat fee for operations
* @param oracle Address of the oracle that will own the bridge
* @param _offchainProcessor Address of the offchain processor
*/
constructor(
address _token,
uint256 _transferFee,
uint256 _operationFee,
address oracle,
address _offchainProcessor
) {
require(_token != address(0), "Invalid token address");
require(oracle != address(0), "Invalid oracle address");
require(_offchainProcessor != address(0), "Invalid processor address");
require(_transferFee <= MAX_TRANSFER_FEE, "Transfer fee too high");
require(_operationFee <= MAX_OPERATION_FEE, "Operation fee too high");
tokenAddress = _token;
transferFee = _transferFee;
operationFee = _operationFee;
offchainProcessor = _offchainProcessor;
_transferOwnership(oracle);
}
/**
* @dev Initiates a bridge transfer to another chain
* @param amount Amount of tokens to bridge
* @param destinationChain Target chain identifier
* @param destinationAddress Recipient address on target chain
*
* Security:
* - Validates allowance and balances
* - Calculates fees with overflow protection
* - Burns tokens after successful transfer
* - Admin (owner) is exempt from fees
*/
function receiveAsset(
uint256 amount,
string memory destinationChain,
address destinationAddress
) external whenNotPaused {
require(amount != 0, "Amount must be greater than 0");
require(bytes(destinationChain).length != 0, "Invalid destination chain");
require(destinationAddress != address(0), "Invalid destination address");
TokenManager token = TokenManager(tokenAddress);
address thisAddress = address(this);
uint256 allowance = token.allowance(msg.sender, thisAddress);
require(allowance >= amount, "Insufficient allowance");
// Calculate fees - exempt for admin
uint256 totalFee = 0;
uint256 amountAfterFee = amount;
if (msg.sender != owner()) {
// Calculate fees with overflow protection
uint256 transferFeeAmount = (amount * transferFee) / FEE_DENOMINATOR;
totalFee = transferFeeAmount + operationFee;
require(totalFee < amount, "Fee exceeds amount");
amountAfterFee = amount - totalFee;
}
require(token.transferFrom(msg.sender, thisAddress, amount), "Transfer failed");
// Burn only the amount after fees, keep fees in contract
if (amountAfterFee > 0) {
token.burnFrom(thisAddress, amountAfterFee);
}
emit BridgeStarted(msg.sender, amount, amountAfterFee, destinationChain, destinationAddress);
}
/**
* @dev Mints tokens for cross-chain transfers
* @param to Recipient address
* @param amount Amount of tokens to mint
*
* Security:
* - Only callable by offchain processor
* - Protected by pausable mechanism
*/
function mintAsset(
address to,
uint256 amount
) external onlyOffchain whenNotPaused {
require(to != address(0), "Invalid recipient");
require(amount != 0, "Amount must be greater than 0");
TokenManager token = TokenManager(tokenAddress);
token.mint(to, amount);
emit AssetMinted(to, amount);
}
/**
* @dev Updates the transfer fee percentage
* @param newFee New fee in basis points
*
* Security: Only callable by owner (Oracle)
*/
function updateTransferFee(uint256 newFee) external onlyOwner {
require(newFee <= MAX_TRANSFER_FEE, "Fee too high");
transferFee = newFee;
emit FeeUpdated(newFee, operationFee);
}
/**
* @dev Updates the flat operation fee
* @param newFee New fee amount
*
* Security: Only callable by owner (Oracle)
*/
function updateOperationFee(uint256 newFee) external onlyOwner {
require(newFee <= MAX_OPERATION_FEE, "Fee too high");
operationFee = newFee;
emit FeeUpdated(transferFee, newFee);
}
/**
* @dev Pauses bridge operations
* Security: Only callable by owner (Oracle)
*/
function pause() external onlyOwner {
_pause();
}
/**
* @dev Unpauses bridge operations
* Security: Only callable by owner (Oracle)
*/
function unpause() external onlyOwner {
_unpause();
}
/**
* @dev Withdraws accumulated fees
* @param to Address to receive the fees
*
* Security:
* - Only callable by owner (Oracle)
* - Protected against reentrancy by transfer pattern
* - Emits event for tracking
*/
function withdrawFees(address to) external onlyOwner {
require(to != address(0), "Invalid recipient");
IERC20 token = IERC20(tokenAddress);
address thisAddress = address(this);
uint256 balance = token.balanceOf(thisAddress);
require(balance != 0, "No fees to withdraw");
require(token.transfer(to, balance), "Fee withdrawal failed");
emit FeesWithdrawn(to, balance);
}
/**
* @dev Updates the offchain processor address
* @param newOffchainProcessor New processor address
*
* Security: Only callable by owner (Oracle)
*/
function changeOffchain(address newOffchainProcessor) external onlyOwner {
require(newOffchainProcessor != address(0), "Invalid processor address");
address oldProcessor = offchainProcessor;
offchainProcessor = newOffchainProcessor;
emit OffchainProcessorChanged(oldProcessor, newOffchainProcessor);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.0;
import "./Ownable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
_transferOwnership(sender);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.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}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* 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.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => 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 override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override 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 override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override 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 `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` 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 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
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 `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `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.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(address from, address to, uint256 amount) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
// Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
// decrementing then incrementing.
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
unchecked {
// Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
// Overflow not possible: amount <= accountBalance <= totalSupply.
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` 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.
*/
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
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 v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0 <0.9.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/**
* @title IBEP20
* @dev Interface for BEP-20 token standard, extending ERC-20
*/
interface IBEP20 is IERC20 {
/**
* @dev Returns the owner of the token contract
*/
function getOwner() external view returns (address);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0 <0.9.0;
/**
* @title ITokenManager
* @dev Interface for the Project Merlin token manager contract
*/
interface ITokenManager {
/**
* @dev Emitted when bridge infrastructure is deployed
*/
event BridgeDeployed(address indexed bridge, address indexed oracle);
/**
* @dev Emitted when tokens are burned
*/
event TokensBurned(address indexed account, uint256 amount);
/**
* @dev Emitted when tokens are minted
*/
event TokensMinted(address indexed to, uint256 amount);
/**
* @dev Returns the bridge contract address
*/
function bridge() external view returns (address);
/**
* @dev Returns the oracle contract address
*/
function oracle() external view returns (address);
/**
* @dev Returns the maximum allowed transfer fee in basis points
*/
function MAX_TRANSFER_FEE() external pure returns (uint256);
/**
* @dev Returns the maximum allowed operation fee in tokens
*/
function MAX_OPERATION_FEE() external pure returns (uint256);
/**
* @dev Burns tokens from a specified account
* @param account The account to burn tokens from
* @param amount The amount of tokens to burn
*/
function burnFrom(address account, uint256 amount) external;
/**
* @dev Mints new tokens to a specified address
* @param to The address to mint tokens to
* @param amount The amount of tokens to mint
*/
function mint(address to, uint256 amount) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0 <0.9.0;
import {IBEP20} from "./interfaces/IBEP20.sol";
import {ITokenManager} from "./interfaces/ITokenManager.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
/**
* @title TokenManager
* @dev Implementation of the Project Merlin token with bridge functionality
*
* This contract manages the ERC20/BEP20 token used in the Project Merlin ecosystem.
* It includes bridging capabilities that can be added later through a dedicated Bridge contract.
*
* Security considerations:
* - Only the owner can mint and burn tokens initially
* - Bridge address can be set later to enable cross-chain functionality
* - Initial token distribution is handled in constructor
* - Uses OpenZeppelin's battle-tested ERC20 and Ownable implementations
*/
contract TokenManager is ERC20, Ownable2Step, ITokenManager, IBEP20 {
// Contract addresses for core functionality
address public override bridge;
address public override oracle;
// Maximum allowed fees (in basis points)
uint256 public constant override MAX_TRANSFER_FEE = 1000; // 10%
uint256 public constant override MAX_OPERATION_FEE = 1000 * 10 ** 18; // 1000 tokens
/**
* @dev Constructor initializes the token without bridge infrastructure
* @param name_ The name of the token
* @param symbol_ The symbol of the token
* @param totalSupply_ The total supply of tokens to be minted
*/
constructor(
string memory name_,
string memory symbol_,
uint256 totalSupply_
) ERC20(name_, symbol_) {
require(bytes(name_).length != 0, "Name cannot be empty");
require(bytes(symbol_).length != 0, "Symbol cannot be empty");
require(totalSupply_ != 0, "Total supply must be positive");
transferOwnership(msg.sender);
// Mint total supply to deployer (owner)
_mint(msg.sender, totalSupply_);
}
/**
* @dev Returns the owner of the token contract (BEP-20 compatibility)
*/
function getOwner() external view override returns (address) {
return owner();
}
/**
* @dev Sets the bridge and oracle addresses
* @param _bridge Address of the bridge contract
* @param _oracle Address of the oracle contract
*
* Security: Only callable by owner
*/
function setBridgeAndOracle(address _bridge, address _oracle) external onlyOwner {
require(_bridge != address(0), "Bridge address cannot be zero");
require(_oracle != address(0), "Oracle address cannot be zero");
require(bridge == address(0), "Bridge already set");
require(oracle == address(0), "Oracle already set");
bridge = _bridge;
oracle = _oracle;
emit BridgeDeployed(_bridge, _oracle);
}
/**
* @dev Modifier to restrict certain functions to only be called by the bridge contract
*
* Security: Critical for maintaining token supply control
*/
modifier onlyBridge() {
require(msg.sender == bridge, "Only bridge can call this");
require(bridge != address(0), "Bridge not initialized");
_;
}
/**
* @dev Burns tokens from a specified account, only callable by bridge or owner
* @param account The account to burn tokens from
* @param amount The amount of tokens to burn
*/
function burnFrom(address account, uint256 amount) public override {
require(msg.sender == bridge || msg.sender == owner(), "Only bridge or owner can call this");
require(account != address(0), "Cannot burn from zero address");
require(amount != 0, "Cannot burn zero tokens");
if (msg.sender == owner()) {
// Owner must have allowance
uint256 currentAllowance = allowance(account, owner());
require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance");
_approve(account, owner(), currentAllowance - amount);
}
_burn(account, amount);
emit TokensBurned(account, amount);
}
/**
* @dev Mints new tokens to a specified address, only callable by bridge or owner
* @param to The address to mint tokens to
* @param amount The amount of tokens to mint
*/
function mint(address to, uint256 amount) public override {
require(msg.sender == bridge || msg.sender == owner(), "Only bridge or owner can call this");
require(to != address(0), "Cannot mint to zero address");
require(amount != 0, "Cannot mint zero tokens");
_mint(to, amount);
emit TokensMinted(to, amount);
}
}{
"optimizer": {
"enabled": true,
"runs": 200,
"details": {
"yul": false
}
},
"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":"_token","type":"address"},{"internalType":"uint256","name":"_transferFee","type":"uint256"},{"internalType":"uint256","name":"_operationFee","type":"uint256"},{"internalType":"address","name":"oracle","type":"address"},{"internalType":"address","name":"_offchainProcessor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AssetMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountAfterFee","type":"uint256"},{"indexed":false,"internalType":"string","name":"destinationChain","type":"string"},{"indexed":false,"internalType":"address","name":"destinationAddress","type":"address"}],"name":"BridgeStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newTransferFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newOperationFee","type":"uint256"}],"name":"FeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldProcessor","type":"address"},{"indexed":true,"internalType":"address","name":"newProcessor","type":"address"}],"name":"OffchainProcessorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"address","name":"newOffchainProcessor","type":"address"}],"name":"changeOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mintAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"offchainProcessor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operationFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"destinationChain","type":"string"},{"internalType":"address","name":"destinationAddress","type":"address"}],"name":"receiveAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transferFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"updateOperationFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"updateTransferFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFees","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b506040516200181b3803806200181b83398101604081905262000034916200020f565b6200003f3362000171565b6000805460ff60a01b191690556001600160a01b0385166200007e5760405162461bcd60e51b81526004016200007590620002ca565b60405180910390fd5b6001600160a01b038216620000a75760405162461bcd60e51b8152600401620000759062000311565b6001600160a01b038116620000d05760405162461bcd60e51b8152600401620000759062000358565b6103e8841115620000f55760405162461bcd60e51b815260040162000075906200039f565b683635c9adc5dea00000831115620001215760405162461bcd60e51b81526004016200007590620003e6565b600180546001600160a01b038088166001600160a01b031992831617909255600286905560038590556004805492841692909116919091179055620001668262000171565b5050505050620003f8565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006001600160a01b0382165b92915050565b620001df81620001c1565b8114620001eb57600080fd5b50565b8051620001ce81620001d4565b80620001df565b8051620001ce81620001fb565b600080600080600060a086880312156200022c576200022c600080fd5b60006200023a8888620001ee565b95505060206200024d8882890162000202565b9450506040620002608882890162000202565b93505060606200027388828901620001ee565b92505060806200028688828901620001ee565b9150509295509295909350565b601581526000602082017f496e76616c696420746f6b656e20616464726573730000000000000000000000815291505b5060200190565b60208082528101620001ce8162000293565b601681526000602082017f496e76616c6964206f7261636c6520616464726573730000000000000000000081529150620002c3565b60208082528101620001ce81620002dc565b601981526000602082017f496e76616c69642070726f636573736f7220616464726573730000000000000081529150620002c3565b60208082528101620001ce8162000323565b601581526000602082017f5472616e736665722066656520746f6f2068696768000000000000000000000081529150620002c3565b60208082528101620001ce816200036a565b601681526000602082017f4f7065726174696f6e2066656520746f6f20686967680000000000000000000081529150620002c3565b60208082528101620001ce81620003b1565b61141380620004086000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c8063715018a6116100975780639d76ea58116100665780639d76ea58146101e5578063acb2ad6f146101f8578063de8132581461020e578063f2fde38b1461021757600080fd5b8063715018a6146101b15780638456cb59146101b95780638577a6d5146101c15780638da5cb5b146101d457600080fd5b80632096d703116100d35780632096d703146101535780633f4ba83a1461017c5780635c975abb146101845780635f758bef1461019e57600080fd5b806308d6a6ec146101055780630ee7f1431461011a5780630fbe80081461012d578063164e68de14610140575b600080fd5b610118610113366004610c60565b61022a565b005b610118610128366004610ccb565b61050e565b61011861013b366004610cec565b61058e565b61011861014e366004610ccb565b610602565b600454610166906001600160a01b031681565b6040516101739190610d1c565b60405180910390f35b61011861079e565b600054600160a01b900460ff166040516101739190610d32565b6101186101ac366004610d40565b6107b0565b6101186108fc565b61011861090e565b6101186101cf366004610cec565b61091e565b6000546001600160a01b0316610166565b600154610166906001600160a01b031681565b61020160025481565b6040516101739190610d83565b61020160035481565b610118610225366004610ccb565b610981565b6102326109bb565b8260000361025b5760405162461bcd60e51b815260040161025290610dc8565b60405180910390fd5b815160000361027c5760405162461bcd60e51b815260040161025290610e0c565b6001600160a01b0381166102a25760405162461bcd60e51b815260040161025290610e50565b600154604051636eb1769f60e11b81526001600160a01b03909116903090600090839063dd62ed3e906102db9033908690600401610e60565b602060405180830381865afa1580156102f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061031c9190610e8d565b90508581101561033e5760405162461bcd60e51b815260040161025290610edb565b6000866103536000546001600160a01b031690565b6001600160a01b0316336001600160a01b0316146103c75760006127106002548a61037e9190610f01565b6103889190610f36565b9050600354816103989190610f4a565b92508883106103b95760405162461bcd60e51b815260040161025290610f86565b6103c3838a610f96565b9150505b6040516323b872dd60e01b81526001600160a01b038616906323b872dd906103f790339088908d90600401610fa9565b6020604051808303816000875af1158015610416573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043a9190610fe4565b6104565760405162461bcd60e51b81526004016102529061102b565b80156104bd5760405163079cc67960e41b81526001600160a01b038616906379cc67909061048a908790859060040161103b565b600060405180830381600087803b1580156104a457600080fd5b505af11580156104b8573d6000803e3d6000fd5b505050505b336001600160a01b03167fbb36925fc4e03ef09041c070c617b55bfe4cb14603e071145e72064fdb50c02089838a8a6040516104fc94939291906110ac565b60405180910390a25050505050505050565b6105166109e5565b6001600160a01b03811661053c5760405162461bcd60e51b815260040161025290611125565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5748ceacf7748f4256c5ebe16041c4c2fcb347c318558678935a0341dc7876fa90600090a35050565b6105966109e5565b683635c9adc5dea000008111156105bf5760405162461bcd60e51b815260040161025290611158565b60038190556002546040517f528d9479e9f9889a87a3c30c7f7ba537e5e59c4c85a37733b16e57c62df61302916105f7918490611168565b60405180910390a150565b61060a6109e5565b6001600160a01b0381166106305760405162461bcd60e51b81526004016102529061119e565b6001546040516370a0823160e01b81526001600160a01b0390911690309060009083906370a0823190610667908590600401610d1c565b602060405180830381865afa158015610684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a89190610e8d565b9050806000036106ca5760405162461bcd60e51b8152600401610252906111d8565b60405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb906106f8908790859060040161103b565b6020604051808303816000875af1158015610717573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073b9190610fe4565b6107575760405162461bcd60e51b815260040161025290611214565b836001600160a01b03167fc0819c13be868895eb93e40eaceb96de976442fa1d404e5c55f14bb65a8c489a826040516107909190610d83565b60405180910390a250505050565b6107a66109e5565b6107ae610a0f565b565b6004546001600160a01b031633146107da5760405162461bcd60e51b815260040161025290611277565b6004546001600160a01b03166108025760405162461bcd60e51b8152600401610252906112c6565b61080a6109bb565b6001600160a01b0382166108305760405162461bcd60e51b81526004016102529061119e565b806000036108505760405162461bcd60e51b815260040161025290610dc8565b6001546040516340c10f1960e01b81526001600160a01b039091169081906340c10f1990610884908690869060040161103b565b600060405180830381600087803b15801561089e57600080fd5b505af11580156108b2573d6000803e3d6000fd5b50505050826001600160a01b03167f8d1457c1d60a6987eabbac898a50d8d7c81ba604c563663d2807027a4b079054836040516108ef9190610d83565b60405180910390a2505050565b6109046109e5565b6107ae6000610a5e565b6109166109e5565b6107ae610aae565b6109266109e5565b6103e88111156109485760405162461bcd60e51b815260040161025290611158565b60028190556003546040517f528d9479e9f9889a87a3c30c7f7ba537e5e59c4c85a37733b16e57c62df61302916105f791849190611168565b6109896109e5565b6001600160a01b0381166109af5760405162461bcd60e51b815260040161025290611319565b6109b881610a5e565b50565b600054600160a01b900460ff16156107ae5760405162461bcd60e51b815260040161025290611350565b6000546001600160a01b031633146107ae5760405162461bcd60e51b815260040161025290611392565b610a17610af1565b6000805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b604051610a549190610d1c565b60405180910390a1565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b610ab66109bb565b6000805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610a473390565b600054600160a01b900460ff166107ae5760405162461bcd60e51b8152600401610252906113cd565b805b81146109b857600080fd5b8035610b3281610b1a565b92915050565b634e487b7160e01b600052604160045260246000fd5b601f19601f830116810181811067ffffffffffffffff82111715610b7457610b74610b38565b6040525050565b6000610b8660405190565b9050610b928282610b4e565b919050565b600067ffffffffffffffff821115610bb157610bb1610b38565b601f19601f83011660200192915050565b82818337506000910152565b6000610be1610bdc84610b97565b610b7b565b905082815260208101848484011115610bfc57610bfc600080fd5b610c07848285610bc2565b509392505050565b600082601f830112610c2357610c23600080fd5b8135610c33848260208601610bce565b949350505050565b60006001600160a01b038216610b32565b610b1c81610c3b565b8035610b3281610c4c565b600080600060608486031215610c7857610c78600080fd5b6000610c848686610b27565b935050602084013567ffffffffffffffff811115610ca457610ca4600080fd5b610cb086828701610c0f565b9250506040610cc186828701610c55565b9150509250925092565b600060208284031215610ce057610ce0600080fd5b6000610c338484610c55565b600060208284031215610d0157610d01600080fd5b6000610c338484610b27565b610d1681610c3b565b82525050565b60208101610b328284610d0d565b801515610d16565b60208101610b328284610d2a565b60008060408385031215610d5657610d56600080fd5b6000610d628585610c55565b9250506020610d7385828601610b27565b9150509250929050565b80610d16565b60208101610b328284610d7d565b601d81526000602082017f416d6f756e74206d7573742062652067726561746572207468616e2030000000815291505b5060200190565b60208082528101610b3281610d91565b601981526000602082017f496e76616c69642064657374696e6174696f6e20636861696e0000000000000081529150610dc1565b60208082528101610b3281610dd8565b601b81526000602082017f496e76616c69642064657374696e6174696f6e2061646472657373000000000081529150610dc1565b60208082528101610b3281610e1c565b60408101610e6e8285610d0d565b610e7b6020830184610d0d565b9392505050565b8051610b3281610b1a565b600060208284031215610ea257610ea2600080fd5b6000610c338484610e82565b6016815260006020820175496e73756666696369656e7420616c6c6f77616e636560501b81529150610dc1565b60208082528101610b3281610eae565b634e487b7160e01b600052601160045260246000fd5b818102808215838204851417610f1957610f19610eeb565b5092915050565b634e487b7160e01b600052601260045260246000fd5b600082610f4557610f45610f20565b500490565b80820180821115610b3257610b32610eeb565b601281526000602082017111995948195e18d959591cc8185b5bdd5b9d60721b81529150610dc1565b60208082528101610b3281610f5d565b81810381811115610b3257610b32610eeb565b60608101610fb78286610d0d565b610fc46020830185610d0d565b610c336040830184610d7d565b801515610b1c565b8051610b3281610fd1565b600060208284031215610ff957610ff9600080fd5b6000610c338484610fd9565b600f81526000602082016e151c985b9cd9995c8819985a5b1959608a1b81529150610dc1565b60208082528101610b3281611005565b604081016110498285610d0d565b610e7b6020830184610d7d565b60005b83811015611071578181015183820152602001611059565b50506000910152565b6000611084825190565b80845260208401935061109b818560208601611056565b601f01601f19169290920192915050565b608081016110ba8287610d7d565b6110c76020830186610d7d565b81810360408301526110d9818561107a565b90506110e86060830184610d0d565b95945050505050565b601981526000602082017f496e76616c69642070726f636573736f7220616464726573730000000000000081529150610dc1565b60208082528101610b32816110f1565b600c81526000602082016b08ccaca40e8dede40d0d2ced60a31b81529150610dc1565b60208082528101610b3281611135565b604081016110498285610d7d565b6011815260006020820170125b9d985b1a59081c9958da5c1a595b9d607a1b81529150610dc1565b60208082528101610b3281611176565b60138152600060208201724e6f206665657320746f20776974686472617760681b81529150610dc1565b60208082528101610b32816111ae565b6015815260006020820174119959481dda5d1a191c985dd85b0819985a5b1959605a1b81529150610dc1565b60208082528101610b32816111e8565b603381526000602082017f4f6e6c79204f6666636861696e2050726f636573736f7220616c6c6f776564208152721d1bc818d85b1b081d1a1a5cc81b595d1a1bd9606a1b602082015291505b5060400190565b60208082528101610b3281611224565b602281526000602082017f4f6666636861696e2070726f636573736f72206e6f7420696e697469616c697a815261195960f21b60208201529150611270565b60208082528101610b3281611287565b602681526000602082017f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206181526564647265737360d01b60208201529150611270565b60208082528101610b32816112d6565b601081526000602082016f14185d5cd8589b194e881c185d5cd95960821b81529150610dc1565b60208082528101610b3281611329565b60208082527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657291019081526000610dc1565b60208082528101610b3281611360565b601481526000602082017314185d5cd8589b194e881b9bdd081c185d5cd95960621b81529150610dc1565b60208082528101610b32816113a256fea2646970667358221220a9009a782ab0dc84fdeea3c99615de1cf3e44b2be2a88e8e7a3e006f6d64533264736f6c6343000817003300000000000000000000000079be2b20389a869476d183b1f42b9950eaf457d800000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000002660d1a622b7b683e3418dbfccbbcde30d05f48d000000000000000000000000cf632eab35b4885c0f87d14cce44f574eacabffb
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101005760003560e01c8063715018a6116100975780639d76ea58116100665780639d76ea58146101e5578063acb2ad6f146101f8578063de8132581461020e578063f2fde38b1461021757600080fd5b8063715018a6146101b15780638456cb59146101b95780638577a6d5146101c15780638da5cb5b146101d457600080fd5b80632096d703116100d35780632096d703146101535780633f4ba83a1461017c5780635c975abb146101845780635f758bef1461019e57600080fd5b806308d6a6ec146101055780630ee7f1431461011a5780630fbe80081461012d578063164e68de14610140575b600080fd5b610118610113366004610c60565b61022a565b005b610118610128366004610ccb565b61050e565b61011861013b366004610cec565b61058e565b61011861014e366004610ccb565b610602565b600454610166906001600160a01b031681565b6040516101739190610d1c565b60405180910390f35b61011861079e565b600054600160a01b900460ff166040516101739190610d32565b6101186101ac366004610d40565b6107b0565b6101186108fc565b61011861090e565b6101186101cf366004610cec565b61091e565b6000546001600160a01b0316610166565b600154610166906001600160a01b031681565b61020160025481565b6040516101739190610d83565b61020160035481565b610118610225366004610ccb565b610981565b6102326109bb565b8260000361025b5760405162461bcd60e51b815260040161025290610dc8565b60405180910390fd5b815160000361027c5760405162461bcd60e51b815260040161025290610e0c565b6001600160a01b0381166102a25760405162461bcd60e51b815260040161025290610e50565b600154604051636eb1769f60e11b81526001600160a01b03909116903090600090839063dd62ed3e906102db9033908690600401610e60565b602060405180830381865afa1580156102f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061031c9190610e8d565b90508581101561033e5760405162461bcd60e51b815260040161025290610edb565b6000866103536000546001600160a01b031690565b6001600160a01b0316336001600160a01b0316146103c75760006127106002548a61037e9190610f01565b6103889190610f36565b9050600354816103989190610f4a565b92508883106103b95760405162461bcd60e51b815260040161025290610f86565b6103c3838a610f96565b9150505b6040516323b872dd60e01b81526001600160a01b038616906323b872dd906103f790339088908d90600401610fa9565b6020604051808303816000875af1158015610416573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043a9190610fe4565b6104565760405162461bcd60e51b81526004016102529061102b565b80156104bd5760405163079cc67960e41b81526001600160a01b038616906379cc67909061048a908790859060040161103b565b600060405180830381600087803b1580156104a457600080fd5b505af11580156104b8573d6000803e3d6000fd5b505050505b336001600160a01b03167fbb36925fc4e03ef09041c070c617b55bfe4cb14603e071145e72064fdb50c02089838a8a6040516104fc94939291906110ac565b60405180910390a25050505050505050565b6105166109e5565b6001600160a01b03811661053c5760405162461bcd60e51b815260040161025290611125565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5748ceacf7748f4256c5ebe16041c4c2fcb347c318558678935a0341dc7876fa90600090a35050565b6105966109e5565b683635c9adc5dea000008111156105bf5760405162461bcd60e51b815260040161025290611158565b60038190556002546040517f528d9479e9f9889a87a3c30c7f7ba537e5e59c4c85a37733b16e57c62df61302916105f7918490611168565b60405180910390a150565b61060a6109e5565b6001600160a01b0381166106305760405162461bcd60e51b81526004016102529061119e565b6001546040516370a0823160e01b81526001600160a01b0390911690309060009083906370a0823190610667908590600401610d1c565b602060405180830381865afa158015610684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a89190610e8d565b9050806000036106ca5760405162461bcd60e51b8152600401610252906111d8565b60405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb906106f8908790859060040161103b565b6020604051808303816000875af1158015610717573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073b9190610fe4565b6107575760405162461bcd60e51b815260040161025290611214565b836001600160a01b03167fc0819c13be868895eb93e40eaceb96de976442fa1d404e5c55f14bb65a8c489a826040516107909190610d83565b60405180910390a250505050565b6107a66109e5565b6107ae610a0f565b565b6004546001600160a01b031633146107da5760405162461bcd60e51b815260040161025290611277565b6004546001600160a01b03166108025760405162461bcd60e51b8152600401610252906112c6565b61080a6109bb565b6001600160a01b0382166108305760405162461bcd60e51b81526004016102529061119e565b806000036108505760405162461bcd60e51b815260040161025290610dc8565b6001546040516340c10f1960e01b81526001600160a01b039091169081906340c10f1990610884908690869060040161103b565b600060405180830381600087803b15801561089e57600080fd5b505af11580156108b2573d6000803e3d6000fd5b50505050826001600160a01b03167f8d1457c1d60a6987eabbac898a50d8d7c81ba604c563663d2807027a4b079054836040516108ef9190610d83565b60405180910390a2505050565b6109046109e5565b6107ae6000610a5e565b6109166109e5565b6107ae610aae565b6109266109e5565b6103e88111156109485760405162461bcd60e51b815260040161025290611158565b60028190556003546040517f528d9479e9f9889a87a3c30c7f7ba537e5e59c4c85a37733b16e57c62df61302916105f791849190611168565b6109896109e5565b6001600160a01b0381166109af5760405162461bcd60e51b815260040161025290611319565b6109b881610a5e565b50565b600054600160a01b900460ff16156107ae5760405162461bcd60e51b815260040161025290611350565b6000546001600160a01b031633146107ae5760405162461bcd60e51b815260040161025290611392565b610a17610af1565b6000805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b604051610a549190610d1c565b60405180910390a1565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b610ab66109bb565b6000805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610a473390565b600054600160a01b900460ff166107ae5760405162461bcd60e51b8152600401610252906113cd565b805b81146109b857600080fd5b8035610b3281610b1a565b92915050565b634e487b7160e01b600052604160045260246000fd5b601f19601f830116810181811067ffffffffffffffff82111715610b7457610b74610b38565b6040525050565b6000610b8660405190565b9050610b928282610b4e565b919050565b600067ffffffffffffffff821115610bb157610bb1610b38565b601f19601f83011660200192915050565b82818337506000910152565b6000610be1610bdc84610b97565b610b7b565b905082815260208101848484011115610bfc57610bfc600080fd5b610c07848285610bc2565b509392505050565b600082601f830112610c2357610c23600080fd5b8135610c33848260208601610bce565b949350505050565b60006001600160a01b038216610b32565b610b1c81610c3b565b8035610b3281610c4c565b600080600060608486031215610c7857610c78600080fd5b6000610c848686610b27565b935050602084013567ffffffffffffffff811115610ca457610ca4600080fd5b610cb086828701610c0f565b9250506040610cc186828701610c55565b9150509250925092565b600060208284031215610ce057610ce0600080fd5b6000610c338484610c55565b600060208284031215610d0157610d01600080fd5b6000610c338484610b27565b610d1681610c3b565b82525050565b60208101610b328284610d0d565b801515610d16565b60208101610b328284610d2a565b60008060408385031215610d5657610d56600080fd5b6000610d628585610c55565b9250506020610d7385828601610b27565b9150509250929050565b80610d16565b60208101610b328284610d7d565b601d81526000602082017f416d6f756e74206d7573742062652067726561746572207468616e2030000000815291505b5060200190565b60208082528101610b3281610d91565b601981526000602082017f496e76616c69642064657374696e6174696f6e20636861696e0000000000000081529150610dc1565b60208082528101610b3281610dd8565b601b81526000602082017f496e76616c69642064657374696e6174696f6e2061646472657373000000000081529150610dc1565b60208082528101610b3281610e1c565b60408101610e6e8285610d0d565b610e7b6020830184610d0d565b9392505050565b8051610b3281610b1a565b600060208284031215610ea257610ea2600080fd5b6000610c338484610e82565b6016815260006020820175496e73756666696369656e7420616c6c6f77616e636560501b81529150610dc1565b60208082528101610b3281610eae565b634e487b7160e01b600052601160045260246000fd5b818102808215838204851417610f1957610f19610eeb565b5092915050565b634e487b7160e01b600052601260045260246000fd5b600082610f4557610f45610f20565b500490565b80820180821115610b3257610b32610eeb565b601281526000602082017111995948195e18d959591cc8185b5bdd5b9d60721b81529150610dc1565b60208082528101610b3281610f5d565b81810381811115610b3257610b32610eeb565b60608101610fb78286610d0d565b610fc46020830185610d0d565b610c336040830184610d7d565b801515610b1c565b8051610b3281610fd1565b600060208284031215610ff957610ff9600080fd5b6000610c338484610fd9565b600f81526000602082016e151c985b9cd9995c8819985a5b1959608a1b81529150610dc1565b60208082528101610b3281611005565b604081016110498285610d0d565b610e7b6020830184610d7d565b60005b83811015611071578181015183820152602001611059565b50506000910152565b6000611084825190565b80845260208401935061109b818560208601611056565b601f01601f19169290920192915050565b608081016110ba8287610d7d565b6110c76020830186610d7d565b81810360408301526110d9818561107a565b90506110e86060830184610d0d565b95945050505050565b601981526000602082017f496e76616c69642070726f636573736f7220616464726573730000000000000081529150610dc1565b60208082528101610b32816110f1565b600c81526000602082016b08ccaca40e8dede40d0d2ced60a31b81529150610dc1565b60208082528101610b3281611135565b604081016110498285610d7d565b6011815260006020820170125b9d985b1a59081c9958da5c1a595b9d607a1b81529150610dc1565b60208082528101610b3281611176565b60138152600060208201724e6f206665657320746f20776974686472617760681b81529150610dc1565b60208082528101610b32816111ae565b6015815260006020820174119959481dda5d1a191c985dd85b0819985a5b1959605a1b81529150610dc1565b60208082528101610b32816111e8565b603381526000602082017f4f6e6c79204f6666636861696e2050726f636573736f7220616c6c6f776564208152721d1bc818d85b1b081d1a1a5cc81b595d1a1bd9606a1b602082015291505b5060400190565b60208082528101610b3281611224565b602281526000602082017f4f6666636861696e2070726f636573736f72206e6f7420696e697469616c697a815261195960f21b60208201529150611270565b60208082528101610b3281611287565b602681526000602082017f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206181526564647265737360d01b60208201529150611270565b60208082528101610b32816112d6565b601081526000602082016f14185d5cd8589b194e881c185d5cd95960821b81529150610dc1565b60208082528101610b3281611329565b60208082527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657291019081526000610dc1565b60208082528101610b3281611360565b601481526000602082017314185d5cd8589b194e881b9bdd081c185d5cd95960621b81529150610dc1565b60208082528101610b32816113a256fea2646970667358221220a9009a782ab0dc84fdeea3c99615de1cf3e44b2be2a88e8e7a3e006f6d64533264736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000079be2b20389a869476d183b1f42b9950eaf457d800000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000002660d1a622b7b683e3418dbfccbbcde30d05f48d000000000000000000000000cf632eab35b4885c0f87d14cce44f574eacabffb
-----Decoded View---------------
Arg [0] : _token (address): 0x79bE2B20389A869476d183b1f42B9950EAf457d8
Arg [1] : _transferFee (uint256): 5
Arg [2] : _operationFee (uint256): 1000000000000000000
Arg [3] : oracle (address): 0x2660d1a622B7b683E3418dbfCcbBcDe30d05f48d
Arg [4] : _offchainProcessor (address): 0xcF632eAb35B4885C0f87D14cce44F574eACABFFb
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 00000000000000000000000079be2b20389a869476d183b1f42b9950eaf457d8
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [2] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [3] : 0000000000000000000000002660d1a622b7b683e3418dbfccbbcde30d05f48d
Arg [4] : 000000000000000000000000cf632eab35b4885c0f87d14cce44f574eacabffb
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in BNB
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.
${zeroWidthWarningMessage} Check the actual text at SPACE ID.
`;
}
const ensOnL2NoteHtml = ensOnL2Note != "" ? `Additional Info
Full Name:
${ensNameForkIconSrc}
Note:
- Name tag is displayed due to forward and reverse resolution. Find out more.
- A Domain Name is not necessarily held by a person popularly associated with the name. ${ensOnL2NoteHtml}
Other names resolving to this address:
${listOtherENSNames}
${moreOtherENSNames}
`;
return result;
}
function removeSpecificDomain(url, domain) {
return url.replace(new RegExp(domain + '$'), '');
}
// ===== UD name tag
const displayUDName = '';
const primaryUDName = '';
const showUDPublicNote = 'false';
let otherUDNamesHtml = "";
function initUDNamePopOver() {
//required to allow bootstrap popover to support table
$.fn.popover.Constructor.Default.allowList.table = [];
$.fn.popover.Constructor.Default.allowList.tr = [];
$.fn.popover.Constructor.Default.allowList.td = [];
$.fn.popover.Constructor.Default.allowList.th = [];
$.fn.popover.Constructor.Default.allowList.div = [];
$.fn.popover.Constructor.Default.allowList.tbody = [];
$.fn.popover.Constructor.Default.allowList.thead = [];
//allowList my inline styling for bootstrap
$.fn.popover.Constructor.Default.allowList['*'].push('style')
let unicodeWarningHtml = "";
if ($("#hdnIsUDContainUnicodeChars").val() == "true") {
unicodeWarningHtml =
`
${unicodeWarningMessage} Check the actual text at Unstoppable Domains.
`;
}
let zeroWidthWarningHtml = "";
if ($("#hdnIsUDContainZeroWidthChars").val() == "true") {
zeroWidthWarningHtml =
`
${unicodeWarningMessage} Check the actual text at Unstoppable Domains.
`;
}
const contentHtml =
`Additional Info
Full Name:
Note:
- Name tag is displayed due to forward and reverse resolution. Find out more
- A Domain Name is not necessarily held by a person popularly associated with the name.
Other names resolving to this address:
${listOtherUDNames}
${moreOtherUDNames}
`;
return result;
}
// ===== end UD name tag
const tooltipForTokenHolding = '1 Token Contract';
var adjustPosition = 0;
$(document).ready(function () {
switchAmountToValue(document.getElementById("headerAmountValue"), 'Value (USD)', 'Amount', true);
switchAmountToValue(document.getElementById("headerIntAmountValue"), 'Value (USD)', 'Amount', true);
switchMethodColumn(document.getElementById("headerMethod"), 'Method', 'Action', true);
onDocumentReady();
$("[rel='tooltip']").tooltip();
$("[data-bs-toggle-second='tooltip']").tooltip({ trigger: 'hover' });
$("[rel='tooltipEns']").each(function () {
$(this).tooltip({ title: $(this).attr("tooltip-title") });
});
if (hash != '') {
activaTab(hash);
};
onAddressDocReady();
// Note: this is causing "Copied" tooltip not showing when copy button is clicked in V3, and seems like not applicable to v3, comment out first in case there is issue
//$('[data-bs-toggle="tooltip"]').click(function () {
// $('[data-bs-toggle="tooltip"]').tooltip("hide");
//});
document.getElementById("copyaddressbutton").classList.remove("disabled");
if ($("#txtSearchContract").length) {
initialiseKeyupOnDocReady();
}
if (!!$('#ensName')[0]) {
initEnsNamePopOver();
}
if (!!$("#udName")[0]) {
initUDNamePopOver();
}
handleToggle();
if (window.matchMedia("(max-width: 767px)").matches) {
// Mobile
adjustPosition = 90;
} else {
// Others
adjustPosition = 50;
}
if (tooltipForTokenHolding) {
const dropdownMenuBalance = document.getElementById("dropdownMenuBalance");
if (dropdownMenuBalance) {
const dropdownWrapper = dropdownMenuBalance.closest(".dropdown");
if (dropdownWrapper) {
dropdownWrapper.setAttribute("title", tooltipForTokenHolding);
new bootstrap.Tooltip(dropdownWrapper);
}
}
}
});
function displayAudit() {
$('html, body').animate({
scrollTop: $("#auditReportId").offset().top - adjustPosition
});
}
var cThemeMode = getCookie('displaymode');
function handleToggle() {
var className = document.getElementsByClassName('editor');
var classNameCount = className.length;
for (var j = 0; j t.innerWidth()) {
if (mb + d > tb) {
t.css('padding-bottom', ((mb + d) - tb));
}
}
else {
t.css('overflow', 'visible');
}
}).on('hidden.bs.dropdown', function () {
$(this).css({ 'padding-bottom': '', 'overflow': '' });
});
var btn_ERC20_sort = {
count: 0,
reminder_count: 2,
list: [],
default_list: [],
ERC20_sort_start: function (count) {
if (document.getElementsByClassName('list-custom-divider-ERC20')[0]) {
var self = this
if (count != undefined) {
self.count = count
}
var before_el = document.getElementsByClassName('list-custom-divider-ERC20')[0]
var parent_el = before_el.parentNode
var element_selector = parent_el.querySelectorAll(".list-custom-ERC20");
if (self.list.length == 0) {
element_selector.forEach(function (e) {
self.list.push(e);
self.default_list.push(e);
});
}
$(".list-custom-ERC20").remove()
var type = self.count % self.reminder_count
self.sortList(type, parent_el, before_el);
self.count++
}
},
sortList: function (type, parent_el, before_el) {
var self = this
var sorted_list = []
var icon_el = $(before_el).find('button').find('i')
switch (type) {
case 1:
icon_el.attr("class", "fad fa-sort-up")
sorted_list = self.sortUsdAsc()
break;
default:
icon_el.attr("class", "fad fa-sort-down")
sorted_list = self.sortUsdDesc()
}
for (var i = sorted_list.length - 1; i >= 0; i--) {
before_el.insertAdjacentElement('afterend', sorted_list[i])
}
},
sortUsdAsc: function () {
var self = this
var sort_list = self.list
sort_list.sort(function (a, b) {
var target_a_value = self.formatCurrencyToNumber(a.querySelector('.list-usd-value').textContent.trim() || -1);
var target_b_value = self.formatCurrencyToNumber(b.querySelector('.list-usd-value').textContent.trim() || -1);
if (target_a_value == -1 || target_b_value == -1) {
return 1;
}
if (target_a_value target_b_value) {
return 1;
}
return 0
});
return sort_list
},
sortUsdDesc: function () {
var self = this
var sort_list = self.list
sort_list.sort(function (a, b) {
var target_a_value = self.formatCurrencyToNumber(a.querySelector('.list-usd-value').textContent.trim() || -1);
var target_b_value = self.formatCurrencyToNumber(b.querySelector('.list-usd-value').textContent.trim() || -1);
if (target_a_value target_b_value) {
return -1;
}
return 0
});
return sort_list
},
formatCurrencyToNumber: function (strCurrency) {
if (typeof strCurrency == "number")
return strCurrency
else
return Number(strCurrency.replace(/[^0-9.-]+/g, ""));
},
}
function hrefTokenHolding() {
var location = "/tokenholdings?a=0x26dc8934ec55ff382c0af540d16feb0f9d226e2c"
var queryString = $("input.form-control.form-control-xs.search.mb-3")[0].value
if (queryString) {
location += "&q=" + queryString
}
window.location.href = location
}
$(document).ready(function () {
$("#btn_ERC20_sort").on("click", function (event) {
event.preventDefault();
setTimeout(function () {
btn_ERC20_sort.ERC20_sort_start()
}, 10)
})
btn_ERC20_sort.ERC20_sort_start()
var mainAddress = $("#hdnAddress").val();
// user search for method filters
var searchFuncTimeOut;
$("#ContentPlaceHolder1_inputMethodName").on("keyup", function ($event) {
if (searchFuncTimeOut) {
clearTimeout(searchFuncTimeOut)
}
var searchTerm = $(this).val();
searchFuncTimeOut = setTimeout(function () {
searchFunctions(searchTerm);
}, 350);
});
var isSearchFunctions = false;
$("#dropdownMethod").on("click", function (e) {
if (isSearchFunctions === false) {
searchFunctions('');
isSearchFunctions = true;
}
});
const litDefaultMethodFilterHtml = '';
function searchFunctions(searchTerm) {
if (searchTerm === '' || searchTerm.length > 3) {
const curPath = encodeURIComponent(window.location.search);
$.ajax({
type: 'Get',
url: `/functionSearchHandler.ashx?ca=${mainAddress}&func=${searchTerm ?? ''}&curPath=${curPath}`,
success: function (response) {
$("#searchFunctionResult").html('');
if (response && response.length > 0) {
for (var i = 0; i
${response[i].name}
${response[i].methodId}
`
);
}
$("[data-bs-toggle='tooltip']").tooltip();
}
else {
$("#searchFunctionResult").append(
`