Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
MAPOmnichainServiceV2
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 200 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@mapprotocol/protocol/contracts/interface/ILightVerifier.sol";
import "@mapprotocol/protocol/contracts/utils/Utils.sol";
import "./interface/IWrappedToken.sol";
import "./interface/IMintableToken.sol";
import "./interface/IButterReceiver.sol";
import "./interface/IButterMosV2.sol";
import "./utils/EvmDecoder.sol";
contract MAPOmnichainServiceV2 is ReentrancyGuard, Initializable, Pausable, IButterMosV2, UUPSUpgradeable {
using Address for address;
uint256 public immutable selfChainId = block.chainid;
uint256 public nonce;
address public wToken; // native wrapped token
address public relayContract;
uint256 public relayChainId;
ILightVerifier public lightNode;
mapping(bytes32 => bool) public orderList;
mapping(address => bool) public mintableTokens;
mapping(uint256 => mapping(address => bool)) public tokenMappingList;
address public butterRouter;
// reserved
IEvent.swapOutEvent[] private verifiedLogs;
mapping(bytes32 => bool) public storedOrderId; // log hash
event SetButterRouter(address butterRouter);
event SetLightClient(address lightNode);
event SetWrappedToken(address wToken);
event UpdateMintableToken(address token, bool mintable);
event SetRelayContract(uint256 chainId, address relay);
event RegisterToken(address token, uint256 toChain, bool enable);
// event mapSwapExecute(uint256 indexed fromChain, uint256 indexed toChain, address indexed from);
event mapSwapInVerified(bytes logs);
function initialize(
address _wToken,
address _lightNode,
address _owner
) public initializer checkAddress(_wToken) checkAddress(_lightNode) checkAddress(_owner) {
wToken = _wToken;
emit SetWrappedToken(_wToken);
lightNode = ILightVerifier(_lightNode);
emit SetLightClient(_lightNode);
_changeAdmin(_owner);
}
receive() external payable {}
modifier checkOrder(bytes32 _orderId) {
require(!orderList[_orderId], "order exist");
orderList[_orderId] = true;
_;
}
modifier checkBridgeable(address _token, uint256 _chainId) {
require(tokenMappingList[_chainId][_token], "token not registered");
_;
}
modifier checkAddress(address _address) {
require(_address != address(0), "address is zero");
_;
}
modifier onlyOwner() {
require(msg.sender == _getAdmin(), "mos :: only admin");
_;
}
function setPause() external onlyOwner {
_pause();
}
function setUnpause() external onlyOwner {
_unpause();
}
function setLightClient(address _lightNode) external onlyOwner checkAddress(_lightNode) {
lightNode = ILightVerifier(_lightNode);
emit SetLightClient(_lightNode);
}
/*
function setWrappedToken(address _wToken) external onlyOwner {
wToken = _wToken;
emit SetWrappedToken(_wToken);
}
*/
function setButterRouter(address _butterRouter) external onlyOwner {
butterRouter = _butterRouter;
emit SetButterRouter(_butterRouter);
}
function updateMintableToken(address[] memory _tokens, bool _mintable) external onlyOwner {
for (uint256 i = 0; i < _tokens.length; i++) {
mintableTokens[_tokens[i]] = _mintable;
emit UpdateMintableToken(_tokens[i], _mintable);
}
}
function setRelayContract(uint256 _chainId, address _relay) external onlyOwner checkAddress(_relay) {
relayContract = _relay;
relayChainId = _chainId;
emit SetRelayContract(_chainId, _relay);
}
function registerTokenChains(address _token, uint256[] memory _toChains, bool _enable) external onlyOwner {
require(_token.isContract(), "token is not contract");
for (uint256 i = 0; i < _toChains.length; i++) {
uint256 toChain = _toChains[i];
tokenMappingList[toChain][_token] = _enable;
emit RegisterToken(_token, toChain, _enable);
}
}
/*
function withdraw(address _token, address payable _receiver,uint256 _amount) external onlyOwner {
_transfer(_token, _receiver, _amount);
}
*/
// ------------------------------------------
function swapOutToken(
address _initiator, // swap initiator address
address _token, // src token
bytes memory _to,
uint256 _amount,
uint256 _toChain, // target chain id
bytes calldata _swapData
) external payable virtual override nonReentrant whenNotPaused returns (bytes32 orderId) {
require(_amount > 0, "Sending value is zero");
address token = _token;
if (token == address(0)) {
token = wToken;
require(msg.value >= _amount, "Invalid msg value");
IWrappedToken(token).deposit{value: _amount}();
} else {
SafeERC20.safeTransferFrom(IERC20(token), msg.sender, address(this), _amount);
if (_isMintable(token)) {
IMintableToken(token).burn(_amount);
}
}
orderId = _swapOut(token, _to, _initiator, _amount, _toChain, _swapData);
}
/*
function depositToken(address _token, address _to, uint256 _amount) external payable override whenNotPaused {
require(_amount > 0, "Sending value is zero");
address from = msg.sender;
address token = _token;
if (token == address(0)) {
token = wToken;
require(msg.value >= _amount, "Invalid msg value");
IWrappedToken(token).deposit{value: _amount}();
} else {
SafeERC20.safeTransferFrom(IERC20(token), from, address(this), _amount);
if (_isMintable(token)) {
IMintableToken(token).burn(_amount);
}
}
_deposit(token, from, _to, _amount, selfChainId, relayChainId);
}*/
function messageIn(
uint256 _chainId,
uint256 _logIndex,
bytes32 _orderId,
bytes calldata _receiptProof
) external nonReentrant whenNotPaused {
_messageIn(_chainId, _logIndex, _orderId, _receiptProof);
}
function swapIn(
uint256 _chainId,
uint256 _logIndex,
bytes32 _orderId,
bytes calldata _receiptProof
) external nonReentrant whenNotPaused {
_messageIn(_chainId, _logIndex, _orderId, _receiptProof);
}
function _messageIn(
uint256 _chainId,
uint256 _logIndex,
bytes32 _orderId,
bytes calldata _receiptProof
) internal {
require(!orderList[_orderId], "order exist");
require(_chainId == relayChainId, "invalid chain id");
(bool success, string memory message, ILightVerifier.txLog memory log) = lightNode.verifyProofDataWithCache(
false,
_logIndex,
_receiptProof
);
require(success, message);
_swapInVerifiedWithIndex(log, _logIndex);
}
function isMintable(address _token) public view returns (bool) {
return _isMintable(_token);
}
function isBridgeable(address _token, uint256 _toChain) public view returns (bool) {
return tokenMappingList[_toChain][_token];
}
function getOrderStatus(
uint256,
uint256 _blockNum,
bytes32 _orderId
) external view override returns (bool exists, bool verifiable, uint256 nodeType) {
exists = orderList[_orderId];
verifiable = lightNode.isVerifiable(_blockNum, bytes32(""));
nodeType = lightNode.nodeType();
}
function _getOrderID(address _from, bytes memory _to, uint256 _fromChain, uint256 _toChain) internal returns (bytes32) {
return keccak256(abi.encodePacked(address(this), nonce++, _fromChain, _toChain, _from, _to));
}
function _swapInVerifiedWithIndex(ILightVerifier.txLog memory log, uint256 logIndex) private {
require(relayContract == log.addr, "Invalid relay contract");
require(log.topics[0] == EvmDecoder.MAP_SWAPOUT_TOPIC, "Invalid relay topic");
IEvent.swapOutEvent memory outEvent = EvmDecoder.decodeSwapOutLog(log);
require(selfChainId == outEvent.toChain, "Invalid to chain id");
_swapIn(outEvent);
}
function _swapIn(IEvent.swapOutEvent memory _outEvent) internal checkOrder(_outEvent.orderId) {
address tokenIn = Utils.fromBytes(_outEvent.token);
// receiving address
address payable toAddress = payable(Utils.fromBytes(_outEvent.to));
// amount of token need to be sent
uint256 actualAmountIn = _outEvent.amount;
if (_isMintable(tokenIn)) {
IMintableToken(tokenIn).mint(address(this), actualAmountIn);
}
// if swap params is not empty, then we need to do swap on current chain
if (_outEvent.swapData.length > 0 && address(toAddress).isContract()) {
_transfer(_outEvent.toChain, tokenIn, toAddress, actualAmountIn);
try
IButterReceiver(toAddress).onReceived(
_outEvent.orderId,
tokenIn,
actualAmountIn,
_outEvent.fromChain,
_outEvent.from,
_outEvent.swapData
)
{
// do nothing
} catch {
// do nothing
}
} else {
// transfer token if swap did not happen
if (tokenIn == wToken) {
IWrappedToken(tokenIn).withdraw(actualAmountIn);
Address.sendValue(payable(toAddress), actualAmountIn);
} else {
_transfer(_outEvent.toChain, tokenIn, toAddress, actualAmountIn);
}
}
emit mapSwapIn(
_outEvent.fromChain,
_outEvent.toChain,
_outEvent.orderId,
tokenIn,
_outEvent.from,
toAddress,
actualAmountIn
);
}
function _transfer(uint256 _chainId, address _token, address _to, uint256 _amount) internal {
if (_token == address(0)) {
Address.sendValue(payable(_to), _amount);
} else {
if (_chainId == 728126428 && _token == 0xa614f803B6FD780986A42c78Ec9c7f77e6DeD13C) {
// Tron USDT
_token.call(abi.encodeWithSelector(0xa9059cbb, _to, _amount));
} else {
SafeERC20.safeTransfer(IERC20(_token), _to, _amount);
}
}
}
function _swapOut(
address _token, // src token
bytes memory _to,
address _from,
uint256 _amount,
uint256 _toChain, // target chain id
bytes calldata _swapData
) internal checkBridgeable(_token, _toChain) returns (bytes32 orderId) {
uint256 fromChain = selfChainId;
require(_toChain != fromChain, "Cannot swap to self chain");
orderId = _getOrderID(msg.sender, _to, fromChain, _toChain);
_from = (msg.sender == butterRouter) ? _from : msg.sender;
_notifyLightClient(bytes(""));
emit mapSwapOut(
fromChain,
_toChain,
orderId,
Utils.toBytes(_token),
Utils.toBytes(_from),
_to,
_amount,
_swapData
);
}
/*
function _deposit(address _token, address _from, address _to, uint256 _amount, uint256 _fromChain, uint256 _toChain) internal checkBridgeable(_token, _toChain) {
bytes32 orderId = _getOrderID(_from, Utils.toBytes(_to), _fromChain, _toChain);
_notifyLightClient(bytes(""));
emit mapDepositOut(_fromChain, _toChain, orderId, _token, Utils.toBytes(_from), _to, _amount);
}*/
function _isMintable(address _token) internal view returns (bool) {
return mintableTokens[_token];
}
function _notifyLightClient(bytes memory _data) internal {
lightNode.notifyLightClient(address(this), _data);
}
/** UUPS *********************************************************/
function _authorizeUpgrade(address) internal view override {
require(msg.sender == _getAdmin(), "MAPOmnichainService: only Admin can upgrade");
}
function changeAdmin(address _admin) external onlyOwner checkAddress(_admin) {
_changeAdmin(_admin);
}
function getAdmin() external view returns (address) {
return _getAdmin();
}
function getImplementation() external view returns (address) {
return _getImplementation();
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ILightVerifier {
struct txLog {
address addr;
bytes32[] topics;
bytes data;
}
event ClientNotifySend(address indexed sender, uint256 indexed blockHeight, bytes notifyData);
// @notice Notify light client to relay the block
// @param _data - notify data, if no data set it to empty
function notifyLightClient(address _from, bytes memory _data) external;
// @notice Validate the receipt according to the block header and receipt merkel proof
// Using block header number and block receipt root cache to optimize the validation gas cost.
// @param _receiptProof - the bytes to receipt proof
// @return success - verification result
// @return message - the result message, return null if verify successfully
// @return logs - the logs included in the receipt
function verifyProofDataWithCache(
bytes memory _receiptProof
) external returns (bool success, string memory message, bytes memory logs);
// @notice Validate the receipt according to the block header and receipt merkel proof
// Using block header number and block receipt root cache to optimize the validation gas cost.
// @param _cache - whether store the receipt root as cache, will extra cost store gas
// but will save the header proof verification if will verify more tx receipts in one block
// @param _logIndex - the log index from 0
// @param _receiptProof - the bytes to receipt proof
// @return success - verification result
// @return message - the result message, return null if verify successfully
// @return log - the log corresponding to the index
function verifyProofDataWithCache(
bool _cache,
uint256 _logIndex,
bytes calldata _receiptProofBytes
) external returns (bool success, string memory message, txLog memory log);
// @notice Validate the receipt according to the block header and receipt merkel proof
// @param _receiptProof - the bytes to receipt proof
// @return success - verification result
// @return message - the result message, return null if verify successfully
// @return logs - the rlp logs included in the receipt
function verifyProofData(
bytes memory _receiptProof
) external view returns (bool success, string memory message, bytes memory logs);
// @notice Validate the receipt according to the block header and receipt merkel proof
// @param _logIndex - the log index from 0
// @param _receiptProof - the bytes to receipt proof
// @return success - verification result
// @return message - the result message, return null if verify successfully
// @return log - the log corresponding to the index
function verifyProofData(
uint256 _logIndex,
bytes memory _receiptProof
) external view returns (bool success, string memory message, txLog memory log);
function verifiableHeaderRange() external view returns (uint256, uint256);
// @notice Check whether the block can be verified
// @param _blockHeight - the block number
// @param _hash - the block receipt root
// @return
function isVerifiable(uint256 _blockHeight, bytes32 _hash) external view returns (bool);
// @notice Get the light client type
// @return - 1 default light client
// 2 zk light client
// 3 oracle client
// 4 oracle client v2
function nodeType() external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library Utils {
uint256 constant MIN_NEAR_ADDRESS_LEN = 2;
uint256 constant MAX_NEAR_ADDRESS_LEN = 64;
function checkBytes(bytes memory b1, bytes memory b2) internal pure returns (bool) {
return keccak256(b1) == keccak256(b2);
}
function fromBytes(bytes memory bys) internal pure returns (address addr) {
assembly {
addr := mload(add(bys, 20))
}
}
function toBytes(address self) internal pure returns (bytes memory b) {
b = abi.encodePacked(self);
}
function splitExtra(bytes memory extra) internal pure returns (bytes memory newExtra) {
require(extra.length >= 64, "Invalid extra result type");
newExtra = new bytes(64);
for (uint256 i = 0; i < 64; i++) {
newExtra[i] = extra[i];
}
}
function hexStrToBytes(bytes memory _hexStr) internal pure returns (bytes memory) {
//Check hex string is valid
if (_hexStr.length % 2 != 0 || _hexStr.length < 4) {
revert("hexStrToBytes: invalid input");
}
bytes memory bytes_array = new bytes(_hexStr.length / 2 - 32);
for (uint256 i = 64; i < _hexStr.length; i += 2) {
uint8 tetrad1 = 16;
uint8 tetrad2 = 16;
//left digit
if (uint8(_hexStr[i]) >= 48 && uint8(_hexStr[i]) <= 57) tetrad1 = uint8(_hexStr[i]) - 48;
//right digit
if (uint8(_hexStr[i + 1]) >= 48 && uint8(_hexStr[i + 1]) <= 57) tetrad2 = uint8(_hexStr[i + 1]) - 48;
//left A->F
if (uint8(_hexStr[i]) >= 65 && uint8(_hexStr[i]) <= 70) tetrad1 = uint8(_hexStr[i]) - 65 + 10;
//right A->F
if (uint8(_hexStr[i + 1]) >= 65 && uint8(_hexStr[i + 1]) <= 70) tetrad2 = uint8(_hexStr[i + 1]) - 65 + 10;
//left a->f
if (uint8(_hexStr[i]) >= 97 && uint8(_hexStr[i]) <= 102) tetrad1 = uint8(_hexStr[i]) - 97 + 10;
//right a->f
if (uint8(_hexStr[i + 1]) >= 97 && uint8(_hexStr[i + 1]) <= 102) tetrad2 = uint8(_hexStr[i + 1]) - 97 + 10;
//Check all symbols are allowed
if (tetrad1 == 16 || tetrad2 == 16) revert("hexStrToBytes: invalid input");
bytes_array[i / 2 - 32] = bytes1(16 * tetrad1 + tetrad2);
}
return bytes_array;
}
function isValidNearAddress(bytes memory _addr) internal pure returns (bool) {
if (_addr.length < MIN_NEAR_ADDRESS_LEN || _addr.length > MAX_NEAR_ADDRESS_LEN) {
return false;
}
bool last_char_is_separator = true;
for (uint256 i = 0; i < _addr.length; i++) {
uint8 char = uint8(_addr[i]);
bool current_char_is_separator = false;
//char 97-122 is a-z, 48-57 is 0-9 , 45 is - ,46 is .,95 is _
if ((char >= 97 && char <= 122) || (char >= 48 && char <= 57) || (char == 45 || char == 46 || char == 95)) {
if ((char == 45 || char == 46 || char == 95)) {
current_char_is_separator = true;
}
} else {
return false;
}
if (current_char_is_separator && last_char_is_separator) {
return false;
}
last_char_is_separator = current_char_is_separator;
}
return !last_char_is_separator;
}
function isValidEvmAddress(bytes memory _addr) internal pure returns (bool) {
return _addr.length == 20;
}
function isValidAddress(bytes memory _addr, uint256 chainType) internal pure returns (bool) {
if (chainType == 1) return isValidEvmAddress(_addr);
if (chainType == 2) return isValidNearAddress(_addr);
return false;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822Proxiable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
*
* _Available since v4.8.3._
*/
interface IERC1967 {
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/
event BeaconUpgraded(address indexed beacon);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeacon {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {BeaconProxy} will check that this address is a contract.
*/
function implementation() external view returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeacon.sol";
import "../../interfaces/IERC1967.sol";
import "../../interfaces/draft-IERC1822.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*/
abstract contract ERC1967Upgrade is IERC1967 {
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
// Upgrades from old implementations will perform a rollback test. This test requires the new
// implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
// this special case will break upgrade paths from old UUPS implementation to new ones.
if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
_setImplementation(newImplementation);
} else {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
} catch {
revert("ERC1967Upgrade: new implementation is not UUPS");
}
_upgradeToAndCall(newImplementation, data, forceCall);
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
Address.isContract(IBeacon(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/Address.sol";
/**
* @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 Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 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 functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_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 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_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() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @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 {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.0;
import "../../interfaces/draft-IERC1822.sol";
import "../ERC1967/ERC1967Upgrade.sol";
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*
* _Available since v4.1._
*/
abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
require(address(this) != __self, "Function must be called through delegatecall");
require(_getImplementation() == __self, "Function must be called through active proxy");
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
_;
}
/**
* @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
return _IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeTo(address newImplementation) public virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data, true);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeTo} and {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal override onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
}// 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) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @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;
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
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// 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;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated 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.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.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: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
* _Available since v4.9 for `string`, `bytes`._
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IButterMosV2 {
function swapOutToken(
address _sender,
address _token, // src token
bytes memory _to,
uint256 _amount,
uint256 _toChain, // target chain id
bytes calldata _swapData
) external payable returns (bytes32 orderId);
//function swapOutNative(
// address _sender,
// bytes memory _to,
// uint256 _toChain, // target chain id
// bytes calldata _swapData
//) external payable returns (bytes32 orderId);
// function depositToken(address _token, address to, uint256 _amount) external payable;
//function depositNative(address _to) external payable;
function getOrderStatus(
uint256 _chainId,
uint256 _blockNum,
bytes32 _orderId
) external view returns (bool exists, bool verifiable, uint256 nodeType);
event mapTransferOut(
uint256 indexed fromChain,
uint256 indexed toChain,
bytes32 orderId,
bytes token,
bytes from,
bytes to,
uint256 amount,
bytes toChainToken
);
event mapDepositOut(
uint256 indexed fromChain,
uint256 indexed toChain,
bytes32 orderId,
address token,
bytes from,
address to,
uint256 amount
);
event mapSwapOut(
uint256 indexed fromChain, // from chain
uint256 indexed toChain, // to chain
bytes32 orderId, // order id
bytes token, // token to transfer
bytes from, // source chain from address
bytes to,
uint256 amount,
bytes swapData // swap data, used on target chain dex.
);
event mapSwapIn(
uint256 indexed fromChain,
uint256 indexed toChain,
bytes32 indexed orderId,
address token,
bytes from,
address toAddress,
uint256 amountOut
);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IButterReceiver {
//_srcToken received token (wtoken or erc20 token)
function onReceived(
bytes32 _orderId,
address _srcToken,
uint256 _amount,
uint256 _fromChain,
bytes calldata _from,
bytes calldata _payload
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IEvent {
struct depositOutEvent {
bytes token;
bytes from;
bytes32 orderId;
uint256 fromChain;
uint256 toChain;
bytes to;
uint256 amount;
}
struct swapOutEvent {
uint256 fromChain;
uint256 toChain;
bytes32 orderId;
bytes token; // token to transfer
bytes from;
bytes to;
uint256 amount;
bytes swapData;
}
/*
struct txLog {
address addr;
bytes32[] topics;
bytes data;
}*/
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IMintableToken {
function mint(address to, uint256 amount) external;
function burn(uint256 amount) external;
function burnFrom(address from, uint256 amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IWrappedToken {
function deposit() external payable;
function transfer(address to, uint256 value) external returns (bool);
function withdraw(uint256) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import "@mapprotocol/protocol/contracts/utils/Utils.sol";
import "@mapprotocol/protocol/contracts/interface/ILightVerifier.sol";
import "../interface/IEvent.sol";
library EvmDecoder {
bytes32 constant MAP_DEPOSITOUT_TOPIC =
keccak256(bytes("mapDepositOut(uint256,uint256,bytes32,address,bytes,address,uint256)"));
bytes32 constant MAP_SWAPOUT_TOPIC =
keccak256(bytes("mapSwapOut(uint256,uint256,bytes32,bytes,bytes,bytes,uint256,bytes)"));
function decodeSwapOutLog(
ILightVerifier.txLog memory log
) internal pure returns (IEvent.swapOutEvent memory outEvent) {
outEvent.fromChain = uint256(log.topics[1]);
outEvent.toChain = uint256(log.topics[2]);
(outEvent.orderId, outEvent.token, outEvent.from, outEvent.to, outEvent.amount, outEvent.swapData) = abi.decode(
log.data,
(bytes32, bytes, bytes, bytes, uint256, bytes)
);
}
function decodeDepositOutLog(
ILightVerifier.txLog memory log
) internal pure returns (bytes memory executorId, IEvent.depositOutEvent memory depositEvent) {
executorId = Utils.toBytes(log.addr);
depositEvent.fromChain = uint256(log.topics[1]);
depositEvent.toChain = uint256(log.topics[2]);
address token;
address toAddress;
(depositEvent.orderId, token, depositEvent.from, toAddress, depositEvent.amount) = abi.decode(
log.data,
(bytes32, address, bytes, address, uint256)
);
depositEvent.token = Utils.toBytes(token);
depositEvent.to = Utils.toBytes(toAddress);
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "london",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","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":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"toChain","type":"uint256"},{"indexed":false,"internalType":"bool","name":"enable","type":"bool"}],"name":"RegisterToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"butterRouter","type":"address"}],"name":"SetButterRouter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"lightNode","type":"address"}],"name":"SetLightClient","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":false,"internalType":"address","name":"relay","type":"address"}],"name":"SetRelayContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"wToken","type":"address"}],"name":"SetWrappedToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bool","name":"mintable","type":"bool"}],"name":"UpdateMintableToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromChain","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"toChain","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"orderId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bytes","name":"from","type":"bytes"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mapDepositOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromChain","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"toChain","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"orderId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bytes","name":"from","type":"bytes"},{"indexed":false,"internalType":"address","name":"toAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"mapSwapIn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"logs","type":"bytes"}],"name":"mapSwapInVerified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromChain","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"toChain","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"orderId","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"token","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"from","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"to","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"swapData","type":"bytes"}],"name":"mapSwapOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromChain","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"toChain","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"orderId","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"token","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"from","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"to","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"toChainToken","type":"bytes"}],"name":"mapTransferOut","type":"event"},{"inputs":[],"name":"butterRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"_blockNum","type":"uint256"},{"internalType":"bytes32","name":"_orderId","type":"bytes32"}],"name":"getOrderStatus","outputs":[{"internalType":"bool","name":"exists","type":"bool"},{"internalType":"bool","name":"verifiable","type":"bool"},{"internalType":"uint256","name":"nodeType","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_wToken","type":"address"},{"internalType":"address","name":"_lightNode","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_toChain","type":"uint256"}],"name":"isBridgeable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"isMintable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lightNode","outputs":[{"internalType":"contract ILightVerifier","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"uint256","name":"_logIndex","type":"uint256"},{"internalType":"bytes32","name":"_orderId","type":"bytes32"},{"internalType":"bytes","name":"_receiptProof","type":"bytes"}],"name":"messageIn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mintableTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"orderList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256[]","name":"_toChains","type":"uint256[]"},{"internalType":"bool","name":"_enable","type":"bool"}],"name":"registerTokenChains","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"relayChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"relayContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"selfChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_butterRouter","type":"address"}],"name":"setButterRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_lightNode","type":"address"}],"name":"setLightClient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"address","name":"_relay","type":"address"}],"name":"setRelayContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setUnpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"storedOrderId","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainId","type":"uint256"},{"internalType":"uint256","name":"_logIndex","type":"uint256"},{"internalType":"bytes32","name":"_orderId","type":"bytes32"},{"internalType":"bytes","name":"_receiptProof","type":"bytes"}],"name":"swapIn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_initiator","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"bytes","name":"_to","type":"bytes"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_toChain","type":"uint256"},{"internalType":"bytes","name":"_swapData","type":"bytes"}],"name":"swapOutToken","outputs":[{"internalType":"bytes32","name":"orderId","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"tokenMappingList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"bool","name":"_mintable","type":"bool"}],"name":"updateMintableToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"wToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60c0604052306080524660a05234801561001857600080fd5b5060016000819055805462ff00001916905560805160a0516132ef61007960003960008181610524015281816117740152611e6101526000818161066d015281816106b6015281816107f20152818161083201526108ae01526132ef6000f3fe6080604052600436106101e75760003560e01c80638df0dcde11610102578063d431b1ac11610095578063e35ee9cc11610064578063e35ee9cc146105d8578063ea618b87146105b8578063ee9592b9146105f8578063f5d66c2e1461063357600080fd5b8063d431b1ac14610546578063d93765fc1461055b578063d962e33b14610598578063e282dcdd146105b857600080fd5b8063b899f904116100d1578063b899f904146104bf578063c0c53b8b146104d2578063ca75ecbf146104f2578063cc9e3e891461051257600080fd5b80638df0dcde1461045e5780638f28397014610474578063aaf10f4214610494578063affed0e0146104a957600080fd5b806352d1902d1161017a5780635f670bd3116101495780635f670bd3146103e45780636af6400d146104045780636e9960c314610434578063848cb5c61461044957600080fd5b806352d1902d1461036357806355d35a40146103865780635c550ac2146103a65780635c975abb146103c657600080fd5b80633e553bab116101b65780633e553bab146102e057806345711d48146103005780634de5103e146103305780634f1ef2861461035057600080fd5b80630babd864146101f3578063222b15fb146102305780632b585db4146102795780633659cfe6146102be57600080fd5b366101ee57005b600080fd5b3480156101ff57600080fd5b50600354610213906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561023c57600080fd5b5061026961024b366004612708565b6001600160a01b031660009081526008602052604090205460ff1690565b6040519015158152602001610227565b34801561028557600080fd5b50610269610294366004612725565b60009081526009602090815260408083206001600160a01b03949094168352929052205460ff1690565b3480156102ca57600080fd5b506102de6102d9366004612708565b610663565b005b3480156102ec57600080fd5b506102de6102fb366004612708565b610734565b34801561030c57600080fd5b5061026961031b366004612708565b60086020526000908152604090205460ff1681565b34801561033c57600080fd5b50600a54610213906001600160a01b031681565b6102de61035e36600461283f565b6107e8565b34801561036f57600080fd5b506103786108a1565b604051908152602001610227565b34801561039257600080fd5b506102de6103a136600461288f565b610954565b3480156103b257600080fd5b50600454610213906001600160a01b031681565b3480156103d257600080fd5b5060015462010000900460ff16610269565b3480156103f057600080fd5b50600654610213906001600160a01b031681565b34801561041057600080fd5b5061026961041f3660046128bf565b60076020526000908152604090205460ff1681565b34801561044057600080fd5b50610213610a15565b34801561045557600080fd5b506102de610a24565b34801561046a57600080fd5b5061037860055481565b34801561048057600080fd5b506102de61048f366004612708565b610a66565b3480156104a057600080fd5b50610213610ace565b3480156104b557600080fd5b5061037860025481565b6103786104cd366004612921565b610ad8565b3480156104de57600080fd5b506102de6104ed3660046129c4565b610c9a565b3480156104fe57600080fd5b506102de61050d366004612a51565b610ec3565b34801561051e57600080fd5b506103787f000000000000000000000000000000000000000000000000000000000000000081565b34801561055257600080fd5b506102de610ffa565b34801561056757600080fd5b5061057b610576366004612b07565b61103a565b604080519315158452911515602084015290820152606001610227565b3480156105a457600080fd5b506102de6105b3366004612708565b61114a565b3480156105c457600080fd5b506102de6105d3366004612b33565b6111d6565b3480156105e457600080fd5b506102de6105f3366004612b94565b611204565b34801561060457600080fd5b5061026961061336600461288f565b600960209081526000928352604080842090915290825290205460ff1681565b34801561063f57600080fd5b5061026961064e3660046128bf565b600c6020526000908152604090205460ff1681565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036106b45760405162461bcd60e51b81526004016106ab90612c40565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166106e661131d565b6001600160a01b03161461070c5760405162461bcd60e51b81526004016106ab90612c8c565b6107158161133e565b60408051600080825260208201909252610731918391906113ba565b50565b61073c611525565b6001600160a01b0316336001600160a01b03161461076c5760405162461bcd60e51b81526004016106ab90612cd8565b806001600160a01b0381166107935760405162461bcd60e51b81526004016106ab90612d03565b600680546001600160a01b0319166001600160a01b0384169081179091556040519081527fdbbd7b2f0d0e7ab85011e3c9115c836f3cc29f189c9c0f77b8f0dc718116c9469060200160405180910390a15050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036108305760405162461bcd60e51b81526004016106ab90612c40565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661086261131d565b6001600160a01b0316146108885760405162461bcd60e51b81526004016106ab90612c8c565b6108918261133e565b61089d828260016113ba565b5050565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146109415760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016106ab565b5060008051602061323083398151915290565b61095c611525565b6001600160a01b0316336001600160a01b03161461098c5760405162461bcd60e51b81526004016106ab90612cd8565b806001600160a01b0381166109b35760405162461bcd60e51b81526004016106ab90612d03565b600480546001600160a01b0319166001600160a01b03841690811790915560058490556040805185815260208101929092527f1a43895ae95563631980575c9049ad602ade0cced91de88c94af53e71de9f080910160405180910390a1505050565b6000610a1f611525565b905090565b610a2c611525565b6001600160a01b0316336001600160a01b031614610a5c5760405162461bcd60e51b81526004016106ab90612cd8565b610a6461154d565b565b610a6e611525565b6001600160a01b0316336001600160a01b031614610a9e5760405162461bcd60e51b81526004016106ab90612cd8565b806001600160a01b038116610ac55760405162461bcd60e51b81526004016106ab90612d03565b61089d826115a1565b6000610a1f61131d565b6000610ae26115f5565b610aea61164e565b60008511610b325760405162461bcd60e51b815260206004820152601560248201527453656e64696e672076616c7565206973207a65726f60581b60448201526064016106ab565b866001600160a01b038116610beb57506003546001600160a01b031634861115610b925760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964206d73672076616c756560781b60448201526064016106ab565b806001600160a01b031663d0e30db0876040518263ffffffff1660e01b81526004016000604051808303818588803b158015610bcd57600080fd5b505af1158015610be1573d6000803e3d6000fd5b5050505050610c73565b610bf78133308961169a565b6001600160a01b03811660009081526008602052604090205460ff1615610c7357604051630852cd8d60e31b8152600481018790526001600160a01b038216906342966c6890602401600060405180830381600087803b158015610c5a57600080fd5b505af1158015610c6e573d6000803e3d6000fd5b505050505b610c8281888b89898989611705565b915050610c8f6001600055565b979650505050505050565b600154610100900460ff1615808015610cb757506001805460ff16105b80610cd05750303b158015610cd057506001805460ff16145b610d335760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016106ab565b6001805460ff1916811790558015610d55576001805461ff0019166101001790555b836001600160a01b038116610d7c5760405162461bcd60e51b81526004016106ab90612d03565b836001600160a01b038116610da35760405162461bcd60e51b81526004016106ab90612d03565b836001600160a01b038116610dca5760405162461bcd60e51b81526004016106ab90612d03565b600380546001600160a01b0319166001600160a01b0389169081179091556040519081527f556b8b8772c1552cbcc67f9bb7c7fd60934af593e54ec7aa4e8b2683632675f89060200160405180910390a1600680546001600160a01b0319166001600160a01b0388169081179091556040519081527fdbbd7b2f0d0e7ab85011e3c9115c836f3cc29f189c9c0f77b8f0dc718116c9469060200160405180910390a1610e75856115a1565b5050508015610ebd576001805461ff00191681556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610ecb611525565b6001600160a01b0316336001600160a01b031614610efb5760405162461bcd60e51b81526004016106ab90612cd8565b6001600160a01b0383163b610f4a5760405162461bcd60e51b81526020600482015260156024820152741d1bdad95b881a5cc81b9bdd0818dbdb9d1c9858dd605a1b60448201526064016106ab565b60005b8251811015610ebd576000838281518110610f6a57610f6a612d2c565b60209081029190910181015160008181526009835260408082206001600160a01b038a1680845290855291819020805460ff1916881515908117909155815192835293820183905281019290925291507fb7e2e36d837b3e9a99d8c3de2eed62d21e4b1550a939fe020796d059a023800a9060600160405180910390a15080610ff281612d42565b915050610f4d565b611002611525565b6001600160a01b0316336001600160a01b0316146110325760405162461bcd60e51b81526004016106ab90612cd8565b610a64611888565b6000818152600760205260408082205460065491516303f77f1160e21b8152600481018690526024810184905260ff909116929182916001600160a01b0390911690630fddfc4490604401602060405180830381865afa1580156110a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110c69190612d69565b9150600660009054906101000a90046001600160a01b03166001600160a01b0316633fa9a8de6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561111b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113f9190612d86565b905093509350939050565b611152611525565b6001600160a01b0316336001600160a01b0316146111825760405162461bcd60e51b81526004016106ab90612cd8565b600a80546001600160a01b0319166001600160a01b0383169081179091556040519081527f6966311b8795d1205fa0a2a7b88a0d12234ec213d66e503526fd5db465aae70e9060200160405180910390a150565b6111de6115f5565b6111e661164e565b6111f385858585856118c9565b6111fd6001600055565b5050505050565b61120c611525565b6001600160a01b0316336001600160a01b03161461123c5760405162461bcd60e51b81526004016106ab90612cd8565b60005b825181101561131857816008600085848151811061125f5761125f612d2c565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055507fc62e9940e0af53c422f2a75fd6298cfe31f6c7e05a1de1b65e759b6e423767c78382815181106112d1576112d1612d2c565b6020026020010151836040516112fe9291906001600160a01b039290921682521515602082015260400190565b60405180910390a18061131081612d42565b91505061123f565b505050565b60006000805160206132308339815191525b546001600160a01b0316919050565b611346611525565b6001600160a01b0316336001600160a01b0316146107315760405162461bcd60e51b815260206004820152602b60248201527f4d41504f6d6e69636861696e536572766963653a206f6e6c792041646d696e2060448201526a63616e207570677261646560a81b60648201526084016106ab565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156113ed5761131883611a17565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611447575060408051601f3d908101601f1916820190925261144491810190612d86565b60015b6114aa5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016106ab565b60008051602061323083398151915281146115195760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016106ab565b50611318838383611ab6565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610361132f565b611555611adb565b6001805462ff0000191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6115ca611525565b604080516001600160a01b03928316815291841660208301520160405180910390a161073181611b2a565b6002600054036116475760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106ab565b6002600055565b60015462010000900460ff1615610a645760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016106ab565b6040516001600160a01b0380851660248301528316604482015260648101829052610ebd9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611bb6565b60008381526009602090815260408083206001600160a01b038b1684529091528120548890859060ff166117725760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881b9bdd081c9959da5cdd195c995960621b60448201526064016106ab565b7f00000000000000000000000000000000000000000000000000000000000000008087036117e25760405162461bcd60e51b815260206004820152601960248201527f43616e6e6f74207377617020746f2073656c6620636861696e0000000000000060448201526064016106ab565b6117ee338b838a611c8b565b600a549094506001600160a01b03163314611809573361180b565b885b985061182560405180602001604052806000815250611cdd565b86817fca1cf8cebf88499429cca8f87cbca15ab8dafd06702259a5344ddce89ef3f3a5866118528f611d3d565b61185b8e611d3d565b8f8e8d8d6040516118729796959493929190612e18565b60405180910390a3505050979650505050505050565b61189061164e565b6001805462ff00001916620100001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586115843390565b60008381526007602052604090205460ff16156119165760405162461bcd60e51b815260206004820152600b60248201526a1bdc99195c88195e1a5cdd60aa1b60448201526064016106ab565b600554851461195a5760405162461bcd60e51b815260206004820152601060248201526f1a5b9d985b1a590818da185a5b881a5960821b60448201526064016106ab565b60065460405163108f78a560e21b8152600091829182916001600160a01b03169063423de294906119959084908b908a908a90600401612e80565b6000604051808303816000875af11580156119b4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526119dc9190810190612ef2565b925092509250828290611a025760405162461bcd60e51b81526004016106ab919061303c565b50611a0d8188611d73565b5050505050505050565b6001600160a01b0381163b611a845760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016106ab565b806000805160206132308339815191525b80546001600160a01b0319166001600160a01b039290921691909117905550565b611abf83611ecc565b600082511180611acc5750805b1561131857610ebd8383611f0c565b60015462010000900460ff16610a645760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016106ab565b6001600160a01b038116611b8f5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016106ab565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103611a95565b6000611c0b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611f389092919063ffffffff16565b9050805160001480611c2c575080806020019051810190611c2c9190612d69565b6113185760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016106ab565b6002805460009130919083611c9f83612d42565b9190505584848888604051602001611cbc9695949392919061304f565b6040516020818303038152906040528051906020012090505b949350505050565b600654604051630121b06960e71b81526001600160a01b03909116906390d8348090611d0f90309085906004016130aa565b600060405180830381600087803b158015611d2957600080fd5b505af11580156111fd573d6000803e3d6000fd5b604051606082811b6bffffffffffffffffffffffff19166020830152906034016040516020818303038152906040529050919050565b81516004546001600160a01b03908116911614611dcb5760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a59081c995b185e4818dbdb9d1c9858dd60521b60448201526064016106ab565b60405180608001604052806043815260200161327760439139805190602001208260200151600081518110611e0257611e02612d2c565b602002602001015114611e4d5760405162461bcd60e51b8152602060048201526013602482015272496e76616c69642072656c617920746f70696360681b60448201526064016106ab565b6000611e5883611f47565b905080602001517f000000000000000000000000000000000000000000000000000000000000000014611ec35760405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a59081d1bc818da185a5b881a59606a1b60448201526064016106ab565b61131881612017565b611ed581611a17565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060611f318383604051806060016040528060278152602001613250602791396122c2565b9392505050565b6060611cd5848460008561233a565b611f9260405180610100016040528060008152602001600081526020016000801916815260200160608152602001606081526020016060815260200160008152602001606081525090565b8160200151600181518110611fa957611fa9612d2c565b602090810291909101810151825282015180516002908110611fcd57611fcd612d2c565b6020908102919091018101518282015260408301518051611ff492908201810191016130ce565b60e087015260c086015260a0850152608084015260608301526040820152919050565b60408082015160008181526007602052919091205460ff161561206a5760405162461bcd60e51b815260206004820152600b60248201526a1bdc99195c88195e1a5cdd60aa1b60448201526064016106ab565b6000818152600760205260408120805460ff191660011790556060830151612093906014015190565b905060006120a68460a001516014015190565b60c08501519091506120d0836001600160a01b031660009081526008602052604090205460ff1690565b15612136576040516340c10f1960e01b8152306004820152602481018290526001600160a01b038416906340c10f1990604401600060405180830381600087803b15801561211d57600080fd5b505af1158015612131573d6000803e3d6000fd5b505050505b60008560e001515111801561215457506001600160a01b0382163b15155b156121e157612169856020015184848461240a565b6040808601518651608088015160e08901519351632344e65560e01b81526001600160a01b03871694632344e655946121ab9490938a9389939060040161318d565b600060405180830381600087803b1580156121c557600080fd5b505af19250505080156121d6575060015b1561226b575b61226b565b6003546001600160a01b039081169084160361225b57604051632e1a7d4d60e01b8152600481018290526001600160a01b03841690632e1a7d4d90602401600060405180830381600087803b15801561223957600080fd5b505af115801561224d573d6000803e3d6000fd5b505050506121dc8282612507565b61226b856020015184848461240a565b8460400151856020015186600001517f2a945137b011d4aadec6425788c652197d107fc33f6cdccbb0c269273be9c1c986896080015187876040516122b394939291906131df565b60405180910390a45050505050565b6060600080856001600160a01b0316856040516122df9190613213565b600060405180830381855af49150503d806000811461231a576040519150601f19603f3d011682016040523d82523d6000602084013e61231f565b606091505b509150915061233086838387612620565b9695505050505050565b60608247101561239b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016106ab565b600080866001600160a01b031685876040516123b79190613213565b60006040518083038185875af1925050503d80600081146123f4576040519150601f19603f3d011682016040523d82523d6000602084013e6123f9565b606091505b5091509150610c8f87838387612620565b6001600160a01b038316612427576124228282612507565b610ebd565b83632b6653dc148015612456575073a614f803b6fd780986a42c78ec9c7f77e6ded13c6001600160a01b038416145b156124fc57604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151918516916124b29190613213565b6000604051808303816000865af19150503d80600081146124ef576040519150601f19603f3d011682016040523d82523d6000602084013e6124f4565b606091505b505050610ebd565b610ebd838383612699565b804710156125575760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016106ab565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146125a4576040519150601f19603f3d011682016040523d82523d6000602084013e6125a9565b606091505b50509050806113185760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016106ab565b6060831561268f578251600003612688576001600160a01b0385163b6126885760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106ab565b5081611cd5565b611cd583836126c9565b6040516001600160a01b03831660248201526044810182905261131890849063a9059cbb60e01b906064016116ce565b8151156126d95781518083602001fd5b8060405162461bcd60e51b81526004016106ab919061303c565b6001600160a01b038116811461073157600080fd5b60006020828403121561271a57600080fd5b8135611f31816126f3565b6000806040838503121561273857600080fd5b8235612743816126f3565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff8111828210171561278a5761278a612751565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156127b9576127b9612751565b604052919050565b600067ffffffffffffffff8211156127db576127db612751565b50601f01601f191660200190565b600082601f8301126127fa57600080fd5b813561280d612808826127c1565b612790565b81815284602083860101111561282257600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561285257600080fd5b823561285d816126f3565b9150602083013567ffffffffffffffff81111561287957600080fd5b612885858286016127e9565b9150509250929050565b600080604083850312156128a257600080fd5b8235915060208301356128b4816126f3565b809150509250929050565b6000602082840312156128d157600080fd5b5035919050565b60008083601f8401126128ea57600080fd5b50813567ffffffffffffffff81111561290257600080fd5b60208301915083602082850101111561291a57600080fd5b9250929050565b600080600080600080600060c0888a03121561293c57600080fd5b8735612947816126f3565b96506020880135612957816126f3565b9550604088013567ffffffffffffffff8082111561297457600080fd5b6129808b838c016127e9565b965060608a0135955060808a0135945060a08a01359150808211156129a457600080fd5b506129b18a828b016128d8565b989b979a50959850939692959293505050565b6000806000606084860312156129d957600080fd5b83356129e4816126f3565b925060208401356129f4816126f3565b91506040840135612a04816126f3565b809150509250925092565b600067ffffffffffffffff821115612a2957612a29612751565b5060051b60200190565b801515811461073157600080fd5b8035612a4c81612a33565b919050565b600080600060608486031215612a6657600080fd5b8335612a71816126f3565b925060208481013567ffffffffffffffff811115612a8e57600080fd5b8501601f81018713612a9f57600080fd5b8035612aad61280882612a0f565b81815260059190911b82018301908381019089831115612acc57600080fd5b928401925b82841015612aea57833582529284019290840190612ad1565b8096505050505050612afe60408501612a41565b90509250925092565b600080600060608486031215612b1c57600080fd5b505081359360208301359350604090920135919050565b600080600080600060808688031215612b4b57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff811115612b7757600080fd5b612b83888289016128d8565b969995985093965092949392505050565b60008060408385031215612ba757600080fd5b823567ffffffffffffffff811115612bbe57600080fd5b8301601f81018513612bcf57600080fd5b80356020612bdf61280883612a0f565b82815260059290921b83018101918181019088841115612bfe57600080fd5b938201935b83851015612c25578435612c16816126f3565b82529382019390820190612c03565b9550612c349050868201612a41565b93505050509250929050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b60208082526011908201527036b7b9901d1d1037b7363c9030b236b4b760791b604082015260600190565b6020808252600f908201526e61646472657373206973207a65726f60881b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600060018201612d6257634e487b7160e01b600052601160045260246000fd5b5060010190565b600060208284031215612d7b57600080fd5b8151611f3181612a33565b600060208284031215612d9857600080fd5b5051919050565b60005b83811015612dba578181015183820152602001612da2565b50506000910152565b60008151808452612ddb816020860160208601612d9f565b601f01601f19169290920160200192915050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b87815260c060208201526000612e3160c0830189612dc3565b8281036040840152612e438189612dc3565b90508281036060840152612e578188612dc3565b905085608084015282810360a0840152612e72818587612def565b9a9950505050505050505050565b8415158152836020820152606060408201526000612330606083018486612def565b6000612eb0612808846127c1565b9050828152838383011115612ec457600080fd5b611f31836020830184612d9f565b600082601f830112612ee357600080fd5b611f3183835160208501612ea2565b600080600060608486031215612f0757600080fd5b8351612f1281612a33565b8093505060208085015167ffffffffffffffff80821115612f3257600080fd5b818701915087601f830112612f4657600080fd5b612f54888351858501612ea2565b94506040870151915080821115612f6a57600080fd5b9086019060608289031215612f7e57600080fd5b612f86612767565b8251612f91816126f3565b81528284015182811115612fa457600080fd5b8301601f81018a13612fb557600080fd5b8051612fc361280882612a0f565b81815260059190911b8201860190868101908c831115612fe257600080fd5b928701925b8284101561300057835182529287019290870190612fe7565b808886015250505050604083015193508184111561301d57600080fd5b61302989858501612ed2565b6040820152809450505050509250925092565b602081526000611f316020830184612dc3565b60006bffffffffffffffffffffffff19808960601b168352876014840152866034840152856054840152808560601b166074840152508251613098816088850160208701612d9f565b91909101608801979650505050505050565b6001600160a01b0383168152604060208201819052600090611cd590830184612dc3565b60008060008060008060c087890312156130e757600080fd5b86519550602087015167ffffffffffffffff8082111561310657600080fd5b6131128a838b01612ed2565b9650604089015191508082111561312857600080fd5b6131348a838b01612ed2565b9550606089015191508082111561314a57600080fd5b6131568a838b01612ed2565b94506080890151935060a089015191508082111561317357600080fd5b5061318089828a01612ed2565b9150509295509295509295565b86815260018060a01b038616602082015284604082015283606082015260c0608082015260006131c060c0830185612dc3565b82810360a08401526131d28185612dc3565b9998505050505050505050565b600060018060a01b038087168352608060208401526132016080840187612dc3565b94166040830152506060015292915050565b60008251613225818460208701612d9f565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c65646d6170537761704f75742875696e743235362c75696e743235362c627974657333322c62797465732c62797465732c62797465732c75696e743235362c627974657329a2646970667358221220fea5e06bedf78242e2e5f7ae5a770475764bef400046ba0830bcdedc9081ac4764736f6c63430008140033
Deployed Bytecode
0x6080604052600436106101e75760003560e01c80638df0dcde11610102578063d431b1ac11610095578063e35ee9cc11610064578063e35ee9cc146105d8578063ea618b87146105b8578063ee9592b9146105f8578063f5d66c2e1461063357600080fd5b8063d431b1ac14610546578063d93765fc1461055b578063d962e33b14610598578063e282dcdd146105b857600080fd5b8063b899f904116100d1578063b899f904146104bf578063c0c53b8b146104d2578063ca75ecbf146104f2578063cc9e3e891461051257600080fd5b80638df0dcde1461045e5780638f28397014610474578063aaf10f4214610494578063affed0e0146104a957600080fd5b806352d1902d1161017a5780635f670bd3116101495780635f670bd3146103e45780636af6400d146104045780636e9960c314610434578063848cb5c61461044957600080fd5b806352d1902d1461036357806355d35a40146103865780635c550ac2146103a65780635c975abb146103c657600080fd5b80633e553bab116101b65780633e553bab146102e057806345711d48146103005780634de5103e146103305780634f1ef2861461035057600080fd5b80630babd864146101f3578063222b15fb146102305780632b585db4146102795780633659cfe6146102be57600080fd5b366101ee57005b600080fd5b3480156101ff57600080fd5b50600354610213906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561023c57600080fd5b5061026961024b366004612708565b6001600160a01b031660009081526008602052604090205460ff1690565b6040519015158152602001610227565b34801561028557600080fd5b50610269610294366004612725565b60009081526009602090815260408083206001600160a01b03949094168352929052205460ff1690565b3480156102ca57600080fd5b506102de6102d9366004612708565b610663565b005b3480156102ec57600080fd5b506102de6102fb366004612708565b610734565b34801561030c57600080fd5b5061026961031b366004612708565b60086020526000908152604090205460ff1681565b34801561033c57600080fd5b50600a54610213906001600160a01b031681565b6102de61035e36600461283f565b6107e8565b34801561036f57600080fd5b506103786108a1565b604051908152602001610227565b34801561039257600080fd5b506102de6103a136600461288f565b610954565b3480156103b257600080fd5b50600454610213906001600160a01b031681565b3480156103d257600080fd5b5060015462010000900460ff16610269565b3480156103f057600080fd5b50600654610213906001600160a01b031681565b34801561041057600080fd5b5061026961041f3660046128bf565b60076020526000908152604090205460ff1681565b34801561044057600080fd5b50610213610a15565b34801561045557600080fd5b506102de610a24565b34801561046a57600080fd5b5061037860055481565b34801561048057600080fd5b506102de61048f366004612708565b610a66565b3480156104a057600080fd5b50610213610ace565b3480156104b557600080fd5b5061037860025481565b6103786104cd366004612921565b610ad8565b3480156104de57600080fd5b506102de6104ed3660046129c4565b610c9a565b3480156104fe57600080fd5b506102de61050d366004612a51565b610ec3565b34801561051e57600080fd5b506103787f0000000000000000000000000000000000000000000000000000000000013e3181565b34801561055257600080fd5b506102de610ffa565b34801561056757600080fd5b5061057b610576366004612b07565b61103a565b604080519315158452911515602084015290820152606001610227565b3480156105a457600080fd5b506102de6105b3366004612708565b61114a565b3480156105c457600080fd5b506102de6105d3366004612b33565b6111d6565b3480156105e457600080fd5b506102de6105f3366004612b94565b611204565b34801561060457600080fd5b5061026961061336600461288f565b600960209081526000928352604080842090915290825290205460ff1681565b34801561063f57600080fd5b5061026961064e3660046128bf565b600c6020526000908152604090205460ff1681565b6001600160a01b037f0000000000000000000000004b7d6ba5b9995b54dd3ad3bc27fa976f4a804bb21630036106b45760405162461bcd60e51b81526004016106ab90612c40565b60405180910390fd5b7f0000000000000000000000004b7d6ba5b9995b54dd3ad3bc27fa976f4a804bb26001600160a01b03166106e661131d565b6001600160a01b03161461070c5760405162461bcd60e51b81526004016106ab90612c8c565b6107158161133e565b60408051600080825260208201909252610731918391906113ba565b50565b61073c611525565b6001600160a01b0316336001600160a01b03161461076c5760405162461bcd60e51b81526004016106ab90612cd8565b806001600160a01b0381166107935760405162461bcd60e51b81526004016106ab90612d03565b600680546001600160a01b0319166001600160a01b0384169081179091556040519081527fdbbd7b2f0d0e7ab85011e3c9115c836f3cc29f189c9c0f77b8f0dc718116c9469060200160405180910390a15050565b6001600160a01b037f0000000000000000000000004b7d6ba5b9995b54dd3ad3bc27fa976f4a804bb21630036108305760405162461bcd60e51b81526004016106ab90612c40565b7f0000000000000000000000004b7d6ba5b9995b54dd3ad3bc27fa976f4a804bb26001600160a01b031661086261131d565b6001600160a01b0316146108885760405162461bcd60e51b81526004016106ab90612c8c565b6108918261133e565b61089d828260016113ba565b5050565b6000306001600160a01b037f0000000000000000000000004b7d6ba5b9995b54dd3ad3bc27fa976f4a804bb216146109415760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016106ab565b5060008051602061323083398151915290565b61095c611525565b6001600160a01b0316336001600160a01b03161461098c5760405162461bcd60e51b81526004016106ab90612cd8565b806001600160a01b0381166109b35760405162461bcd60e51b81526004016106ab90612d03565b600480546001600160a01b0319166001600160a01b03841690811790915560058490556040805185815260208101929092527f1a43895ae95563631980575c9049ad602ade0cced91de88c94af53e71de9f080910160405180910390a1505050565b6000610a1f611525565b905090565b610a2c611525565b6001600160a01b0316336001600160a01b031614610a5c5760405162461bcd60e51b81526004016106ab90612cd8565b610a6461154d565b565b610a6e611525565b6001600160a01b0316336001600160a01b031614610a9e5760405162461bcd60e51b81526004016106ab90612cd8565b806001600160a01b038116610ac55760405162461bcd60e51b81526004016106ab90612d03565b61089d826115a1565b6000610a1f61131d565b6000610ae26115f5565b610aea61164e565b60008511610b325760405162461bcd60e51b815260206004820152601560248201527453656e64696e672076616c7565206973207a65726f60581b60448201526064016106ab565b866001600160a01b038116610beb57506003546001600160a01b031634861115610b925760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964206d73672076616c756560781b60448201526064016106ab565b806001600160a01b031663d0e30db0876040518263ffffffff1660e01b81526004016000604051808303818588803b158015610bcd57600080fd5b505af1158015610be1573d6000803e3d6000fd5b5050505050610c73565b610bf78133308961169a565b6001600160a01b03811660009081526008602052604090205460ff1615610c7357604051630852cd8d60e31b8152600481018790526001600160a01b038216906342966c6890602401600060405180830381600087803b158015610c5a57600080fd5b505af1158015610c6e573d6000803e3d6000fd5b505050505b610c8281888b89898989611705565b915050610c8f6001600055565b979650505050505050565b600154610100900460ff1615808015610cb757506001805460ff16105b80610cd05750303b158015610cd057506001805460ff16145b610d335760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016106ab565b6001805460ff1916811790558015610d55576001805461ff0019166101001790555b836001600160a01b038116610d7c5760405162461bcd60e51b81526004016106ab90612d03565b836001600160a01b038116610da35760405162461bcd60e51b81526004016106ab90612d03565b836001600160a01b038116610dca5760405162461bcd60e51b81526004016106ab90612d03565b600380546001600160a01b0319166001600160a01b0389169081179091556040519081527f556b8b8772c1552cbcc67f9bb7c7fd60934af593e54ec7aa4e8b2683632675f89060200160405180910390a1600680546001600160a01b0319166001600160a01b0388169081179091556040519081527fdbbd7b2f0d0e7ab85011e3c9115c836f3cc29f189c9c0f77b8f0dc718116c9469060200160405180910390a1610e75856115a1565b5050508015610ebd576001805461ff00191681556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610ecb611525565b6001600160a01b0316336001600160a01b031614610efb5760405162461bcd60e51b81526004016106ab90612cd8565b6001600160a01b0383163b610f4a5760405162461bcd60e51b81526020600482015260156024820152741d1bdad95b881a5cc81b9bdd0818dbdb9d1c9858dd605a1b60448201526064016106ab565b60005b8251811015610ebd576000838281518110610f6a57610f6a612d2c565b60209081029190910181015160008181526009835260408082206001600160a01b038a1680845290855291819020805460ff1916881515908117909155815192835293820183905281019290925291507fb7e2e36d837b3e9a99d8c3de2eed62d21e4b1550a939fe020796d059a023800a9060600160405180910390a15080610ff281612d42565b915050610f4d565b611002611525565b6001600160a01b0316336001600160a01b0316146110325760405162461bcd60e51b81526004016106ab90612cd8565b610a64611888565b6000818152600760205260408082205460065491516303f77f1160e21b8152600481018690526024810184905260ff909116929182916001600160a01b0390911690630fddfc4490604401602060405180830381865afa1580156110a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110c69190612d69565b9150600660009054906101000a90046001600160a01b03166001600160a01b0316633fa9a8de6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561111b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113f9190612d86565b905093509350939050565b611152611525565b6001600160a01b0316336001600160a01b0316146111825760405162461bcd60e51b81526004016106ab90612cd8565b600a80546001600160a01b0319166001600160a01b0383169081179091556040519081527f6966311b8795d1205fa0a2a7b88a0d12234ec213d66e503526fd5db465aae70e9060200160405180910390a150565b6111de6115f5565b6111e661164e565b6111f385858585856118c9565b6111fd6001600055565b5050505050565b61120c611525565b6001600160a01b0316336001600160a01b03161461123c5760405162461bcd60e51b81526004016106ab90612cd8565b60005b825181101561131857816008600085848151811061125f5761125f612d2c565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055507fc62e9940e0af53c422f2a75fd6298cfe31f6c7e05a1de1b65e759b6e423767c78382815181106112d1576112d1612d2c565b6020026020010151836040516112fe9291906001600160a01b039290921682521515602082015260400190565b60405180910390a18061131081612d42565b91505061123f565b505050565b60006000805160206132308339815191525b546001600160a01b0316919050565b611346611525565b6001600160a01b0316336001600160a01b0316146107315760405162461bcd60e51b815260206004820152602b60248201527f4d41504f6d6e69636861696e536572766963653a206f6e6c792041646d696e2060448201526a63616e207570677261646560a81b60648201526084016106ab565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156113ed5761131883611a17565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611447575060408051601f3d908101601f1916820190925261144491810190612d86565b60015b6114aa5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016106ab565b60008051602061323083398151915281146115195760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016106ab565b50611318838383611ab6565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610361132f565b611555611adb565b6001805462ff0000191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6115ca611525565b604080516001600160a01b03928316815291841660208301520160405180910390a161073181611b2a565b6002600054036116475760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106ab565b6002600055565b60015462010000900460ff1615610a645760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016106ab565b6040516001600160a01b0380851660248301528316604482015260648101829052610ebd9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611bb6565b60008381526009602090815260408083206001600160a01b038b1684529091528120548890859060ff166117725760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881b9bdd081c9959da5cdd195c995960621b60448201526064016106ab565b7f0000000000000000000000000000000000000000000000000000000000013e318087036117e25760405162461bcd60e51b815260206004820152601960248201527f43616e6e6f74207377617020746f2073656c6620636861696e0000000000000060448201526064016106ab565b6117ee338b838a611c8b565b600a549094506001600160a01b03163314611809573361180b565b885b985061182560405180602001604052806000815250611cdd565b86817fca1cf8cebf88499429cca8f87cbca15ab8dafd06702259a5344ddce89ef3f3a5866118528f611d3d565b61185b8e611d3d565b8f8e8d8d6040516118729796959493929190612e18565b60405180910390a3505050979650505050505050565b61189061164e565b6001805462ff00001916620100001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586115843390565b60008381526007602052604090205460ff16156119165760405162461bcd60e51b815260206004820152600b60248201526a1bdc99195c88195e1a5cdd60aa1b60448201526064016106ab565b600554851461195a5760405162461bcd60e51b815260206004820152601060248201526f1a5b9d985b1a590818da185a5b881a5960821b60448201526064016106ab565b60065460405163108f78a560e21b8152600091829182916001600160a01b03169063423de294906119959084908b908a908a90600401612e80565b6000604051808303816000875af11580156119b4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526119dc9190810190612ef2565b925092509250828290611a025760405162461bcd60e51b81526004016106ab919061303c565b50611a0d8188611d73565b5050505050505050565b6001600160a01b0381163b611a845760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016106ab565b806000805160206132308339815191525b80546001600160a01b0319166001600160a01b039290921691909117905550565b611abf83611ecc565b600082511180611acc5750805b1561131857610ebd8383611f0c565b60015462010000900460ff16610a645760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016106ab565b6001600160a01b038116611b8f5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084016106ab565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103611a95565b6000611c0b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611f389092919063ffffffff16565b9050805160001480611c2c575080806020019051810190611c2c9190612d69565b6113185760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016106ab565b6002805460009130919083611c9f83612d42565b9190505584848888604051602001611cbc9695949392919061304f565b6040516020818303038152906040528051906020012090505b949350505050565b600654604051630121b06960e71b81526001600160a01b03909116906390d8348090611d0f90309085906004016130aa565b600060405180830381600087803b158015611d2957600080fd5b505af11580156111fd573d6000803e3d6000fd5b604051606082811b6bffffffffffffffffffffffff19166020830152906034016040516020818303038152906040529050919050565b81516004546001600160a01b03908116911614611dcb5760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a59081c995b185e4818dbdb9d1c9858dd60521b60448201526064016106ab565b60405180608001604052806043815260200161327760439139805190602001208260200151600081518110611e0257611e02612d2c565b602002602001015114611e4d5760405162461bcd60e51b8152602060048201526013602482015272496e76616c69642072656c617920746f70696360681b60448201526064016106ab565b6000611e5883611f47565b905080602001517f0000000000000000000000000000000000000000000000000000000000013e3114611ec35760405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a59081d1bc818da185a5b881a59606a1b60448201526064016106ab565b61131881612017565b611ed581611a17565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060611f318383604051806060016040528060278152602001613250602791396122c2565b9392505050565b6060611cd5848460008561233a565b611f9260405180610100016040528060008152602001600081526020016000801916815260200160608152602001606081526020016060815260200160008152602001606081525090565b8160200151600181518110611fa957611fa9612d2c565b602090810291909101810151825282015180516002908110611fcd57611fcd612d2c565b6020908102919091018101518282015260408301518051611ff492908201810191016130ce565b60e087015260c086015260a0850152608084015260608301526040820152919050565b60408082015160008181526007602052919091205460ff161561206a5760405162461bcd60e51b815260206004820152600b60248201526a1bdc99195c88195e1a5cdd60aa1b60448201526064016106ab565b6000818152600760205260408120805460ff191660011790556060830151612093906014015190565b905060006120a68460a001516014015190565b60c08501519091506120d0836001600160a01b031660009081526008602052604090205460ff1690565b15612136576040516340c10f1960e01b8152306004820152602481018290526001600160a01b038416906340c10f1990604401600060405180830381600087803b15801561211d57600080fd5b505af1158015612131573d6000803e3d6000fd5b505050505b60008560e001515111801561215457506001600160a01b0382163b15155b156121e157612169856020015184848461240a565b6040808601518651608088015160e08901519351632344e65560e01b81526001600160a01b03871694632344e655946121ab9490938a9389939060040161318d565b600060405180830381600087803b1580156121c557600080fd5b505af19250505080156121d6575060015b1561226b575b61226b565b6003546001600160a01b039081169084160361225b57604051632e1a7d4d60e01b8152600481018290526001600160a01b03841690632e1a7d4d90602401600060405180830381600087803b15801561223957600080fd5b505af115801561224d573d6000803e3d6000fd5b505050506121dc8282612507565b61226b856020015184848461240a565b8460400151856020015186600001517f2a945137b011d4aadec6425788c652197d107fc33f6cdccbb0c269273be9c1c986896080015187876040516122b394939291906131df565b60405180910390a45050505050565b6060600080856001600160a01b0316856040516122df9190613213565b600060405180830381855af49150503d806000811461231a576040519150601f19603f3d011682016040523d82523d6000602084013e61231f565b606091505b509150915061233086838387612620565b9695505050505050565b60608247101561239b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016106ab565b600080866001600160a01b031685876040516123b79190613213565b60006040518083038185875af1925050503d80600081146123f4576040519150601f19603f3d011682016040523d82523d6000602084013e6123f9565b606091505b5091509150610c8f87838387612620565b6001600160a01b038316612427576124228282612507565b610ebd565b83632b6653dc148015612456575073a614f803b6fd780986a42c78ec9c7f77e6ded13c6001600160a01b038416145b156124fc57604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151918516916124b29190613213565b6000604051808303816000865af19150503d80600081146124ef576040519150601f19603f3d011682016040523d82523d6000602084013e6124f4565b606091505b505050610ebd565b610ebd838383612699565b804710156125575760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016106ab565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146125a4576040519150601f19603f3d011682016040523d82523d6000602084013e6125a9565b606091505b50509050806113185760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016106ab565b6060831561268f578251600003612688576001600160a01b0385163b6126885760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106ab565b5081611cd5565b611cd583836126c9565b6040516001600160a01b03831660248201526044810182905261131890849063a9059cbb60e01b906064016116ce565b8151156126d95781518083602001fd5b8060405162461bcd60e51b81526004016106ab919061303c565b6001600160a01b038116811461073157600080fd5b60006020828403121561271a57600080fd5b8135611f31816126f3565b6000806040838503121561273857600080fd5b8235612743816126f3565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff8111828210171561278a5761278a612751565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156127b9576127b9612751565b604052919050565b600067ffffffffffffffff8211156127db576127db612751565b50601f01601f191660200190565b600082601f8301126127fa57600080fd5b813561280d612808826127c1565b612790565b81815284602083860101111561282257600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561285257600080fd5b823561285d816126f3565b9150602083013567ffffffffffffffff81111561287957600080fd5b612885858286016127e9565b9150509250929050565b600080604083850312156128a257600080fd5b8235915060208301356128b4816126f3565b809150509250929050565b6000602082840312156128d157600080fd5b5035919050565b60008083601f8401126128ea57600080fd5b50813567ffffffffffffffff81111561290257600080fd5b60208301915083602082850101111561291a57600080fd5b9250929050565b600080600080600080600060c0888a03121561293c57600080fd5b8735612947816126f3565b96506020880135612957816126f3565b9550604088013567ffffffffffffffff8082111561297457600080fd5b6129808b838c016127e9565b965060608a0135955060808a0135945060a08a01359150808211156129a457600080fd5b506129b18a828b016128d8565b989b979a50959850939692959293505050565b6000806000606084860312156129d957600080fd5b83356129e4816126f3565b925060208401356129f4816126f3565b91506040840135612a04816126f3565b809150509250925092565b600067ffffffffffffffff821115612a2957612a29612751565b5060051b60200190565b801515811461073157600080fd5b8035612a4c81612a33565b919050565b600080600060608486031215612a6657600080fd5b8335612a71816126f3565b925060208481013567ffffffffffffffff811115612a8e57600080fd5b8501601f81018713612a9f57600080fd5b8035612aad61280882612a0f565b81815260059190911b82018301908381019089831115612acc57600080fd5b928401925b82841015612aea57833582529284019290840190612ad1565b8096505050505050612afe60408501612a41565b90509250925092565b600080600060608486031215612b1c57600080fd5b505081359360208301359350604090920135919050565b600080600080600060808688031215612b4b57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff811115612b7757600080fd5b612b83888289016128d8565b969995985093965092949392505050565b60008060408385031215612ba757600080fd5b823567ffffffffffffffff811115612bbe57600080fd5b8301601f81018513612bcf57600080fd5b80356020612bdf61280883612a0f565b82815260059290921b83018101918181019088841115612bfe57600080fd5b938201935b83851015612c25578435612c16816126f3565b82529382019390820190612c03565b9550612c349050868201612a41565b93505050509250929050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b60208082526011908201527036b7b9901d1d1037b7363c9030b236b4b760791b604082015260600190565b6020808252600f908201526e61646472657373206973207a65726f60881b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600060018201612d6257634e487b7160e01b600052601160045260246000fd5b5060010190565b600060208284031215612d7b57600080fd5b8151611f3181612a33565b600060208284031215612d9857600080fd5b5051919050565b60005b83811015612dba578181015183820152602001612da2565b50506000910152565b60008151808452612ddb816020860160208601612d9f565b601f01601f19169290920160200192915050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b87815260c060208201526000612e3160c0830189612dc3565b8281036040840152612e438189612dc3565b90508281036060840152612e578188612dc3565b905085608084015282810360a0840152612e72818587612def565b9a9950505050505050505050565b8415158152836020820152606060408201526000612330606083018486612def565b6000612eb0612808846127c1565b9050828152838383011115612ec457600080fd5b611f31836020830184612d9f565b600082601f830112612ee357600080fd5b611f3183835160208501612ea2565b600080600060608486031215612f0757600080fd5b8351612f1281612a33565b8093505060208085015167ffffffffffffffff80821115612f3257600080fd5b818701915087601f830112612f4657600080fd5b612f54888351858501612ea2565b94506040870151915080821115612f6a57600080fd5b9086019060608289031215612f7e57600080fd5b612f86612767565b8251612f91816126f3565b81528284015182811115612fa457600080fd5b8301601f81018a13612fb557600080fd5b8051612fc361280882612a0f565b81815260059190911b8201860190868101908c831115612fe257600080fd5b928701925b8284101561300057835182529287019290870190612fe7565b808886015250505050604083015193508184111561301d57600080fd5b61302989858501612ed2565b6040820152809450505050509250925092565b602081526000611f316020830184612dc3565b60006bffffffffffffffffffffffff19808960601b168352876014840152866034840152856054840152808560601b166074840152508251613098816088850160208701612d9f565b91909101608801979650505050505050565b6001600160a01b0383168152604060208201819052600090611cd590830184612dc3565b60008060008060008060c087890312156130e757600080fd5b86519550602087015167ffffffffffffffff8082111561310657600080fd5b6131128a838b01612ed2565b9650604089015191508082111561312857600080fd5b6131348a838b01612ed2565b9550606089015191508082111561314a57600080fd5b6131568a838b01612ed2565b94506080890151935060a089015191508082111561317357600080fd5b5061318089828a01612ed2565b9150509295509295509295565b86815260018060a01b038616602082015284604082015283606082015260c0608082015260006131c060c0830185612dc3565b82810360a08401526131d28185612dc3565b9998505050505050505050565b600060018060a01b038087168352608060208401526132016080840187612dc3565b94166040830152506060015292915050565b60008251613225818460208701612d9f565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c65646d6170537761704f75742875696e743235362c75696e743235362c627974657333322c62797465732c62797465732c62797465732c75696e743235362c627974657329a2646970667358221220fea5e06bedf78242e2e5f7ae5a770475764bef400046ba0830bcdedc9081ac4764736f6c63430008140033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.