Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
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:
USSI
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.25;
import './Interface.sol';
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {SignatureChecker} from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
import {AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
// import "forge-std/console.sol";
contract USSI is Initializable, OwnableUpgradeable, AccessControlUpgradeable, ERC20Upgradeable, UUPSUpgradeable, PausableUpgradeable {
using EnumerableSet for EnumerableSet.Bytes32Set;
using EnumerableSet for EnumerableSet.UintSet;
using EnumerableSet for EnumerableSet.AddressSet;
using SafeERC20 for IERC20;
enum HedgeOrderType { NONE, MINT, REDEEM, TOKEN_MINT }
enum HedgeOrderStatus { NONE, PENDING, REJECTED, CONFIRMED, CANCELED }
struct HedgeOrder {
string chain;
HedgeOrderType orderType;
uint256 assetID;
address redeemToken;
uint256 nonce;
uint256 inAmount;
uint256 outAmount;
uint256 deadline;
address requester;
address receiver;
address token;
address vault;
}
EnumerableSet.Bytes32Set orderHashs;
mapping(bytes32 => HedgeOrder) public hedgeOrders;
mapping(bytes32 => HedgeOrderStatus) public orderStatus;
mapping(bytes32 => uint256) public requestTimestamps;
EnumerableSet.UintSet supportAssetIDs;
address public redeemToken;
address public orderSigner;
address public factoryAddress;
bytes32 public constant PARTICIPANT_ROLE = keccak256("PARTICIPANT_ROLE");
mapping(bytes32 => bytes32) public redeemTxHashs;
string public chain;
uint256 public constant MAX_MINT_DELAY = 1 days;
uint256 public constant MAX_REDEEM_DELAY = 7 days;
EnumerableSet.AddressSet supportTokens;
address public vault;
mapping(address => address) public vaultRoutes;
EnumerableSet.AddressSet routeRequesters;
mapping(address => uint256) public mintPendingAmounts;
mapping(address => uint256) public redeemPendingAmounts;
event AddAssetID(uint256 assetID);
event RemoveAssetID(uint256 assetID);
event AddToken(address token);
event RemoveToken(address token);
event UpdateOrderSigner(address oldOrderSigner, address orderSigner);
event UpdateRedeemToken(address oldRedeemToken, address redeemToken);
event ApplyMint(HedgeOrder hedgeOrder);
event RejectMint(bytes32 orderHash);
event ConfirmMint(bytes32 orderHash);
event ApplyRedeem(HedgeOrder hedgeOrder);
event RejectRedeem(bytes32 orderHash);
event ConfirmRedeem(bytes32 orderHash);
event CancelMint(bytes32 orderHash);
event CancelRedeem(bytes32 orderHash);
event UpdateVault(address oldVault, address vault);
event AddVaultRoute(address requester, address vault);
event RemoveVaultRoute(address requester);
event RescueToken(address token, uint256 amount);
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
function initialize(address owner, address orderSigner_, address factoryAddress_, address redeemToken_, string memory chain_) public initializer {
__Ownable_init(owner);
__AccessControl_init();
__ERC20_init("USSI", "USSI");
__UUPSUpgradeable_init();
__Pausable_init();
require(factoryAddress_ != address(0), "zero factory address");
require(redeemToken_ != address(0), "zero redeem token address");
require(orderSigner_ != address(0), "zero order signer address");
factoryAddress = factoryAddress_;
redeemToken = redeemToken_;
orderSigner = orderSigner_;
chain = chain_;
_grantRole(DEFAULT_ADMIN_ROLE, owner);
}
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
function decimals() public pure override(ERC20Upgradeable) returns (uint8) {
return 8;
}
function getSupportAssetIDs() external view returns (uint256[] memory assetIDs) {
assetIDs = new uint256[](supportAssetIDs.length());
for (uint i = 0; i < assetIDs.length; i++) {
assetIDs[i] = supportAssetIDs.at(i);
}
}
function addSupportAsset(uint256 assetID) external onlyOwner {
require(IAssetFactory(factoryAddress).hasAssetID(assetID), "asset not exists");
require(!supportAssetIDs.contains(assetID), "already contains assetID");
supportAssetIDs.add(assetID);
emit AddAssetID(assetID);
}
function removeSupportAsset(uint256 assetID) external onlyOwner {
require(IAssetFactory(factoryAddress).hasAssetID(assetID), "asset not exists");
require(supportAssetIDs.contains(assetID), "assetID is not supported");
supportAssetIDs.remove(assetID);
emit RemoveAssetID(assetID);
}
function getSupportTokens() external view returns (address[] memory tokens) {
tokens = new address[](supportTokens.length());
for (uint i = 0; i < tokens.length; i++) {
tokens[i] = supportTokens.at(i);
}
}
function addSupportToken(address token) external onlyOwner {
require(token != address(0), "token is zero address");
require(!supportTokens.contains(token), "already contains token");
supportTokens.add(token);
emit AddToken(token);
}
function removeSupportToken(address token) external onlyOwner {
require(token != address(0), "token is zero address");
require(supportTokens.contains(token), "token is not supported");
supportTokens.remove(token);
emit RemoveToken(token);
}
function updateVault(address vault_) external onlyOwner {
address oldVault = vault;
require(vault_ != address(0), "vault is zero address");
require(vault_ != vault, "vault not change");
vault = vault_;
emit UpdateVault(oldVault, vault);
}
function getVaultRoute(address requester) public view returns (address) {
if (vaultRoutes[requester] == address(0)) {
return vault;
}
return vaultRoutes[requester];
}
function addVaultRoute(address requester, address vault_) external onlyOwner {
require(vault_ != address(0), "vault is zero address");
require(vaultRoutes[requester] != vault_, "vault route not change");
vaultRoutes[requester] = vault_;
routeRequesters.add(requester);
emit AddVaultRoute(requester, vault_);
}
function removeVaultRoute(address requester) external onlyOwner {
require(vaultRoutes[requester] != address(0), "vault route not exists");
delete vaultRoutes[requester];
routeRequesters.remove(requester);
emit RemoveVaultRoute(requester);
}
// @dev only for off-chain use
function getVaultRoutes() external view returns (address[] memory requesters, address[] memory vaults) {
requesters = new address[](routeRequesters.length());
vaults = new address[](routeRequesters.length());
for (uint i = 0; i < routeRequesters.length(); i++) {
requesters[i] = routeRequesters.at(i);
vaults[i] = vaultRoutes[routeRequesters.at(i)];
}
}
function updateOrderSigner(address orderSigner_) external onlyOwner {
address oldOrderSigner = orderSigner;
require(orderSigner_ != address(0), "orderSigner is zero address");
require(orderSigner_ != orderSigner, "orderSigner not change");
orderSigner = orderSigner_;
emit UpdateOrderSigner(oldOrderSigner, orderSigner);
}
function updateRedeemToken(address redeemToken_) external onlyOwner {
address oldRedeemToken = redeemToken;
require(redeemToken_ != address(0), "redeem token is zero address");
require(redeemToken_ != redeemToken, "redeem token not change");
redeemToken = redeemToken_;
emit UpdateRedeemToken(oldRedeemToken, redeemToken);
}
function checkHedgeOrder(HedgeOrder calldata hedgeOrder, bytes32 orderHash, bytes calldata orderSignature) public view {
require(keccak256(abi.encode(chain)) == keccak256(abi.encode(hedgeOrder.chain)), "chain not match");
require(hedgeOrder.orderType != HedgeOrderType.NONE, "order type is none");
if (hedgeOrder.orderType == HedgeOrderType.MINT) {
require(supportAssetIDs.contains(hedgeOrder.assetID), "assetID not supported");
}
if (hedgeOrder.orderType == HedgeOrderType.REDEEM) {
require(hedgeOrder.receiver != address(0), "receiver is zero address");
require(redeemToken == hedgeOrder.redeemToken, "redeem token not supported");
}
if (hedgeOrder.orderType == HedgeOrderType.TOKEN_MINT) {
require(hedgeOrder.token != address(0), "token is zero address");
require(supportTokens.contains(hedgeOrder.token), "token not supported");
}
require(block.timestamp <= hedgeOrder.deadline, "expired");
require(!orderHashs.contains(orderHash), "order already exists");
require(SignatureChecker.isValidSignatureNow(orderSigner, orderHash, orderSignature), "signature not valid");
}
function setHedgeOrder(bytes32 orderHash, HedgeOrder calldata hedgeOrder) internal {
HedgeOrder storage hedgeOrder_ = hedgeOrders[orderHash];
hedgeOrder_.chain = hedgeOrder.chain;
hedgeOrder_.orderType = hedgeOrder.orderType;
hedgeOrder_.assetID = hedgeOrder.assetID;
hedgeOrder_.redeemToken = redeemToken;
hedgeOrder_.nonce = hedgeOrder.nonce;
hedgeOrder_.inAmount = hedgeOrder.inAmount;
hedgeOrder_.outAmount = hedgeOrder.outAmount;
hedgeOrder_.deadline = hedgeOrder.deadline;
hedgeOrder_.requester = hedgeOrder.requester;
hedgeOrder_.receiver = hedgeOrder.receiver;
hedgeOrder_.token = hedgeOrder.token;
hedgeOrder_.vault = hedgeOrder.vault;
orderHashs.add(orderHash);
}
function applyMint(HedgeOrder calldata hedgeOrder, bytes calldata orderSignature) external onlyRole(PARTICIPANT_ROLE) whenNotPaused {
require(hedgeOrder.requester == msg.sender, "msg sender is not requester");
bytes32 orderHash = keccak256(abi.encode(hedgeOrder));
checkHedgeOrder(hedgeOrder, orderHash, orderSignature);
require(hedgeOrder.orderType == HedgeOrderType.MINT || hedgeOrder.orderType == HedgeOrderType.TOKEN_MINT, "order type not match");
IERC20 token;
if (hedgeOrder.orderType == HedgeOrderType.MINT) {
// cannot hedge when underlying is changing
IAssetToken assetToken = IAssetToken(IAssetFactory(factoryAddress).assetTokens(hedgeOrder.assetID));
require(!assetToken.rebalancing(), "asset token is rebalancing");
require(assetToken.feeCollected(), "asset token has fee not collected");
token = IERC20(address(assetToken));
} else {
token = IERC20(hedgeOrder.token);
require(hedgeOrder.vault != address(0), "vault is zero address");
require(getVaultRoute(hedgeOrder.requester) == hedgeOrder.vault, "vault not match");
}
setHedgeOrder(orderHash, hedgeOrder);
orderStatus[orderHash] = HedgeOrderStatus.PENDING;
requestTimestamps[orderHash] = block.timestamp;
mintPendingAmounts[address(token)] += hedgeOrder.inAmount;
require(token.allowance(hedgeOrder.requester, address(this)) >= hedgeOrder.inAmount, "not enough allowance");
token.safeTransferFrom(hedgeOrder.requester, address(this), hedgeOrder.inAmount);
emit ApplyMint(hedgeOrder);
}
// function cancelMint(bytes32 orderHash) external onlyRole(PARTICIPANT_ROLE) whenNotPaused {
// require(orderHashs.contains(orderHash), "order not exists");
// require(orderStatus[orderHash] == HedgeOrderStatus.PENDING, "order is not pending");
// require(requestTimestamps[orderHash] + MAX_MINT_DELAY <= block.timestamp, "not timeout");
// HedgeOrder storage hedgeOrder = hedgeOrders[orderHash];
// require(msg.sender == hedgeOrder.requester, "not requester");
// require(hedgeOrder.orderType == HedgeOrderType.MINT || hedgeOrder.orderType == HedgeOrderType.TOKEN_MINT, "order type not match");
// orderStatus[orderHash] = HedgeOrderStatus.CANCELED;
// IERC20 token;
// if (hedgeOrder.orderType == HedgeOrderType.MINT) {
// token = IERC20(IAssetFactory(factoryAddress).assetTokens(hedgeOrder.assetID));
// } else {
// token = IERC20(hedgeOrder.token);
// }
// mintPendingAmounts[address(token)] -= hedgeOrder.inAmount;
// token.safeTransfer(hedgeOrder.requester, hedgeOrder.inAmount);
// emit CancelMint(orderHash);
// }
function rejectMint(bytes32 orderHash) external onlyOwner {
require(orderHashs.contains(orderHash), "order not exists");
require(orderStatus[orderHash] == HedgeOrderStatus.PENDING, "order is not pending");
HedgeOrder storage hedgeOrder = hedgeOrders[orderHash];
require(hedgeOrder.orderType == HedgeOrderType.MINT || hedgeOrder.orderType == HedgeOrderType.TOKEN_MINT, "order type not match");
orderStatus[orderHash] = HedgeOrderStatus.REJECTED;
IERC20 token;
if (hedgeOrder.orderType == HedgeOrderType.MINT) {
token = IERC20(IAssetFactory(factoryAddress).assetTokens(hedgeOrder.assetID));
} else {
token = IERC20(hedgeOrder.token);
}
mintPendingAmounts[address(token)] -= hedgeOrder.inAmount;
token.safeTransfer(hedgeOrder.requester, hedgeOrder.inAmount);
emit RejectMint(orderHash);
}
function confirmMint(bytes32 orderHash) external onlyOwner {
require(orderHashs.contains(orderHash), "order not exists");
require(orderStatus[orderHash] == HedgeOrderStatus.PENDING, "order is not pending");
HedgeOrder storage hedgeOrder = hedgeOrders[orderHash];
require(hedgeOrder.orderType == HedgeOrderType.MINT || hedgeOrder.orderType == HedgeOrderType.TOKEN_MINT, "order type not match");
_mint(hedgeOrder.requester, hedgeOrder.outAmount);
orderStatus[orderHash] = HedgeOrderStatus.CONFIRMED;
if (hedgeOrder.orderType == HedgeOrderType.MINT) {
IERC20 assetToken = IERC20(IAssetFactory(factoryAddress).assetTokens(hedgeOrder.assetID));
IAssetIssuer issuer = IAssetIssuer(IAssetFactory(factoryAddress).issuers(hedgeOrder.assetID));
if (assetToken.allowance(address(this), address(issuer)) < hedgeOrder.inAmount) {
assetToken.forceApprove(address(issuer), hedgeOrder.inAmount);
}
issuer.burnFor(hedgeOrder.assetID, hedgeOrder.inAmount);
mintPendingAmounts[address(assetToken)] -= hedgeOrder.inAmount;
} else {
IERC20(hedgeOrder.token).safeTransfer(hedgeOrder.vault, hedgeOrder.inAmount);
mintPendingAmounts[hedgeOrder.token] -= hedgeOrder.inAmount;
}
emit ConfirmMint(orderHash);
}
function applyRedeem(HedgeOrder calldata hedgeOrder, bytes calldata orderSignature) external onlyRole(PARTICIPANT_ROLE) whenNotPaused {
require(hedgeOrder.requester == msg.sender, "msg sender is not requester");
bytes32 orderHash = keccak256(abi.encode(hedgeOrder));
checkHedgeOrder(hedgeOrder, orderHash, orderSignature);
require(hedgeOrder.orderType == HedgeOrderType.REDEEM, "order type not match");
require(allowance(hedgeOrder.requester, address(this)) >= hedgeOrder.inAmount, "not enough allowance");
setHedgeOrder(orderHash, hedgeOrder);
orderStatus[orderHash] = HedgeOrderStatus.PENDING;
requestTimestamps[orderHash] = block.timestamp;
redeemPendingAmounts[address(this)] += hedgeOrder.inAmount;
redeemPendingAmounts[hedgeOrder.redeemToken] += hedgeOrder.outAmount;
IERC20(address(this)).safeTransferFrom(hedgeOrder.requester, address(this), hedgeOrder.inAmount);
emit ApplyRedeem(hedgeOrder);
}
// function cancelRedeem(bytes32 orderHash) external onlyRole(PARTICIPANT_ROLE) whenNotPaused {
// require(orderHashs.contains(orderHash), "order not exists");
// require(orderStatus[orderHash] == HedgeOrderStatus.PENDING, "order is not pending");
// require(requestTimestamps[orderHash] + MAX_REDEEM_DELAY <= block.timestamp, "not timeout");
// HedgeOrder storage hedgeOrder = hedgeOrders[orderHash];
// require(msg.sender == hedgeOrder.requester, "not requester");
// require(hedgeOrder.orderType == HedgeOrderType.REDEEM, "order type not match");
// orderStatus[orderHash] = HedgeOrderStatus.CANCELED;
// redeemPendingAmounts[address(this)] -= hedgeOrder.inAmount;
// redeemPendingAmounts[hedgeOrder.redeemToken] -= hedgeOrder.outAmount;
// IERC20(address(this)).safeTransfer(hedgeOrder.requester, hedgeOrder.inAmount);
// emit CancelRedeem(orderHash);
// }
function rejectRedeem(bytes32 orderHash) external onlyOwner {
require(orderHashs.contains(orderHash), "order not exists");
require(orderStatus[orderHash] == HedgeOrderStatus.PENDING, "order is not pending");
HedgeOrder storage hedgeOrder = hedgeOrders[orderHash];
require(hedgeOrder.orderType == HedgeOrderType.REDEEM, "order type not match");
orderStatus[orderHash] = HedgeOrderStatus.REJECTED;
redeemPendingAmounts[address(this)] -= hedgeOrder.inAmount;
redeemPendingAmounts[hedgeOrder.redeemToken] -= hedgeOrder.outAmount;
IERC20(address(this)).safeTransfer(hedgeOrder.requester, hedgeOrder.inAmount);
emit RejectRedeem(orderHash);
}
function confirmRedeem(bytes32 orderHash, bytes32 txHash) external onlyOwner {
require(orderHashs.contains(orderHash), "order not exists");
require(orderStatus[orderHash] == HedgeOrderStatus.PENDING, "order is not pending");
HedgeOrder storage hedgeOrder = hedgeOrders[orderHash];
require(hedgeOrder.orderType == HedgeOrderType.REDEEM, "order type not match");
orderStatus[orderHash] = HedgeOrderStatus.CONFIRMED;
if (txHash == bytes32(0)) {
require(IERC20(hedgeOrder.redeemToken).balanceOf(address(this)) >= hedgeOrder.outAmount, "not enough redeem token");
IERC20(hedgeOrder.redeemToken).safeTransfer(hedgeOrder.requester, hedgeOrder.outAmount);
} else {
redeemTxHashs[orderHash] = txHash;
}
redeemPendingAmounts[address(this)] -= hedgeOrder.inAmount;
redeemPendingAmounts[hedgeOrder.redeemToken] -= hedgeOrder.outAmount;
_burn(address(this), hedgeOrder.inAmount);
emit ConfirmRedeem(orderHash);
}
function rescueToken(address token) external onlyOwner {
require(token != address(0), "token is zero address");
require(vault != address(0), "vault is zero address");
uint256 rescueAmount = IERC20(token).balanceOf(address(this));
require(rescueAmount > mintPendingAmounts[token] + redeemPendingAmounts[token], "nothing to rescue");
rescueAmount -= mintPendingAmounts[token] + redeemPendingAmounts[token];
IERC20(token).safeTransfer(vault, rescueAmount);
emit RescueToken(token, rescueAmount);
}
function getOrderHashs() external view returns (bytes32[] memory orderHashs_) {
orderHashs_ = new bytes32[](orderHashs.length());
for (uint i = 0; i < orderHashs.length(); i++) {
orderHashs_[i] = orderHashs.at(i);
}
}
function getOrderHashLength() external view returns (uint256) {
return orderHashs.length();
}
function getOrderHash(uint256 nonce) external view returns (bytes32) {
return orderHashs.at(nonce);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.25;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
import {IAccessControlEnumerable} from "@openzeppelin/contracts/access/extensions/IAccessControlEnumerable.sol";
struct Token {
string chain;
string symbol;
string addr;
uint8 decimals;
uint256 amount;
}
struct Asset {
uint256 id;
string name;
string symbol;
Token[] tokenset;
}
struct Order {
string chain;
address maker;
uint256 nonce;
Token[] inTokenset;
Token[] outTokenset;
string[] inAddressList;
string[] outAddressList;
uint256 inAmount;
uint256 outAmount;
uint256 deadline;
address requester;
}
struct OrderInfo {
Order order;
bytes32 orderHash;
bytes orderSign;
}
struct Range {
uint256 min;
uint256 max;
}
enum SwapRequestStatus {NONE, PENDING, MAKER_CONFIRMED, CONFIRMED, REJECTED, CANCEL, FORCE_CANCEL}
struct SwapRequest {
bytes[] inTxHashs;
bytes[] outTxHashs;
SwapRequestStatus status;
address requester;
bool inByContract;
bool outByContract;
uint256 blocknumber;
uint256 requestTimestamp;
}
enum RequestStatus {NONE, PENDING, CONFIRMED, REJECTED, CANCEL}
struct Request {
uint nonce;
address requester;
address assetTokenAddress;
uint amount;
address swapAddress;
bytes32 orderHash;
RequestStatus status;
uint requestTimestamp;
uint issueFee;
}
interface IAssetToken is IERC20, IAccessControl {
function decimals() external view returns (uint8);
// id
function id() external returns (uint256);
// roles
function ISSUER_ROLE() external returns (bytes32);
function REBALANCER_ROLE() external returns (bytes32);
function FEEMANAGER_ROLE() external returns (bytes32);
// tokenset
function getTokenset() external view returns (Token[] memory);
function initTokenset(Token[] memory tokenset) external;
function getBasket() external view returns (Token[] memory);
// issue
function lockIssue() external;
function issuing() external view returns (bool);
function unlockIssue() external;
function mint(address account, uint amount) external;
function burn(uint amount) external;
// rebalance
function lockRebalance() external;
function rebalancing() external view returns (bool);
function unlockRebalance() external;
function rebalance(Token[] memory inBasket, Token[] memory outBasket) external;
// fee
function feeDecimals() external view returns (uint);
function maxFee() external view returns (uint);
function fee() external view returns (uint);
function setFee(uint fee_) external;
function lastCollectTimestamp() external view returns (uint);
function feeCollected() external view returns (bool);
function getFeeTokenset() external view returns (Token[] memory);
function collectFeeTokenset() external;
function lockBurnFee() external;
function burningFee() external view returns (bool);
function unlockBurnFee() external;
function burnFeeTokenset(Token[] memory feeTokenset) external;
}
interface IAssetFactory {
function vault() external view returns (address);
function chain() external view returns (string memory);
// asset tokens
function createAssetToken(Asset memory asset, uint maxFee, address issuer, address rebalancer, address feeMamanger, address swap) external returns (address);
function assetTokens(uint assetID) external view returns (address);
function hasAssetID(uint assetID) external view returns (bool);
function getAssetIDs() external view returns (uint[] memory);
function issuers(uint assetID) external view returns (address);
function rebalancers(uint assetID) external view returns (address);
function feeManagers(uint assetID) external view returns (address);
function swaps(uint assetID) external view returns (address);
}
interface ISwap is IAccessControl {
function TAKER_ROLE() external returns (bytes32);
function MAKER_ROLE() external returns (bytes32);
function checkOrderInfo(OrderInfo memory orderInfo) external view returns (uint);
function getOrderHashs() external view returns (bytes32[] memory);
function getOrderHashLength() external view returns (uint256);
function getOrderHash(uint256 idx) external view returns (bytes32);
function getSwapRequest(bytes32 orderHash) external view returns (SwapRequest memory);
function addSwapRequest(OrderInfo memory orderInfo, bool inByContract, bool outByContract) external;
function makerConfirmSwapRequest(OrderInfo memory orderInfo, bytes[] memory outTxHashs) external;
function makerRejectSwapRequest(OrderInfo memory orderInfo) external;
function rollbackSwapRequest(OrderInfo memory orderInfo) external;
function cancelSwapRequest(OrderInfo memory orderInfo) external;
function confirmSwapRequest(OrderInfo memory orderInfo, bytes[] memory inTxHashs) external;
function setTakerAddresses(string[] memory takerReceivers_, string[] memory takerSenders_) external;
function getTakerAddresses() external view returns (string[] memory receivers, string[] memory senders);
function getWhiteListTokens() external view returns (Token[] memory tokens);
}
interface IAssetController {
function factoryAddress() external returns (address);
}
interface IAssetIssuer is IAssetController {
// mint
function getMintRequestLength() external view returns (uint256);
function getMintRequest(uint256 nonce) external view returns (Request memory);
function addMintRequest(uint256 assetID, OrderInfo memory orderInfo, uint256 maxIssueFee) external returns (uint);
function rejectMintRequest(uint256 nonce, OrderInfo memory orderInfo, bool force) external;
function confirmMintRequest(uint nonce, OrderInfo memory orderInfo, bytes[] memory inTxHashs) external;
// redeem
function getRedeemRequestLength() external view returns (uint256);
function getRedeemRequest(uint256 nonce) external view returns (Request memory);
function addRedeemRequest(uint256 assetID, OrderInfo memory orderInfo, uint256 maxIssueFee) external returns (uint256);
function rejectRedeemRequest(uint256 nonce) external;
function confirmRedeemRequest(uint nonce, OrderInfo memory orderInfo, bytes[] memory inTxHashs, bool force) external;
// manage participants
function isParticipant(uint256 assetID, address participant) external view returns (bool);
function getParticipants(uint256 assetID) external view returns (address[] memory);
function getParticipantLength(uint256 assetID) external view returns (uint256);
function getParticipant(uint256 assetID, uint256 idx) external view returns (address);
function addParticipant(uint256 assetID, address participant) external;
function removeParticipant(uint256 assetID, address participant) external;
// fee
function setIssueFee(uint256 assetID, uint256 issueFee) external;
function getIssueFee(uint256 assetID) external view returns (uint256);
function feeDecimals() external view returns (uint256);
// issue amount range
function getIssueAmountRange(uint256 assetID) external view returns (Range memory);
function setIssueAmountRange(uint256 assetID, Range calldata issueAmountRange) external;
// burn for
function burnFor(uint256 assetID, uint256 amount) external;
}
interface IAssetRebalancer is IAssetController {
function getRebalanceRequestLength() external view returns (uint256);
function getRebalanceRequest(uint256 nonce) external view returns (Request memory);
function addRebalanceRequest(uint256 assetID, Token[] memory basket, OrderInfo memory orderInfo) external returns (uint256);
function rejectRebalanceRequest(uint256 nonce) external;
function confirmRebalanceRequest(uint nonce, OrderInfo memory orderInfo, bytes[] memory inTxHashs) external;
}
interface IAssetFeeManager is IAssetController {
function setFee(uint256 assetID, uint256 fee) external;
function collectFeeTokenset(uint256 assetID) external;
function getBurnFeeRequestLength() external view returns (uint256);
function getBurnFeeRequest(uint256 nonce) external view returns (Request memory);
function addBurnFeeRequest(uint256 assetID, OrderInfo memory orderInfo) external returns (uint256);
function rejectBurnFeeRequest(uint256 nonce) external;
function confirmBurnFeeRequest(uint nonce, OrderInfo memory orderInfo, bytes[] memory inTxHashs) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC-20
* applications.
*/
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
mapping(address account => uint256) private _balances;
mapping(address account => mapping(address spender => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `value`.
*/
function transfer(address to, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_transfer(owner, to, value);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, value);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Skips emitting an {Approval} event indicating an allowance update. This is not
* required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `value`.
* - the caller must have allowance for ``from``'s tokens of at least
* `value`.
*/
function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, value);
_transfer(from, to, value);
return true;
}
/**
* @dev Moves a `value` amount of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _transfer(address from, address to, uint256 value) internal {
if (from == address(0)) {
revert ERC20InvalidSender(address(0));
}
if (to == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(from, to, value);
}
/**
* @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
* (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
* this function.
*
* Emits a {Transfer} event.
*/
function _update(address from, address to, uint256 value) internal virtual {
if (from == address(0)) {
// Overflow check required: The rest of the code assumes that totalSupply never overflows
_totalSupply += value;
} else {
uint256 fromBalance = _balances[from];
if (fromBalance < value) {
revert ERC20InsufficientBalance(from, fromBalance, value);
}
unchecked {
// Overflow not possible: value <= fromBalance <= totalSupply.
_balances[from] = fromBalance - value;
}
}
if (to == address(0)) {
unchecked {
// Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
_totalSupply -= value;
}
} else {
unchecked {
// Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
_balances[to] += value;
}
}
emit Transfer(from, to, value);
}
/**
* @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
* Relies on the `_update` mechanism
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _mint(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(address(0), account, value);
}
/**
* @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
* Relies on the `_update` mechanism.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead
*/
function _burn(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidSender(address(0));
}
_update(account, address(0), value);
}
/**
* @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address owner, address spender, uint256 value) internal {
_approve(owner, spender, value, true);
}
/**
* @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
*
* By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
* `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
* `Approval` event during `transferFrom` operations.
*
* Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
* true using the following override:
*
* ```solidity
* function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
* super._approve(owner, spender, value, true);
* }
* ```
*
* Requirements are the same as {_approve}.
*/
function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
if (owner == address(0)) {
revert ERC20InvalidApprover(address(0));
}
if (spender == address(0)) {
revert ERC20InvalidSpender(address(0));
}
_allowances[owner][spender] = value;
if (emitEvent) {
emit Approval(owner, spender, value);
}
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `value`.
*
* Does not update the allowance value in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Does not emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance < type(uint256).max) {
if (currentAllowance < value) {
revert ERC20InsufficientAllowance(spender, currentAllowance, value);
}
unchecked {
_approve(owner, spender, currentAllowance - value, false);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC-20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.20;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position is the index of the value in the `values` array plus 1.
// Position 0 is used to mean a value is not in the set.
mapping(bytes32 value => uint256) _positions;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._positions[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We cache the value's position to prevent multiple reads from the same storage slot
uint256 position = set._positions[value];
if (position != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 valueIndex = position - 1;
uint256 lastIndex = set._values.length - 1;
if (valueIndex != lastIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the lastValue to the index where the value to delete is
set._values[valueIndex] = lastValue;
// Update the tracked position of the lastValue (that was just moved)
set._positions[lastValue] = position;
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the tracked position for the deleted slot
delete set._positions[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._positions[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
assembly ("memory-safe") {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly ("memory-safe") {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly ("memory-safe") {
result := store
}
return result;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/SignatureChecker.sol)
pragma solidity ^0.8.20;
import {ECDSA} from "./ECDSA.sol";
import {IERC1271} from "../../interfaces/IERC1271.sol";
/**
* @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA
* signatures from externally owned accounts (EOAs) as well as ERC-1271 signatures from smart contract wallets like
* Argent and Safe Wallet (previously Gnosis Safe).
*/
library SignatureChecker {
/**
* @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the
* signature is validated against that smart contract using ERC-1271, otherwise it's validated using `ECDSA.recover`.
*
* NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
* change through time. It could return true at block N and false at block N+1 (or the opposite).
*/
function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {
if (signer.code.length == 0) {
(address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecover(hash, signature);
return err == ECDSA.RecoverError.NoError && recovered == signer;
} else {
return isValidERC1271SignatureNow(signer, hash, signature);
}
}
/**
* @dev Checks if a signature is valid for a given signer and data hash. The signature is validated
* against the signer smart contract using ERC-1271.
*
* NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
* change through time. It could return true at block N and false at block N+1 (or the opposite).
*/
function isValidERC1271SignatureNow(
address signer,
bytes32 hash,
bytes memory signature
) internal view returns (bool) {
(bool success, bytes memory result) = signer.staticcall(
abi.encodeCall(IERC1271.isValidSignature, (hash, signature))
);
return (success &&
result.length >= 32 &&
abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)
pragma solidity ^0.8.20;
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {ERC165Upgradeable} from "../utils/introspection/ERC165Upgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControl, ERC165Upgradeable {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/// @custom:storage-location erc7201:openzeppelin.storage.AccessControl
struct AccessControlStorage {
mapping(bytes32 role => RoleData) _roles;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.AccessControl")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant AccessControlStorageLocation = 0x02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800;
function _getAccessControlStorage() private pure returns (AccessControlStorage storage $) {
assembly {
$.slot := AccessControlStorageLocation
}
}
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
function __AccessControl_init() internal onlyInitializing {
}
function __AccessControl_init_unchained() internal onlyInitializing {
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
AccessControlStorage storage $ = _getAccessControlStorage();
return $._roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
AccessControlStorage storage $ = _getAccessControlStorage();
return $._roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
AccessControlStorage storage $ = _getAccessControlStorage();
bytes32 previousAdminRole = getRoleAdmin(role);
$._roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
AccessControlStorage storage $ = _getAccessControlStorage();
if (!hasRole(role, account)) {
$._roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
/**
* @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
AccessControlStorage storage $ = _getAccessControlStorage();
if (hasRole(role, account)) {
$._roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
/// @custom:storage-location erc7201:openzeppelin.storage.Ownable
struct OwnableStorage {
address _owner;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;
function _getOwnableStorage() private pure returns (OwnableStorage storage $) {
assembly {
$.slot := OwnableStorageLocation
}
}
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
function __Ownable_init(address initialOwner) internal onlyInitializing {
__Ownable_init_unchained(initialOwner);
}
function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
OwnableStorage storage $ = _getOwnableStorage();
return $._owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
OwnableStorage storage $ = _getOwnableStorage();
address oldOwner = $._owner;
$._owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {ContextUpgradeable} from "../../utils/ContextUpgradeable.sol";
import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC-20
* applications.
*/
abstract contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors {
/// @custom:storage-location erc7201:openzeppelin.storage.ERC20
struct ERC20Storage {
mapping(address account => uint256) _balances;
mapping(address account => mapping(address spender => uint256)) _allowances;
uint256 _totalSupply;
string _name;
string _symbol;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC20")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00;
function _getERC20Storage() private pure returns (ERC20Storage storage $) {
assembly {
$.slot := ERC20StorageLocation
}
}
/**
* @dev Sets the values for {name} and {symbol}.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {
__ERC20_init_unchained(name_, symbol_);
}
function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {
ERC20Storage storage $ = _getERC20Storage();
$._name = name_;
$._symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
ERC20Storage storage $ = _getERC20Storage();
return $._name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
ERC20Storage storage $ = _getERC20Storage();
return $._symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
ERC20Storage storage $ = _getERC20Storage();
return $._totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual returns (uint256) {
ERC20Storage storage $ = _getERC20Storage();
return $._balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `value`.
*/
function transfer(address to, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_transfer(owner, to, value);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual returns (uint256) {
ERC20Storage storage $ = _getERC20Storage();
return $._allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, value);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Skips emitting an {Approval} event indicating an allowance update. This is not
* required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `value`.
* - the caller must have allowance for ``from``'s tokens of at least
* `value`.
*/
function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, value);
_transfer(from, to, value);
return true;
}
/**
* @dev Moves a `value` amount of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _transfer(address from, address to, uint256 value) internal {
if (from == address(0)) {
revert ERC20InvalidSender(address(0));
}
if (to == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(from, to, value);
}
/**
* @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
* (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
* this function.
*
* Emits a {Transfer} event.
*/
function _update(address from, address to, uint256 value) internal virtual {
ERC20Storage storage $ = _getERC20Storage();
if (from == address(0)) {
// Overflow check required: The rest of the code assumes that totalSupply never overflows
$._totalSupply += value;
} else {
uint256 fromBalance = $._balances[from];
if (fromBalance < value) {
revert ERC20InsufficientBalance(from, fromBalance, value);
}
unchecked {
// Overflow not possible: value <= fromBalance <= totalSupply.
$._balances[from] = fromBalance - value;
}
}
if (to == address(0)) {
unchecked {
// Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
$._totalSupply -= value;
}
} else {
unchecked {
// Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
$._balances[to] += value;
}
}
emit Transfer(from, to, value);
}
/**
* @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
* Relies on the `_update` mechanism
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _mint(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(address(0), account, value);
}
/**
* @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
* Relies on the `_update` mechanism.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead
*/
function _burn(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidSender(address(0));
}
_update(account, address(0), value);
}
/**
* @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address owner, address spender, uint256 value) internal {
_approve(owner, spender, value, true);
}
/**
* @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
*
* By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
* `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
* `Approval` event during `transferFrom` operations.
*
* Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
* true using the following override:
*
* ```solidity
* function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
* super._approve(owner, spender, value, true);
* }
* ```
*
* Requirements are the same as {_approve}.
*/
function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
ERC20Storage storage $ = _getERC20Storage();
if (owner == address(0)) {
revert ERC20InvalidApprover(address(0));
}
if (spender == address(0)) {
revert ERC20InvalidSpender(address(0));
}
$._allowances[owner][spender] = value;
if (emitEvent) {
emit Approval(owner, spender, value);
}
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `value`.
*
* Does not update the allowance value in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Does not emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance < type(uint256).max) {
if (currentAllowance < value) {
revert ERC20InsufficientAllowance(spender, currentAllowance, value);
}
unchecked {
_approve(owner, spender, currentAllowance - value, false);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.20;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Storage of the initializable contract.
*
* It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
* when using with upgradeable contracts.
*
* @custom:storage-location erc7201:openzeppelin.storage.Initializable
*/
struct InitializableStorage {
/**
* @dev Indicates that the contract has been initialized.
*/
uint64 _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
/**
* @dev The contract is already initialized.
*/
error InvalidInitialization();
/**
* @dev The contract is not initializing.
*/
error NotInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint64 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
* number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
* production.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
// Cache values to avoid duplicated sloads
bool isTopLevelCall = !$._initializing;
uint64 initialized = $._initialized;
// Allowed calls:
// - initialSetup: the contract is not in the initializing state and no previous version was
// initialized
// - construction: the contract is initialized at version 1 (no reininitialization) and the
// current contract is just being deployed
bool initialSetup = initialized == 0 && isTopLevelCall;
bool construction = initialized == 1 && address(this).code.length == 0;
if (!initialSetup && !construction) {
revert InvalidInitialization();
}
$._initialized = 1;
if (isTopLevelCall) {
$._initializing = true;
}
_;
if (isTopLevelCall) {
$._initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint64 version) {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing || $._initialized >= version) {
revert InvalidInitialization();
}
$._initialized = version;
$._initializing = true;
_;
$._initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
_checkInitializing();
_;
}
/**
* @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
*/
function _checkInitializing() internal view virtual {
if (!_isInitializing()) {
revert NotInitializing();
}
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing) {
revert InvalidInitialization();
}
if ($._initialized != type(uint64).max) {
$._initialized = type(uint64).max;
emit Initialized(type(uint64).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint64) {
return _getInitializableStorage()._initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _getInitializableStorage()._initializing;
}
/**
* @dev Returns a pointer to the storage namespace.
*/
// solhint-disable-next-line var-name-mixedcase
function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
assembly {
$.slot := INITIALIZABLE_STORAGE
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.22;
import {IERC1822Proxiable} from "@openzeppelin/contracts/interfaces/draft-IERC1822.sol";
import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol";
import {Initializable} from "./Initializable.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.
*/
abstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address private immutable __self = address(this);
/**
* @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`
* and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,
* while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.
* If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must
* be the empty byte string if no function should be called, making it impossible to invoke the `receive` function
* during an upgrade.
*/
string public constant UPGRADE_INTERFACE_VERSION = "5.0.0";
/**
* @dev The call is from an unauthorized context.
*/
error UUPSUnauthorizedCallContext();
/**
* @dev The storage `slot` is unsupported as a UUID.
*/
error UUPSUnsupportedProxiableUUID(bytes32 slot);
/**
* @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 ERC-1967) 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 ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
_checkProxy();
_;
}
/**
* @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() {
_checkNotDelegated();
_;
}
function __UUPSUpgradeable_init() internal onlyInitializing {
}
function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
}
/**
* @dev Implementation of the ERC-1822 {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 notDelegated returns (bytes32) {
return ERC1967Utils.IMPLEMENTATION_SLOT;
}
/**
* @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);
}
/**
* @dev Reverts if the execution is not performed via delegatecall or the execution
* context is not of a proxy with an ERC-1967 compliant implementation pointing to self.
* See {_onlyProxy}.
*/
function _checkProxy() internal view virtual {
if (
address(this) == __self || // Must be called through delegatecall
ERC1967Utils.getImplementation() != __self // Must be called through an active proxy
) {
revert UUPSUnauthorizedCallContext();
}
}
/**
* @dev Reverts if the execution is performed via delegatecall.
* See {notDelegated}.
*/
function _checkNotDelegated() internal view virtual {
if (address(this) != __self) {
// Must not be called through delegatecall
revert UUPSUnauthorizedCallContext();
}
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
/**
* @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.
*
* As a security check, {proxiableUUID} is invoked in the new implementation, and the return value
* is expected to be the implementation slot in ERC-1967.
*
* Emits an {IERC1967-Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {
revert UUPSUnsupportedProxiableUUID(slot);
}
ERC1967Utils.upgradeToAndCall(newImplementation, data);
} catch {
// The implementation is not UUPS
revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)
pragma solidity ^0.8.20;
import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.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 PausableUpgradeable is Initializable, ContextUpgradeable {
/// @custom:storage-location erc7201:openzeppelin.storage.Pausable
struct PausableStorage {
bool _paused;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Pausable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300;
function _getPausableStorage() private pure returns (PausableStorage storage $) {
assembly {
$.slot := PausableStorageLocation
}
}
/**
* @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);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @dev Initializes the contract in unpaused state.
*/
function __Pausable_init() internal onlyInitializing {
__Pausable_init_unchained();
}
function __Pausable_init_unchained() internal onlyInitializing {
PausableStorage storage $ = _getPausableStorage();
$._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) {
PausableStorage storage $ = _getPausableStorage();
return $._paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
PausableStorage storage $ = _getPausableStorage();
$._paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
PausableStorage storage $ = _getPausableStorage();
$._paused = false;
emit Unpaused(_msgSender());
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol)
pragma solidity ^0.8.20;
/**
* @dev External interface of AccessControl declared to support ERC-165 detection.
*/
interface IAccessControl {
/**
* @dev The `account` is missing a role.
*/
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/
error AccessControlBadConfirmation();
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).
* Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (access/extensions/IAccessControlEnumerable.sol)
pragma solidity ^0.8.20;
import {IAccessControl} from "../IAccessControl.sol";
/**
* @dev External interface of AccessControlEnumerable declared to support ERC-165 detection.
*/
interface IAccessControlEnumerable is IAccessControl {
/**
* @dev Returns one of the accounts that have `role`. `index` must be a
* value between 0 and {getRoleMemberCount}, non-inclusive.
*
* Role bearers are not sorted in any particular way, and their ordering may
* change at any point.
*
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
* you perform all queries on the same block. See the following
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
* for more information.
*/
function getRoleMember(bytes32 role, uint256 index) external view returns (address);
/**
* @dev Returns the number of accounts that have `role`. Can be used
* together with {getRoleMember} to enumerate all bearers of a role.
*/
function getRoleMemberCount(bytes32 role) external view returns (uint256);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard ERC-20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC-721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC-1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.20;
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS
}
/**
* @dev The signature derives the `address(0)`.
*/
error ECDSAInvalidSignature();
/**
* @dev The signature has an invalid length.
*/
error ECDSAInvalidSignatureLength(uint256 length);
/**
* @dev The signature has an S value that is in the upper half order.
*/
error ECDSAInvalidSignatureS(bytes32 s);
/**
* @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
* return address(0) without also returning an error description. Errors are documented using an enum (error type)
* and a bytes32 providing additional information about the error.
*
* If no error is returned, then the address can be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*/
function tryRecover(
bytes32 hash,
bytes memory signature
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly ("memory-safe") {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures]
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
unchecked {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
// We do not check for an overflow here since the shift operation results in 0 or 1.
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*/
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS, s);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature, bytes32(0));
}
return (signer, RecoverError.NoError, bytes32(0));
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
*/
function _throwError(RecoverError error, bytes32 errorArg) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert ECDSAInvalidSignature();
} else if (error == RecoverError.InvalidSignatureLength) {
revert ECDSAInvalidSignatureLength(uint256(errorArg));
} else if (error == RecoverError.InvalidSignatureS) {
revert ECDSAInvalidSignatureS(errorArg);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1271.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-1271 standard signature validation method for
* contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
*/
interface IERC1271 {
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param hash Hash of the data to be signed
* @param signature Signature byte array associated with _data
*/
function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165Upgradeable is Initializable, IERC165 {
function __ERC165_init() internal onlyInitializing {
}
function __ERC165_init_unchained() internal onlyInitializing {
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.20;
/**
* @dev ERC-1822: 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 v5.1.0) (proxy/ERC1967/ERC1967Utils.sol)
pragma solidity ^0.8.22;
import {IBeacon} from "../beacon/IBeacon.sol";
import {IERC1967} from "../../interfaces/IERC1967.sol";
import {Address} from "../../utils/Address.sol";
import {StorageSlot} from "../../utils/StorageSlot.sol";
/**
* @dev This library provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.
*/
library ERC1967Utils {
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1.
*/
// solhint-disable-next-line private-vars-leading-underscore
bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev The `implementation` of the proxy is invalid.
*/
error ERC1967InvalidImplementation(address implementation);
/**
* @dev The `admin` of the proxy is invalid.
*/
error ERC1967InvalidAdmin(address admin);
/**
* @dev The `beacon` of the proxy is invalid.
*/
error ERC1967InvalidBeacon(address beacon);
/**
* @dev An upgrade function sees `msg.value > 0` that may be lost.
*/
error ERC1967NonPayable();
/**
* @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 ERC-1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
if (newImplementation.code.length == 0) {
revert ERC1967InvalidImplementation(newImplementation);
}
StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Performs implementation upgrade with additional setup call if data is nonempty.
* This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
* to avoid stuck value in the contract.
*
* Emits an {IERC1967-Upgraded} event.
*/
function upgradeToAndCall(address newImplementation, bytes memory data) internal {
_setImplementation(newImplementation);
emit IERC1967.Upgraded(newImplementation);
if (data.length > 0) {
Address.functionDelegateCall(newImplementation, data);
} else {
_checkNonPayable();
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1.
*/
// solhint-disable-next-line private-vars-leading-underscore
bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*
* TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using
* the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
* `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
*/
function getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the ERC-1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
if (newAdmin == address(0)) {
revert ERC1967InvalidAdmin(address(0));
}
StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {IERC1967-AdminChanged} event.
*/
function changeAdmin(address newAdmin) internal {
emit IERC1967.AdminChanged(getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1.
*/
// solhint-disable-next-line private-vars-leading-underscore
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 ERC-1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
if (newBeacon.code.length == 0) {
revert ERC1967InvalidBeacon(newBeacon);
}
StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;
address beaconImplementation = IBeacon(newBeacon).implementation();
if (beaconImplementation.code.length == 0) {
revert ERC1967InvalidImplementation(beaconImplementation);
}
}
/**
* @dev Change the beacon and trigger a setup call if data is nonempty.
* This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
* to avoid stuck value in the contract.
*
* Emits an {IERC1967-BeaconUpgraded} event.
*
* CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since
* it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for
* efficiency.
*/
function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {
_setBeacon(newBeacon);
emit IERC1967.BeaconUpgraded(newBeacon);
if (data.length > 0) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
} else {
_checkNonPayable();
}
}
/**
* @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract
* if an upgrade doesn't perform an initialization call.
*/
function _checkNonPayable() private {
if (msg.value > 0) {
revert ERC1967NonPayable();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.20;
/**
* @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.
*
* {UpgradeableBeacon} will check that this address is a contract.
*/
function implementation() external view returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)
pragma solidity ^0.8.20;
/**
* @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
*/
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 (last updated v5.1.0) (utils/Address.sol)
pragma solidity ^0.8.20;
import {Errors} from "./Errors.sol";
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert Errors.InsufficientBalance(address(this).balance, amount);
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert Errors.FailedCall();
}
}
/**
* @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 or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {Errors.FailedCall} error.
*
* 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.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @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`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
* of an unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {Errors.FailedCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.
*/
function _revert(bytes memory returndata) 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
assembly ("memory-safe") {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert Errors.FailedCall();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.20;
/**
* @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 ERC-1967 implementation slot:
* ```solidity
* contract ERC1967 {
* // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(newImplementation.code.length > 0);
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* TIP: Consider using this library along with {SlotDerivation}.
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct Int256Slot {
int256 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) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Int256Slot` with member `value` located at `slot`.
*/
function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
assembly ("memory-safe") {
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) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
/**
* @dev Returns a `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
assembly ("memory-safe") {
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) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of common custom errors used in multiple contracts
*
* IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
* It is recommended to avoid relying on the error API for critical functionality.
*
* _Available since v5.1._
*/
library Errors {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error InsufficientBalance(uint256 balance, uint256 needed);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedCall();
/**
* @dev The deployment failed.
*/
error FailedDeployment();
/**
* @dev A necessary precompile is missing.
*/
error MissingPrecompile(address);
}{
"remappings": [
"forge-std/=lib/forge-std/src/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"ds-test/=lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
"openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/",
"solidity-stringutils/=lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": true,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"assetID","type":"uint256"}],"name":"AddAssetID","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"AddToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"requester","type":"address"},{"indexed":false,"internalType":"address","name":"vault","type":"address"}],"name":"AddVaultRoute","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"string","name":"chain","type":"string"},{"internalType":"enum USSI.HedgeOrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"assetID","type":"uint256"},{"internalType":"address","name":"redeemToken","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"inAmount","type":"uint256"},{"internalType":"uint256","name":"outAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"requester","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"vault","type":"address"}],"indexed":false,"internalType":"struct USSI.HedgeOrder","name":"hedgeOrder","type":"tuple"}],"name":"ApplyMint","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"string","name":"chain","type":"string"},{"internalType":"enum USSI.HedgeOrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"assetID","type":"uint256"},{"internalType":"address","name":"redeemToken","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"inAmount","type":"uint256"},{"internalType":"uint256","name":"outAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"requester","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"vault","type":"address"}],"indexed":false,"internalType":"struct USSI.HedgeOrder","name":"hedgeOrder","type":"tuple"}],"name":"ApplyRedeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"CancelMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"CancelRedeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"ConfirmMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"ConfirmRedeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"RejectMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"RejectRedeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"assetID","type":"uint256"}],"name":"RemoveAssetID","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"RemoveToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"requester","type":"address"}],"name":"RemoveVaultRoute","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RescueToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOrderSigner","type":"address"},{"indexed":false,"internalType":"address","name":"orderSigner","type":"address"}],"name":"UpdateOrderSigner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldRedeemToken","type":"address"},{"indexed":false,"internalType":"address","name":"redeemToken","type":"address"}],"name":"UpdateRedeemToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldVault","type":"address"},{"indexed":false,"internalType":"address","name":"vault","type":"address"}],"name":"UpdateVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_MINT_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_REDEEM_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PARTICIPANT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetID","type":"uint256"}],"name":"addSupportAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"addSupportToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"},{"internalType":"address","name":"vault_","type":"address"}],"name":"addVaultRoute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"chain","type":"string"},{"internalType":"enum USSI.HedgeOrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"assetID","type":"uint256"},{"internalType":"address","name":"redeemToken","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"inAmount","type":"uint256"},{"internalType":"uint256","name":"outAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"requester","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"vault","type":"address"}],"internalType":"struct USSI.HedgeOrder","name":"hedgeOrder","type":"tuple"},{"internalType":"bytes","name":"orderSignature","type":"bytes"}],"name":"applyMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"chain","type":"string"},{"internalType":"enum USSI.HedgeOrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"assetID","type":"uint256"},{"internalType":"address","name":"redeemToken","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"inAmount","type":"uint256"},{"internalType":"uint256","name":"outAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"requester","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"vault","type":"address"}],"internalType":"struct USSI.HedgeOrder","name":"hedgeOrder","type":"tuple"},{"internalType":"bytes","name":"orderSignature","type":"bytes"}],"name":"applyRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chain","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"chain","type":"string"},{"internalType":"enum USSI.HedgeOrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"assetID","type":"uint256"},{"internalType":"address","name":"redeemToken","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"inAmount","type":"uint256"},{"internalType":"uint256","name":"outAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"requester","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"vault","type":"address"}],"internalType":"struct USSI.HedgeOrder","name":"hedgeOrder","type":"tuple"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"bytes","name":"orderSignature","type":"bytes"}],"name":"checkHedgeOrder","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"confirmMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"bytes32","name":"txHash","type":"bytes32"}],"name":"confirmRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"factoryAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"getOrderHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOrderHashLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOrderHashs","outputs":[{"internalType":"bytes32[]","name":"orderHashs_","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSupportAssetIDs","outputs":[{"internalType":"uint256[]","name":"assetIDs","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSupportTokens","outputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"}],"name":"getVaultRoute","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVaultRoutes","outputs":[{"internalType":"address[]","name":"requesters","type":"address[]"},{"internalType":"address[]","name":"vaults","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"hedgeOrders","outputs":[{"internalType":"string","name":"chain","type":"string"},{"internalType":"enum USSI.HedgeOrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"assetID","type":"uint256"},{"internalType":"address","name":"redeemToken","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"inAmount","type":"uint256"},{"internalType":"uint256","name":"outAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"requester","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"vault","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"orderSigner_","type":"address"},{"internalType":"address","name":"factoryAddress_","type":"address"},{"internalType":"address","name":"redeemToken_","type":"address"},{"internalType":"string","name":"chain_","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mintPendingAmounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"orderSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"orderStatus","outputs":[{"internalType":"enum USSI.HedgeOrderStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"redeemPendingAmounts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redeemToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"redeemTxHashs","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"rejectMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"rejectRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assetID","type":"uint256"}],"name":"removeSupportAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"removeSupportToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"requester","type":"address"}],"name":"removeVaultRoute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requestTimestamps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"rescueToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"orderSigner_","type":"address"}],"name":"updateOrderSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"redeemToken_","type":"address"}],"name":"updateRedeemToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault_","type":"address"}],"name":"updateVault","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":"vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"vaultRoutes","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60a080604052346100c257306080525f5160206151bd5f395f51905f525460ff8160401c166100b3576002600160401b03196001600160401b03821601610060575b6040516150f690816100c78239608051818181611ff501526120970152f35b6001600160401b0319166001600160401b039081175f5160206151bd5f395f51905f525581527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a15f80610041565b63f92ee8a960e01b5f5260045ffd5b5f80fdfe6080806040526004361015610012575f80fd5b5f905f3560e01c90816301ffc9a7146136d45750806305e0a9b5146136b857806306fdde03146135d6578063081a1a50146135b9578063095ea7b31461353a57806310a255ce1461327a57806318160ddd146132515780631c68bf00146131985780631e3a915f1461308b57806323b872dd14612fb3578063248a9ca314612f74578063256ea64514612e895780632af03d7814612db05780632dff692d14612d7a5780632f2ff15d14612d305780632f310bad14612d085780632fb3b3611461259e578063313ce5671461258357806336568abe1461253f57806339cdfb2b1461249e5780633f4ba83a14612420578063437f2e61146123f65780634460d3cf146122695780634e60cd14146122295780634f1ef2861461204957806352d1902d14611fe357806353c34f0214611ec55780635c975abb14611e975780635f8a7abe14611e5d5780636f6f990014611d5357806370a0823114611d0f578063715018a614611ca857806371bbd15014611bd657806377c4accf14611b9e5780637d941f7914611b6e5780637df6d891146116ca5780638456cb59146116575780638da5cb5b1461162257806391d14854146115cc57806393d82de71461151157806395d89b411461142a578063966dae0e14611401578063998fccc5146112035780639c4c82aa146111ca578063a0a0036014611160578063a217fddf14611144578063a9059cbb14611112578063ad3cb1cc146110c9578063b4c081b814610f4a578063b9f0d68e14610f1c578063c06f8e3714610dfa578063c33bb25614610c95578063c5a5666414610c77578063c5e0e0cf14610b5c578063c763e5a114610b19578063d547741f14610ac5578063dd62ed3e14610a7d578063ddd6c72a14610a53578063e2769cfa1461098d578063e477a571146108da578063e7563f3f14610805578063ec2fe14a1461036a578063f299f8b314610341578063f2fde38b146103145763fbfa77cf146102e9575f80fd5b34610311578060031936011261031157600e546040516001600160a01b039091168152602090f35b80fd5b50346103115760203660031901126103115761033e61033161374b565b6103396142c7565b614256565b80f35b50346103115780600319360112610311576008546040516001600160a01b039091168152602090f35b5034610311576103793661397f565b91906103836143fb565b61038b61475b565b6103df6101008301936103b06103a086613cdf565b6001600160a01b031633146140a3565b60405160208101906103d4816103c688856140ef565b03601f19810183528261378b565b519020928385613cf3565b6020820135600481101590816107ec576103f881613975565b60018114918280156107f0575b61040e90613a54565b6107ec5761041b90613975565b1561074757600954604080516373bacc5b60e01b815290840135600482015290602090829060249082906001600160a01b03165afa90811561073c57859161070d575b5060405163959b13d960e01b81526001600160a01b039190911690602081600481855afa9081156106205786916106ee575b506106a957604051631b29fe5760e21b8152602081600481855afa90811561062057869161067a575b501561062b57905b6104cb8382614782565b808552600360205260408520600160ff198254161790558452600460205242604085205560a082013590610556602060018060a01b0383168088526012825260408820610519868254613c16565b905561052487613cdf565b604051636eb1769f60e11b81526001600160a01b03909116600482015230602482015292839190829081906044820190565b03915afa9081156106205786916105c2575b50917f51433b4a579ebe26ed2ca605218d3d56d316d7198fecfe7cf02ece121e58ca5b946105b0926105a0836105bc97961015614213565b6105aa3092613cdf565b906149e6565b604051918291826140ef565b0390a180f35b91939290506020823d602011610618575b816105e06020938361378b565b81010312610614579051919290917f51433b4a579ebe26ed2ca605218d3d56d316d7198fecfe7cf02ece121e58ca5b610568565b5f80fd5b3d91506105d3565b6040513d88823e3d90fd5b60405162461bcd60e51b815260206004820152602160248201527f617373657420746f6b656e2068617320666565206e6f7420636f6c6c656374656044820152601960fa1b6064820152608490fd5b61069c915060203d6020116106a2575b610694818361378b565b810190613b40565b5f6104b9565b503d61068a565b60405162461bcd60e51b815260206004820152601a60248201527f617373657420746f6b656e20697320726562616c616e63696e670000000000006044820152606490fd5b610707915060203d6020116106a257610694818361378b565b5f610490565b61072f915060203d602011610735575b610727818361378b565b810190613c6e565b5f61045e565b503d61071d565b6040513d87823e3d90fd5b6001600160a01b0361075c6101408401613cdf565b1690610160830161077f6001600160a01b0361077783613cdf565b161515613afc565b61079061078b86613cdf565b613c23565b906001600160a01b03906107a390613cdf565b6001600160a01b039092169116146104c15760405162461bcd60e51b815260206004820152600f60248201526e0ecc2ead8e840dcdee840dac2e8c6d608b1b6044820152606490fd5b8580fd5b5050856107fc82613975565b60038214610405565b50346103115760203660031901126103115761081f61374b565b6108276142c7565b600e54906001600160a01b03908116908216610844821515613afc565b8082146108a2576001600160a01b03199092168117600e55604080516001600160a01b0393841681529290911660208301527f4cc233b502e1e28f371b28114d4a8be87a93f330c18e3c339079fc498320fb8d9190819081016105bc565b60405162461bcd60e51b815260206004820152601060248201526f7661756c74206e6f74206368616e676560801b6044820152606490fd5b503461031157806003193601126103115780546108f681613b97565b610903604051918261378b565b81815261090f82613b97565b602082019290601f1901368437835b81811061096957505090604051928392602084019060208552518091526040840192915b818110610950575050500390f35b8251845285945060209384019390920191600101610942565b80610975600192614a9a565b90549060031b1c6109868286613bae565b520161091e565b5034610311576020366003190112610311576109a761374b565b6109af6142c7565b6001600160a01b03166109c3811515613ab8565b6109d8815f52600d60205260405f2054151590565b15610a1557602081610a0a7f4eb129c82dcd3eedb52df2b0e6fb4cfa41ac64ee9d63ff081acbb1877e85d79b93614d81565b50604051908152a180f35b60405162461bcd60e51b81526020600482015260166024820152751d1bdad95b881a5cc81b9bdd081cdd5c1c1bdc9d195960521b6044820152606490fd5b50346103115760203660031901126103115760406020916004358152600483522054604051908152f35b503461031157604036600319011261031157610a9761374b565b610aa8610aa2613761565b91613839565b9060018060a01b03165f52602052602060405f2054604051908152f35b503461031157604036600319011261031157610b15600435610ae5613761565b90610b10610b0b825f525f5160206150615f395f51905f52602052600160405f20015490565b61446a565b614603565b5080f35b5034610311578060031936011261031157610b58604051610b4481610b3d816138d6565b038261378b565b604051918291602083526020830190613727565b0390f35b503461031157602036600319011261031157610b7661374b565b610b7e6142c7565b600854906001600160a01b039081169082168115610c3257808214610bf4576001600160a01b03199092168117600855604080516001600160a01b0393841681529290911660208301527fd0eaca066dcad6475231b378a5902742964eff4c8a1f2d85a094fb173cf3edc29190819081016105bc565b60405162461bcd60e51b81526020600482015260166024820152756f726465725369676e6572206e6f74206368616e676560501b6044820152606490fd5b60405162461bcd60e51b815260206004820152601b60248201527f6f726465725369676e6572206973207a65726f206164647265737300000000006044820152606490fd5b5034610311578060031936011261031157602060405162093a808152f35b503461031157610ca43661397f565b9091610cae6143fb565b610cb661475b565b610cec610100820192610ccb6103a085613cdf565b6040516020810190610ce1816103c687856140ef565b519020948584613cf3565b60208101356004811015610df6577f73ffaa914260351efaba05b8fd31e1f8e94ed128d9fe9b14855e592c1ed34f41936105bc93610d3860026105b094610d3281613975565b14613a54565b610d49610d4482613cdf565b613839565b60018060a01b0330165f5260205260405f205491610d6e60a086013580941015614213565b610d788582614782565b808852600360205260408820600160ff1982541617905587526004602052426040882055308752601360205260408720610db3838254613c16565b90556001600160a01b03610dc960608601613cdf565b168752601360205260408720610de460c08601358254613c16565b9055610df03091613cdf565b306149e6565b8480fd5b503461031157602036600319011261031157610e1461374b565b610e1c6142c7565b600754906001600160a01b039081169082168115610ed757808214610e92576001600160a01b03199092168117600755604080516001600160a01b0393841681529290911660208301527f20796ffdb9bb1dad9a8e0682228d91254a48f4968c6f5f69dc235bc6147637dd9190819081016105bc565b60405162461bcd60e51b815260206004820152601760248201527f72656465656d20746f6b656e206e6f74206368616e67650000000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601c60248201527f72656465656d20746f6b656e206973207a65726f2061646472657373000000006044820152606490fd5b5034610311576020366003190112610311576020610f3b600435614a9a565b90549060031b1c604051908152f35b503461031157602036600319011261031157600435815260026020526040812060405182819390835490610f7d8261389e565b80855291600181169081156110a25750600114611065575b8361018086610fa68387038461378b565b600181015460028201546003830154600484015460058501546006860154600787015460088801546009890154600a8a0154600b909a01546040518c81529c8d9c60ff9b909b169b6001600160a01b039283169b9083169a938316999483169895979594909216929161101c91908e0190613727565b9a61102681613975565b60208d015260408c015260608b015260808a015260a089015260c088015260e08701526101008601526101208501526101408401526101608301520390f35b9150838252602082205b818310611086575050810160200181610fa6610f95565b602091935080600191548385890101520191019091849261106f565b60ff191660208681019190915292151560051b85019092019250839150610fa69050610f95565b503461031157806003193601126103115750610b586040516110ec60408261378b565b60058152640352e302e360dc1b6020820152604051918291602083526020830190613727565b50346103115760403660031901126103115761113961112f61374b565b602435903361433d565b602060405160018152f35b5034610311578060031936011261031157602090604051908152f35b5034610311576060366003190112610311576004356001600160401b0381116111c65761018060031982360301126111c657604435906001600160401b0382116111c2576111b561033e923690600401613871565b9160243590600401613cf3565b8280fd5b5080fd5b5034610311576020366003190112610311576020906040906001600160a01b036111f261374b565b168152601383522054604051908152f35b5034610311576020366003190112610311576004356112206142c7565b61123d611238825f52600160205260405f2054151590565b6139d2565b808252600360205260ff60408320541660058110156113ed5760016112629114613a11565b80825260026020526040822090600160ff8184016112978282541661128681613975565b8481149081156113d9575b50613a54565b8386526003602052604086206002831982541617905554166112b881613975565b0361139e5760018060a01b036009541690602060028401546024604051809581936373bacc5b60e01b835260048301525afa918215611393577f84424a38089bbc6d3e1350ac43d1f6e27aa6a520c269cca98291f20dd0ae41499360209361136c928791611376575b506001600160a01b0316905b6005810190815460018060a01b03841689526012875261135260408a20918254613a97565b9055600801549054916001600160a01b03909116906142fa565b604051908152a180f35b61138d9150853d871161073557610727818361378b565b5f611321565b6040513d86823e3d90fd5b60209061136c7f84424a38089bbc6d3e1350ac43d1f6e27aa6a520c269cca98291f20dd0ae41499360018060a01b03600a820154169061132d565b600391506113e681613975565b145f611291565b634e487b7160e01b83526021600452602483fd5b50346103115780600319360112610311576009546040516001600160a01b039091168152602090f35b503461031157806003193601126103115760405190805f516020614fe15f395f51905f5254906114598261389e565b80855291600181169081156114ea5750600114611481575b610b5884610b448186038261378b565b5f516020614fe15f395f51905f5281527f46a2803e59a4de4e7a4c574b1243f25977ac4c77d5a1a4a609b5394cebb4a2aa939250905b8082106114d057509091508101602001610b4482611471565b9192600181602092548385880101520191019092916114b7565b60ff191660208087019190915292151560051b85019092019250610b449150839050611471565b503461031157806003193601126103115760105461152e81613be4565b9061153881613be4565b92805b82811061156c5761155e84610b58876040519384936040855260408501906137fd565b9083820360208501526137fd565b80611578600192614a82565b838060a01b0391549060031b1c166115908287613bae565b5261159a81614a82565b838060a01b0391549060031b1c168352600f602052818060a01b036040842054166115c58288613bae565b520161153b565b50346103115760403660031901126103115760406115e8613761565b9160043581525f5160206150615f395f51905f52602052209060018060a01b03165f52602052602060ff60405f2054166040519015158152f35b50346103115780600319360112610311575f5160206150015f395f51905f52546040516001600160a01b039091168152602090f35b50346103115780600319360112610311576116706142c7565b61167861475b565b600160ff195f5160206150815f395f51905f525416175f5160206150815f395f51905f52557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b5034610614576020366003190112610614576004356116e76142c7565b6116ff611238825f52600160205260405f2054151590565b805f52600360205260ff60405f2054166005811015611b5a5760016117249114613a11565b805f52600260205260405f206001810161175660ff82541661174581613975565b600181149081156113d95750613a54565b600882015460068301546001600160a01b03909116918215611b47576001925f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6020856117b460ff975f5160206150215f395f51905f5254613c16565b5f5160206150215f395f51905f52558484525f516020614fc15f395f51905f52825260408420818154019055604051908152a3845f52600360205260405f2060038319825416179055541661180881613975565b03611aca576009546002820180546040516373bacc5b60e01b8152600481018290529093926001600160a01b031690602081602481855afa801561199a576020915f91611aad575b5060405163187b0c3160e21b815260048101969096526001600160a01b03169491829060249082905afa90811561199a575f91611a8e575b50604051636eb1769f60e11b81523060048201526001600160a01b0391909116602482018190529092909190602084604481885afa93841561199a575f94611a59575b506005019283548091106119a5575b50548254823b156106145760445f92836040519586948593635be0a35560e01b8552600485015260248401525af1801561199a5761195d575b50916020917ffe342118b30db7f9445876707e254f48f40847121ad55e6e6011e5634ab048af93549085526012835261195160408620918254613a97565b9055604051908152a180f35b7ffe342118b30db7f9445876707e254f48f40847121ad55e6e6011e5634ab048af939194509161198f5f60209461378b565b5f9491935091611913565b6040513d5f823e3d90fd5b60405163095ea7b360e01b60208083019182526001600160a01b03861660248401526044808401949094529282529091905f906119e360648561378b565b83519082895af15f513d82611a3d575b50506118da57611a3790611a3160405163095ea7b360e01b60208201528560248201525f604482015260448152611a2b60648261378b565b87614a2a565b85614a2a565b5f6118da565b909150611a515750843b15155b5f806119f3565b600114611a4a565b9093506020813d602011611a86575b81611a756020938361378b565b8101031261061457519260056118cb565b3d9150611a68565b611aa7915060203d60201161073557610727818361378b565b5f611888565b611ac49150823d841161073557610727818361378b565b5f611850565b600a81018054600b830154600590930180547ffe342118b30db7f9445876707e254f48f40847121ad55e6e6011e5634ab048af95602095909493611b1b92916001600160a01b0390811691166142fa565b5490546001600160a01b03165f908152601284526040902080549091611b4091613a97565b905561136c565b63ec442f0560e01b5f525f60045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b34610614576020366003190112610614576020611b8c61078b61374b565b6040516001600160a01b039091168152f35b34610614576020366003190112610614576001600160a01b03611bbf61374b565b165f526012602052602060405f2054604051908152f35b3461061457602036600319011261061457611bef61374b565b611bf76142c7565b6001600160a01b039081165f818152600f602052604090205490911615611c6a576020817ff25aefc32b3c9def33df65eb3281ad00c9578c0b47953d8b8732f9a600390015925f52600f825260405f206001600160601b0360a01b8154169055611c6081614cd6565b50604051908152a1005b60405162461bcd60e51b81526020600482015260166024820152757661756c7420726f757465206e6f742065786973747360501b6044820152606490fd5b34610614575f36600319011261061457611cc06142c7565b5f5160206150015f395f51905f5280546001600160a01b031981169091555f906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610614576020366003190112610614576001600160a01b03611d3061374b565b165f525f516020614fc15f395f51905f52602052602060405f2054604051908152f35b3461061457602036600319011261061457600435611d6f6142c7565b600954604051631313084160e11b81526004810183905290602090829060249082906001600160a01b03165afa801561199a57611db3915f91611e3e575b50613b58565b611dc8815f52600660205260405f2054151590565b611df957602081611c607fd40c7dd7ca4862165f47de6beb02e0fdb1d61ff12b99f2aec91b62fe9553f15393614b7b565b60405162461bcd60e51b815260206004820152601860248201527f616c726561647920636f6e7461696e73206173736574494400000000000000006044820152606490fd5b611e57915060203d6020116106a257610694818361378b565b83611dad565b34610614575f3660031901126106145760206040517f938c45fe3baa5cbd047f2473358a27f57db22291e9af95379a15ad016886dfb78152f35b34610614575f36600319011261061457602060ff5f5160206150815f395f51905f5254166040519015158152f35b3461061457602036600319011261061457600435611ee16142c7565b611ef9611238825f52600160205260405f2054151590565b805f52600360205260ff60405f2054166005811015611b5a577f08598c58e7d4625272865a734dffcd03e88a72ac08aa94dea237d1a21c5b221691611f42600160209314613a11565b805f5260028252611fda60405f20611f66600260ff600184015416610d3281613975565b825f526003845260405f20600260ff1982541617905560058101908154305f5260138652611f9960405f20918254613a97565b9055600681015460018060a01b036003830154165f5260138652611fc260405f20918254613a97565b9055600801549054906001600160a01b0316306142fa565b604051908152a1005b34610614575f366003190112610614577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316300361203a5760206040515f5160206150415f395f51905f528152f35b63703e46dd60e11b5f5260045ffd5b60403660031901126106145761205d61374b565b6024356001600160401b03811161061457366023820112156106145761208d9036906024816004013591016137c7565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016308114908115612207575b5061203a576120cf6142c7565b6040516352d1902d60e01b81526001600160a01b0383169290602081600481875afa5f91816121d3575b506121115783634c9c8ce360e01b5f5260045260245ffd5b805f5160206150415f395f51905f528592036121c15750813b156121af575f5160206150415f395f51905f5280546001600160a01b031916821790557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2815115612197575f8083602061219595519101845af461218f614e57565b91614f42565b005b5050346121a057005b63b398979f60e01b5f5260045ffd5b634c9c8ce360e01b5f5260045260245ffd5b632a87526960e21b5f5260045260245ffd5b9091506020813d6020116121ff575b816121ef6020938361378b565b81010312610614575190856120f9565b3d91506121e2565b5f5160206150415f395f51905f52546001600160a01b031614159050836120c2565b34610614576020366003190112610614576001600160a01b0361224a61374b565b165f52600f602052602060018060a01b0360405f205416604051908152f35b346106145760203660031901126106145761228261374b565b61228a6142c7565b6001600160a01b038116906122a0821515613ab8565b600e546001600160a01b0316906122b8821515613afc565b6040516370a0823160e01b8152306004820152602081602481875afa90811561199a575f916123c4575b50835f52601260205261230660405f2054855f52601360205260405f205490613c16565b81111561238b578361235f612367927fe603e9649c28b74edd6859199c6264fa2d833d570225c1d29095c0b8a0196c77965f52601260205261235960405f2054845f52601360205260405f205490613c16565b90613a97565b9384916142fa565b604080516001600160a01b039092168252602082019290925290819081015b0390a1005b60405162461bcd60e51b81526020600482015260116024820152706e6f7468696e6720746f2072657363756560781b6044820152606490fd5b90506020813d6020116123ee575b816123df6020938361378b565b810103126106145751846122e2565b3d91506123d2565b34610614576020366003190112610614576004355f52600a602052602060405f2054604051908152f35b34610614575f366003190112610614576124386142c7565b5f5160206150815f395f51905f525460ff81161561248f5760ff19165f5160206150815f395f51905f52557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b638dfc202b60e01b5f5260045ffd5b34610614575f366003190112610614576124b9600c54613be4565b600c545f5b8251811015612529578181101561251557600c5f527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7810154600191906001600160a01b031661250e8286613bae565b52016124be565b634e487b7160e01b5f52603260045260245ffd5b60405160208082528190610b58908201866137fd565b3461061457604036600319011261061457612558613761565b336001600160a01b038216036125745761219590600435614603565b63334bd91960e11b5f5260045ffd5b34610614575f36600319011261061457602060405160088152f35b346106145760a0366003190112610614576125b761374b565b6125bf613761565b906044356001600160a01b03811690819003610614576064356001600160a01b0381169190829003610614576084356001600160401b03811161061457366023820112156106145761261b9036906024816004013591016137c7565b915f5160206150a15f395f51905f52549460ff8660401c1615956001600160401b03811680159081612d00575b6001149081612cf6575b159081612ced575b50612cde5767ffffffffffffffff1981166001175f5160206150a15f395f51905f525586612cb2575b5061268c614e2c565b612694614e2c565b61269d85614256565b6126a5614e2c565b6126ad613bc2565b6126b5613bc2565b906126be614e2c565b6126c6614e2c565b8051906001600160401b0382116129ea576126ee5f516020614fa15f395f51905f525461389e565b601f8111612c43575b50602090601f8311600114612bc65761272792915f9183612bbb575b50508160011b915f199060031b1c19161790565b5f516020614fa15f395f51905f52555b8051906001600160401b0382116129ea5761275f5f516020614fe15f395f51905f525461389e565b601f8111612b4c575b50602090601f8311600114612acf5761279792915f9183612ac45750508160011b915f199060031b1c19161790565b5f516020614fe15f395f51905f52555b6127af614e2c565b6127b7614e2c565b6127bf614e2c565b60ff195f5160206150815f395f51905f5254165f5160206150815f395f51905f52558215612a88578115612a43576001600160a01b03169182156129fe576001600160601b0360a01b60095416176009556001600160601b0360a01b60075416176007556001600160601b0360a01b60085416176008558051906001600160401b0382116129ea57612852600b5461389e565b601f8111612987575b50602090601f831160011461290057918061288f9261289795945f926128f55750508160011b915f199060031b1c19161790565b600b556144b0565b5061289e57005b68ff0000000000000000195f5160206150a15f395f51905f5254165f5160206150a15f395f51905f52557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b015190508680612713565b90601f19831691600b5f527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9925f5b81811061296f575091600193918561289797969410612957575b505050811b01600b556144b0565b01515f1960f88460031b161c19169055858080612949565b9293602060018192878601518155019501930161292f565b600b5f527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9601f840160051c810191602085106129e0575b601f0160051c01905b8181106129d5575061285b565b5f81556001016129c8565b90915081906129bf565b634e487b7160e01b5f52604160045260245ffd5b60405162461bcd60e51b815260206004820152601960248201527f7a65726f206f72646572207369676e65722061646472657373000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601960248201527f7a65726f2072656465656d20746f6b656e2061646472657373000000000000006044820152606490fd5b60405162461bcd60e51b81526020600482015260146024820152737a65726f20666163746f7279206164647265737360601b6044820152606490fd5b015190508980612713565b90601f198316915f516020614fe15f395f51905f525f52815f20925f5b818110612b345750908460019594939210612b1c575b505050811b015f516020614fe15f395f51905f52556127a7565b01515f1960f88460031b161c19169055888080612b02565b92936020600181928786015181550195019301612aec565b5f516020614fe15f395f51905f525f527f46a2803e59a4de4e7a4c574b1243f25977ac4c77d5a1a4a609b5394cebb4a2aa601f840160051c81019160208510612bb1575b601f0160051c01905b818110612ba65750612768565b5f8155600101612b99565b9091508190612b90565b015190508a80612713565b90601f198316915f516020614fa15f395f51905f525f52815f20925f5b818110612c2b5750908460019594939210612c13575b505050811b015f516020614fa15f395f51905f5255612737565b01515f1960f88460031b161c19169055898080612bf9565b92936020600181928786015181550195019301612be3565b5f516020614fa15f395f51905f525f527f2ae08a8e29253f69ac5d979a101956ab8f8d9d7ded63fa7a83b16fc47648eab0601f840160051c81019160208510612ca8575b601f0160051c01905b818110612c9d57506126f7565b5f8155600101612c90565b9091508190612c87565b68ffffffffffffffffff191668010000000000000001175f5160206150a15f395f51905f525586612683565b63f92ee8a960e01b5f5260045ffd5b9050158861265a565b303b159150612652565b889150612648565b34610614575f366003190112610614576007546040516001600160a01b039091168152602090f35b3461061457604036600319011261061457612195600435612d4f613761565b90612d75610b0b825f525f5160206150615f395f51905f52602052600160405f20015490565b61455f565b34610614576020366003190112610614576004355f52600360205260ff60405f2054166040516005821015611b5a576020918152f35b34610614575f36600319011261061457600554612de5612dcf82613b97565b91612ddd604051938461378b565b808352613b97565b6020820190601f19013682376005545f5b8351811015612e4457818110156125155760055f527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db081015460019190612e3d8287613bae565b5201612df6565b505090604051918291602083019060208452518091526040830191905f5b818110612e70575050500390f35b8251845285945060209384019390920191600101612e62565b3461061457602036600319011261061457600435612ea56142c7565b600954604051631313084160e11b81526004810183905290602090829060249082906001600160a01b03165afa801561199a57612ee8915f91611e3e5750613b58565b612efd815f52600660205260405f2054151590565b15612f2f57602081611c607fd353b91ef24b87233598a495783dabdd9d6b182c6cd964f6ecab24f70df6ea2b93614c17565b60405162461bcd60e51b815260206004820152601860248201527f61737365744944206973206e6f7420737570706f7274656400000000000000006044820152606490fd5b34610614576020366003190112610614576020612fab6004355f525f5160206150615f395f51905f52602052600160405f20015490565b604051908152f35b3461061457606036600319011261061457612fcc61374b565b612fd4613761565b60443590612fe183613839565b335f9081526020919091526040902054925f198410613005575b611139935061433d565b828410613070576001600160a01b0381161561305d57331561304a576111399361302e82613839565b60018060a01b0333165f526020528360405f2091039055612ffb565b634a1406b160e11b5f525f60045260245ffd5b63e602df0560e01b5f525f60045260245ffd5b8284637dc7a0d960e11b5f523360045260245260445260645ffd5b34610614576040366003190112610614576130a461374b565b6130ac613761565b6130b46142c7565b6001600160a01b038116916130ca831515613afc565b6001600160a01b038181165f818152600f602052604090205490949116811461315a5783613136917f30d682126baa75723af317029e67cda86b0334871b273c3f0676e0e475cc2971955f52600f60205260405f20906001600160601b0360a01b825416179055614b2b565b50604080516001600160a01b03928316815292909116602083015281908101612386565b60405162461bcd60e51b81526020600482015260166024820152757661756c7420726f757465206e6f74206368616e676560501b6044820152606490fd5b34610614576020366003190112610614576131b161374b565b6131b96142c7565b6001600160a01b03166131cd811515613ab8565b6131e2815f52600d60205260405f2054151590565b61321357602081611c607fe473c74f34be27c1464d6624f14a0d7fd4e301cbfa29c3eba425d378c8a7ebe093614ac5565b60405162461bcd60e51b815260206004820152601660248201527530b63932b0b23c9031b7b73a30b4b739903a37b5b2b760511b6044820152606490fd5b34610614575f3660031901126106145760205f5160206150215f395f51905f5254604051908152f35b34610614576040366003190112610614576004356024356132996142c7565b6132b1611238835f52600160205260405f2054151590565b815f52600360205260ff60405f2054166005811015611b5a5760016132d69114613a11565b815f52600260205260405f20906132f9600260ff600185015416610d3281613975565b825f52600360205260405f20600360ff1982541617905580155f14613528575060038101546040516370a0823160e01b81523060048201526001600160a01b0390911690602081602481855afa90811561199a575f916134f6575b5060068301548091106134b157600883015461337b926001600160a01b03909116906142fa565b60058101908154305f52601360205261339960405f20918254613a97565b9055600681015490600360018060a01b03910154165f5260136020526133c460405f20918254613a97565b90555490301561349e57305f525f516020614fc15f395f51905f5260205260405f205482811061348357905f837f7ad7174076b297a24f706a24c4f35617b4a2ac4b102f85e9f11654b46cd31512946020943084525f516020614fc15f395f51905f528652036040832055805f5160206150215f395f51905f5254035f5160206150215f395f51905f52556040519081527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef843092a3604051908152a1005b905063391434e360e21b5f523060045260245260445260645ffd5b634b637e8f60e11b5f525f60045260245ffd5b60405162461bcd60e51b815260206004820152601760248201527f6e6f7420656e6f7567682072656465656d20746f6b656e0000000000000000006044820152606490fd5b90506020813d602011613520575b816135116020938361378b565b81010312610614575184613354565b3d9150613504565b825f52600a60205260405f205561337b565b346106145760403660031901126106145761355361374b565b60243590331561305d576001600160a01b031690811561304a5761357633613839565b825f526020528060405f20556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b34610614575f366003190112610614576020604051620151808152f35b34610614575f366003190112610614576040515f5f516020614fa15f395f51905f52546136028161389e565b8084529060018116908115613694575060011461362a575b610b5883610b448185038261378b565b5f516020614fa15f395f51905f525f9081527f2ae08a8e29253f69ac5d979a101956ab8f8d9d7ded63fa7a83b16fc47648eab0939250905b80821061367a57509091508101602001610b4461361a565b919260018160209254838588010152019101909291613662565b60ff191660208086019190915291151560051b84019091019150610b44905061361a565b34610614575f3660031901126106145760205f54604051908152f35b34610614576020366003190112610614576004359063ffffffff60e01b821680920361061457602091637965db0b60e01b8114908115613716575b5015158152f35b6301ffc9a760e01b1490508361370f565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b600435906001600160a01b038216820361061457565b602435906001600160a01b038216820361061457565b35906001600160a01b038216820361061457565b90601f801991011681019081106001600160401b038211176129ea57604052565b6001600160401b0381116129ea57601f01601f191660200190565b9291926137d3826137ac565b916137e1604051938461378b565b829481845281830111610614578281602093845f960137010152565b90602080835192838152019201905f5b81811061381a5750505090565b82516001600160a01b031684526020938401939092019160010161380d565b6001600160a01b03165f9081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020526040902090565b9181601f84011215610614578235916001600160401b038311610614576020838186019501011161061457565b90600182811c921680156138cc575b60208310146138b857565b634e487b7160e01b5f52602260045260245ffd5b91607f16916138ad565b600b545f92916138e58261389e565b80825291600181169081156139595750600114613900575050565b600b5f9081529293509091907f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db95b83831061393f575060209250010190565b60018160209294939454838587010152019101919061392e565b9050602093945060ff929192191683830152151560051b010190565b60041115611b5a57565b906040600319830112610614576004356001600160401b0381116106145761018081840360031901126106145760040191602435906001600160401b038211610614576139ce91600401613871565b9091565b156139d957565b60405162461bcd60e51b815260206004820152601060248201526f6f72646572206e6f742065786973747360801b6044820152606490fd5b15613a1857565b60405162461bcd60e51b81526020600482015260146024820152736f72646572206973206e6f742070656e64696e6760601b6044820152606490fd5b15613a5b57565b60405162461bcd60e51b81526020600482015260146024820152730dee4c8cae440e8f2e0ca40dcdee840dac2e8c6d60631b6044820152606490fd5b91908203918211613aa457565b634e487b7160e01b5f52601160045260245ffd5b15613abf57565b60405162461bcd60e51b8152602060048201526015602482015274746f6b656e206973207a65726f206164647265737360581b6044820152606490fd5b15613b0357565b60405162461bcd60e51b81526020600482015260156024820152747661756c74206973207a65726f206164647265737360581b6044820152606490fd5b90816020910312610614575180151581036106145790565b15613b5f57565b60405162461bcd60e51b815260206004820152601060248201526f6173736574206e6f742065786973747360801b6044820152606490fd5b6001600160401b0381116129ea5760051b60200190565b80518210156125155760209160051b010190565b60405190613bd160408361378b565b60048252635553534960e01b6020830152565b90613bee82613b97565b613bfb604051918261378b565b8281528092613c0c601f1991613b97565b0190602036910137565b91908201809211613aa457565b6001600160a01b039081165f818152600f602052604090205490911615613c5e575f908152600f60205260409020546001600160a01b031690565b50600e546001600160a01b031690565b9081602091031261061457516001600160a01b03811681036106145790565b903590601e198136030182121561061457018035906001600160401b0382116106145760200191813603831361061457565b908060209392818452848401375f828201840152601f01601f1916010190565b356001600160a01b03811681036106145790565b929192604051602081019060208252613d12816103c6604082016138d6565b519020613d406103c6613d258480613c8d565b92906040519283916020830195602087526040840191613cbf565b5190200361406c576020810135600481101561061457613d5f81613975565b801561403257613d6e81613975565b60018114613fd8575b613d8081613975565b60028114613f12575b600390613d9581613975565b14613e8b575b60e001354211613e5c57613dba815f52600160205260405f2054151590565b613e2057613dd8613dde9360018060a01b03600854169336916137c7565b9161469f565b15613de557565b60405162461bcd60e51b81526020600482015260136024820152721cda59db985d1d5c99481b9bdd081d985b1a59606a1b6044820152606490fd5b60405162461bcd60e51b81526020600482015260146024820152736f7264657220616c72656164792065786973747360601b6044820152606490fd5b60405162461bcd60e51b8152602060048201526007602482015266195e1c1a5c995960ca1b6044820152606490fd5b613ed36101408201613eaf6001600160a01b03613ea783613cdf565b161515613ab8565b6001600160a01b0390613ec190613cdf565b165f52600d60205260405f2054151590565b613d9b5760405162461bcd60e51b81526020600482015260136024820152721d1bdad95b881b9bdd081cdd5c1c1bdc9d1959606a1b6044820152606490fd5b6001600160a01b03613f276101208401613cdf565b1615613f93576007546001600160a01b0390811690613f4860608501613cdf565b1614613d895760405162461bcd60e51b815260206004820152601a60248201527f72656465656d20746f6b656e206e6f7420737570706f727465640000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601860248201527f7265636569766572206973207a65726f206164647265737300000000000000006044820152606490fd5b613ff160408301355f52600660205260405f2054151590565b613d775760405162461bcd60e51b8152602060048201526015602482015274185cdcd95d1251081b9bdd081cdd5c1c1bdc9d1959605a1b6044820152606490fd5b60405162461bcd60e51b81526020600482015260126024820152716f726465722074797065206973206e6f6e6560701b6044820152606490fd5b60405162461bcd60e51b815260206004820152600f60248201526e0c6d0c2d2dc40dcdee840dac2e8c6d608b1b6044820152606490fd5b156140aa57565b60405162461bcd60e51b815260206004820152601b60248201527f6d73672073656e646572206973206e6f742072657175657374657200000000006044820152606490fd5b602081528135601e19833603018112156106145782016020813591016001600160401b038211610614578136038113610614576141399161018060208501526101a0840191613cbf565b916020810135906004821015610614578161415661018093613975565b60408401526040810135606084015260018060a01b0361417860608301613777565b166080840152608081013560a084015260a081013560c084015260c081013560e084015260e081013561010084015260018060a01b036141bb6101008301613777565b1661012084015260018060a01b036141d66101208301613777565b1661014084015260018060a01b036141f16101408301613777565b1661016084015261420c61016060018060a01b039201613777565b1691015290565b1561421a57565b60405162461bcd60e51b81526020600482015260146024820152736e6f7420656e6f75676820616c6c6f77616e636560601b6044820152606490fd5b6001600160a01b031680156142b4575f5160206150015f395f51905f5280546001600160a01b0319811683179091556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b631e4fbdf760e01b5f525f60045260245ffd5b5f5160206150015f395f51905f52546001600160a01b031633036142e757565b63118cdaa760e01b5f523360045260245ffd5b60405163a9059cbb60e01b60208201526001600160a01b0392909216602483015260448083019390935291815261433b9161433660648361378b565b614a2a565b565b6001600160a01b031690811561349e576001600160a01b0316918215611b4757815f525f516020614fc15f395f51905f5260205260405f20548181106143e257817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f516020614fc15f395f51905f5284520360405f2055845f525f516020614fc15f395f51905f52825260405f20818154019055604051908152a3565b8263391434e360e21b5f5260045260245260445260645ffd5b335f9081527fccf616fcc782ae4975b4090604ebc6d6877b665e3ab61c33e0108a88b1f19746602052604090205460ff161561443357565b63e2517d3f60e01b5f52336004527f938c45fe3baa5cbd047f2473358a27f57db22291e9af95379a15ad016886dfb760245260445ffd5b5f8181525f5160206150615f395f51905f526020908152604080832033845290915290205460ff161561449a5750565b63e2517d3f60e01b5f523360045260245260445ffd5b6001600160a01b0381165f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff1661455a576001600160a01b03165f8181527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d60205260408120805460ff191660011790553391907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8180a4600190565b505f90565b5f8181525f5160206150615f395f51905f52602090815260408083206001600160a01b038616845290915290205460ff166145fd575f8181525f5160206150615f395f51905f52602090815260408083206001600160a01b0395909516808452949091528120805460ff19166001179055339291907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9080a4600190565b50505f90565b5f8181525f5160206150615f395f51905f52602090815260408083206001600160a01b038616845290915290205460ff16156145fd575f8181525f5160206150615f395f51905f52602090815260408083206001600160a01b0395909516808452949091528120805460ff19169055339291907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9080a4600190565b9190823b6146da57906146b191614e86565b506146bb81613975565b1591826146c757505090565b6001600160a01b03918216911614919050565b915f926103c661471085946040519283916020830195630b135d3f60e11b87526024840152604060448401526064830190613727565b51915afa61471c614e57565b8161474d575b8161472b575090565b80516020808301935090820191909103126106145751630b135d3f60e11b1490565b905060208151101590614722565b60ff5f5160206150815f395f51905f52541661477357565b63d93c066560e01b5f5260045ffd5b805f52600260205260405f206147988380613c8d565b906001600160401b0382116129ea576147b1835461389e565b601f81116149a1575b505f90601f831160011461493d576147e892915f91836149325750508160011b915f199060031b1c19161790565b81555b602083013560048110156106145761490b61016061492f95600b93600186019061481481613975565b815460ff191660ff9190911617905560408101356002860155600780546003870180546001600160a01b039092166001600160a01b03199092169190911790556080820135600487015560a0820135600587015560c0820135600687015560e0820135908601556148886101008201613cdf565b6008860180546001600160a01b0319166001600160a01b039092169190911790556148b66101208201613cdf565b6009860180546001600160a01b0319166001600160a01b039092169190911790556148e46101408201613cdf565b600a860180546001600160a01b0319166001600160a01b0390921691909117905501613cdf565b910180546001600160a01b0319166001600160a01b03909216919091179055614bcb565b50565b013590505f80612713565b601f19831691845f5260205f20925f5b8181106149895750908460019594939210614970575b505050811b0181556147eb565b01355f19600384901b60f8161c191690555f8080614963565b9193602060018192878701358155019501920161494d565b835f5260205f20601f840160051c810191602085106149dc575b601f0160051c01905b8181106149d157506147ba565b5f81556001016149c4565b90915081906149bb565b6040516323b872dd60e01b60208201526001600160a01b03928316602482015292909116604483015260648083019390935291815261433b9161433660848361378b565b905f602091828151910182855af11561199a575f513d614a7957506001600160a01b0381163b155b614a595750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b60011415614a52565b6010548110156125155760105f5260205f2001905f90565b5f54811015612515575f805260205f2001905f90565b8054821015612515575f5260205f2001905f90565b805f52600d60205260405f2054155f1461455a57600c54600160401b8110156129ea57614b14614afe826001859401600c55600c614ab0565b819391549060031b91821b915f19901b19161790565b9055600c54905f52600d60205260405f2055600190565b805f52601160205260405f2054155f1461455a57601054600160401b8110156129ea57614b64614afe8260018594016010556010614ab0565b9055601054905f52601160205260405f2055600190565b805f52600660205260405f2054155f1461455a57600554600160401b8110156129ea57614bb4614afe8260018594016005556005614ab0565b9055600554905f52600660205260405f2055600190565b805f52600160205260405f2054155f1461455a575f54600160401b8110156129ea57614c01614afe8260018594015f555f614ab0565b90555f54905f52600160205260405f2055600190565b5f8181526006602052604090205480156145fd575f198101818111613aa4576005545f19810191908211613aa457818103614c9e575b5050506005548015614c8a575f1901614c67816005614ab0565b8154905f199060031b1b191690556005555f5260066020525f6040812055600190565b634e487b7160e01b5f52603160045260245ffd5b614cc0614caf614afe936005614ab0565b90549060031b1c9283926005614ab0565b90555f52600660205260405f20555f8080614c4d565b5f8181526011602052604090205480156145fd575f198101818111613aa4576010545f19810191908211613aa457818103614d49575b5050506010548015614c8a575f1901614d26816010614ab0565b8154905f199060031b1b191690556010555f5260116020525f6040812055600190565b614d6b614d5a614afe936010614ab0565b90549060031b1c9283926010614ab0565b90555f52601160205260405f20555f8080614d0c565b5f818152600d602052604090205480156145fd575f198101818111613aa457600c545f19810191908211613aa457818103614df4575b505050600c548015614c8a575f1901614dd181600c614ab0565b8154905f199060031b1b19169055600c555f52600d6020525f6040812055600190565b614e16614e05614afe93600c614ab0565b90549060031b1c928392600c614ab0565b90555f52600d60205260405f20555f8080614db7565b60ff5f5160206150a15f395f51905f525460401c1615614e4857565b631afcd79f60e31b5f5260045ffd5b3d15614e81573d90614e68826137ac565b91614e76604051938461378b565b82523d5f602084013e565b606090565b8151919060418303614eb657614eaf9250602082015190606060408401519301515f1a90614ec0565b9192909190565b50505f9160029190565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411614f37579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa1561199a575f516001600160a01b03811615614f2d57905f905f90565b505f906001905f90565b5050505f9160039190565b90614f665750805115614f5757805190602001fd5b63d6bda27560e01b5f5260045ffd5b81511580614f97575b614f77575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b15614f6f56fe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0352c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0052c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace049016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930052c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800cd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212209899a8da5b0b749f923a81f67c991aa5a13a110221aee65cff471850b120aeb964736f6c634300081c0033f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00
Deployed Bytecode
0x6080806040526004361015610012575f80fd5b5f905f3560e01c90816301ffc9a7146136d45750806305e0a9b5146136b857806306fdde03146135d6578063081a1a50146135b9578063095ea7b31461353a57806310a255ce1461327a57806318160ddd146132515780631c68bf00146131985780631e3a915f1461308b57806323b872dd14612fb3578063248a9ca314612f74578063256ea64514612e895780632af03d7814612db05780632dff692d14612d7a5780632f2ff15d14612d305780632f310bad14612d085780632fb3b3611461259e578063313ce5671461258357806336568abe1461253f57806339cdfb2b1461249e5780633f4ba83a14612420578063437f2e61146123f65780634460d3cf146122695780634e60cd14146122295780634f1ef2861461204957806352d1902d14611fe357806353c34f0214611ec55780635c975abb14611e975780635f8a7abe14611e5d5780636f6f990014611d5357806370a0823114611d0f578063715018a614611ca857806371bbd15014611bd657806377c4accf14611b9e5780637d941f7914611b6e5780637df6d891146116ca5780638456cb59146116575780638da5cb5b1461162257806391d14854146115cc57806393d82de71461151157806395d89b411461142a578063966dae0e14611401578063998fccc5146112035780639c4c82aa146111ca578063a0a0036014611160578063a217fddf14611144578063a9059cbb14611112578063ad3cb1cc146110c9578063b4c081b814610f4a578063b9f0d68e14610f1c578063c06f8e3714610dfa578063c33bb25614610c95578063c5a5666414610c77578063c5e0e0cf14610b5c578063c763e5a114610b19578063d547741f14610ac5578063dd62ed3e14610a7d578063ddd6c72a14610a53578063e2769cfa1461098d578063e477a571146108da578063e7563f3f14610805578063ec2fe14a1461036a578063f299f8b314610341578063f2fde38b146103145763fbfa77cf146102e9575f80fd5b34610311578060031936011261031157600e546040516001600160a01b039091168152602090f35b80fd5b50346103115760203660031901126103115761033e61033161374b565b6103396142c7565b614256565b80f35b50346103115780600319360112610311576008546040516001600160a01b039091168152602090f35b5034610311576103793661397f565b91906103836143fb565b61038b61475b565b6103df6101008301936103b06103a086613cdf565b6001600160a01b031633146140a3565b60405160208101906103d4816103c688856140ef565b03601f19810183528261378b565b519020928385613cf3565b6020820135600481101590816107ec576103f881613975565b60018114918280156107f0575b61040e90613a54565b6107ec5761041b90613975565b1561074757600954604080516373bacc5b60e01b815290840135600482015290602090829060249082906001600160a01b03165afa90811561073c57859161070d575b5060405163959b13d960e01b81526001600160a01b039190911690602081600481855afa9081156106205786916106ee575b506106a957604051631b29fe5760e21b8152602081600481855afa90811561062057869161067a575b501561062b57905b6104cb8382614782565b808552600360205260408520600160ff198254161790558452600460205242604085205560a082013590610556602060018060a01b0383168088526012825260408820610519868254613c16565b905561052487613cdf565b604051636eb1769f60e11b81526001600160a01b03909116600482015230602482015292839190829081906044820190565b03915afa9081156106205786916105c2575b50917f51433b4a579ebe26ed2ca605218d3d56d316d7198fecfe7cf02ece121e58ca5b946105b0926105a0836105bc97961015614213565b6105aa3092613cdf565b906149e6565b604051918291826140ef565b0390a180f35b91939290506020823d602011610618575b816105e06020938361378b565b81010312610614579051919290917f51433b4a579ebe26ed2ca605218d3d56d316d7198fecfe7cf02ece121e58ca5b610568565b5f80fd5b3d91506105d3565b6040513d88823e3d90fd5b60405162461bcd60e51b815260206004820152602160248201527f617373657420746f6b656e2068617320666565206e6f7420636f6c6c656374656044820152601960fa1b6064820152608490fd5b61069c915060203d6020116106a2575b610694818361378b565b810190613b40565b5f6104b9565b503d61068a565b60405162461bcd60e51b815260206004820152601a60248201527f617373657420746f6b656e20697320726562616c616e63696e670000000000006044820152606490fd5b610707915060203d6020116106a257610694818361378b565b5f610490565b61072f915060203d602011610735575b610727818361378b565b810190613c6e565b5f61045e565b503d61071d565b6040513d87823e3d90fd5b6001600160a01b0361075c6101408401613cdf565b1690610160830161077f6001600160a01b0361077783613cdf565b161515613afc565b61079061078b86613cdf565b613c23565b906001600160a01b03906107a390613cdf565b6001600160a01b039092169116146104c15760405162461bcd60e51b815260206004820152600f60248201526e0ecc2ead8e840dcdee840dac2e8c6d608b1b6044820152606490fd5b8580fd5b5050856107fc82613975565b60038214610405565b50346103115760203660031901126103115761081f61374b565b6108276142c7565b600e54906001600160a01b03908116908216610844821515613afc565b8082146108a2576001600160a01b03199092168117600e55604080516001600160a01b0393841681529290911660208301527f4cc233b502e1e28f371b28114d4a8be87a93f330c18e3c339079fc498320fb8d9190819081016105bc565b60405162461bcd60e51b815260206004820152601060248201526f7661756c74206e6f74206368616e676560801b6044820152606490fd5b503461031157806003193601126103115780546108f681613b97565b610903604051918261378b565b81815261090f82613b97565b602082019290601f1901368437835b81811061096957505090604051928392602084019060208552518091526040840192915b818110610950575050500390f35b8251845285945060209384019390920191600101610942565b80610975600192614a9a565b90549060031b1c6109868286613bae565b520161091e565b5034610311576020366003190112610311576109a761374b565b6109af6142c7565b6001600160a01b03166109c3811515613ab8565b6109d8815f52600d60205260405f2054151590565b15610a1557602081610a0a7f4eb129c82dcd3eedb52df2b0e6fb4cfa41ac64ee9d63ff081acbb1877e85d79b93614d81565b50604051908152a180f35b60405162461bcd60e51b81526020600482015260166024820152751d1bdad95b881a5cc81b9bdd081cdd5c1c1bdc9d195960521b6044820152606490fd5b50346103115760203660031901126103115760406020916004358152600483522054604051908152f35b503461031157604036600319011261031157610a9761374b565b610aa8610aa2613761565b91613839565b9060018060a01b03165f52602052602060405f2054604051908152f35b503461031157604036600319011261031157610b15600435610ae5613761565b90610b10610b0b825f525f5160206150615f395f51905f52602052600160405f20015490565b61446a565b614603565b5080f35b5034610311578060031936011261031157610b58604051610b4481610b3d816138d6565b038261378b565b604051918291602083526020830190613727565b0390f35b503461031157602036600319011261031157610b7661374b565b610b7e6142c7565b600854906001600160a01b039081169082168115610c3257808214610bf4576001600160a01b03199092168117600855604080516001600160a01b0393841681529290911660208301527fd0eaca066dcad6475231b378a5902742964eff4c8a1f2d85a094fb173cf3edc29190819081016105bc565b60405162461bcd60e51b81526020600482015260166024820152756f726465725369676e6572206e6f74206368616e676560501b6044820152606490fd5b60405162461bcd60e51b815260206004820152601b60248201527f6f726465725369676e6572206973207a65726f206164647265737300000000006044820152606490fd5b5034610311578060031936011261031157602060405162093a808152f35b503461031157610ca43661397f565b9091610cae6143fb565b610cb661475b565b610cec610100820192610ccb6103a085613cdf565b6040516020810190610ce1816103c687856140ef565b519020948584613cf3565b60208101356004811015610df6577f73ffaa914260351efaba05b8fd31e1f8e94ed128d9fe9b14855e592c1ed34f41936105bc93610d3860026105b094610d3281613975565b14613a54565b610d49610d4482613cdf565b613839565b60018060a01b0330165f5260205260405f205491610d6e60a086013580941015614213565b610d788582614782565b808852600360205260408820600160ff1982541617905587526004602052426040882055308752601360205260408720610db3838254613c16565b90556001600160a01b03610dc960608601613cdf565b168752601360205260408720610de460c08601358254613c16565b9055610df03091613cdf565b306149e6565b8480fd5b503461031157602036600319011261031157610e1461374b565b610e1c6142c7565b600754906001600160a01b039081169082168115610ed757808214610e92576001600160a01b03199092168117600755604080516001600160a01b0393841681529290911660208301527f20796ffdb9bb1dad9a8e0682228d91254a48f4968c6f5f69dc235bc6147637dd9190819081016105bc565b60405162461bcd60e51b815260206004820152601760248201527f72656465656d20746f6b656e206e6f74206368616e67650000000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601c60248201527f72656465656d20746f6b656e206973207a65726f2061646472657373000000006044820152606490fd5b5034610311576020366003190112610311576020610f3b600435614a9a565b90549060031b1c604051908152f35b503461031157602036600319011261031157600435815260026020526040812060405182819390835490610f7d8261389e565b80855291600181169081156110a25750600114611065575b8361018086610fa68387038461378b565b600181015460028201546003830154600484015460058501546006860154600787015460088801546009890154600a8a0154600b909a01546040518c81529c8d9c60ff9b909b169b6001600160a01b039283169b9083169a938316999483169895979594909216929161101c91908e0190613727565b9a61102681613975565b60208d015260408c015260608b015260808a015260a089015260c088015260e08701526101008601526101208501526101408401526101608301520390f35b9150838252602082205b818310611086575050810160200181610fa6610f95565b602091935080600191548385890101520191019091849261106f565b60ff191660208681019190915292151560051b85019092019250839150610fa69050610f95565b503461031157806003193601126103115750610b586040516110ec60408261378b565b60058152640352e302e360dc1b6020820152604051918291602083526020830190613727565b50346103115760403660031901126103115761113961112f61374b565b602435903361433d565b602060405160018152f35b5034610311578060031936011261031157602090604051908152f35b5034610311576060366003190112610311576004356001600160401b0381116111c65761018060031982360301126111c657604435906001600160401b0382116111c2576111b561033e923690600401613871565b9160243590600401613cf3565b8280fd5b5080fd5b5034610311576020366003190112610311576020906040906001600160a01b036111f261374b565b168152601383522054604051908152f35b5034610311576020366003190112610311576004356112206142c7565b61123d611238825f52600160205260405f2054151590565b6139d2565b808252600360205260ff60408320541660058110156113ed5760016112629114613a11565b80825260026020526040822090600160ff8184016112978282541661128681613975565b8481149081156113d9575b50613a54565b8386526003602052604086206002831982541617905554166112b881613975565b0361139e5760018060a01b036009541690602060028401546024604051809581936373bacc5b60e01b835260048301525afa918215611393577f84424a38089bbc6d3e1350ac43d1f6e27aa6a520c269cca98291f20dd0ae41499360209361136c928791611376575b506001600160a01b0316905b6005810190815460018060a01b03841689526012875261135260408a20918254613a97565b9055600801549054916001600160a01b03909116906142fa565b604051908152a180f35b61138d9150853d871161073557610727818361378b565b5f611321565b6040513d86823e3d90fd5b60209061136c7f84424a38089bbc6d3e1350ac43d1f6e27aa6a520c269cca98291f20dd0ae41499360018060a01b03600a820154169061132d565b600391506113e681613975565b145f611291565b634e487b7160e01b83526021600452602483fd5b50346103115780600319360112610311576009546040516001600160a01b039091168152602090f35b503461031157806003193601126103115760405190805f516020614fe15f395f51905f5254906114598261389e565b80855291600181169081156114ea5750600114611481575b610b5884610b448186038261378b565b5f516020614fe15f395f51905f5281527f46a2803e59a4de4e7a4c574b1243f25977ac4c77d5a1a4a609b5394cebb4a2aa939250905b8082106114d057509091508101602001610b4482611471565b9192600181602092548385880101520191019092916114b7565b60ff191660208087019190915292151560051b85019092019250610b449150839050611471565b503461031157806003193601126103115760105461152e81613be4565b9061153881613be4565b92805b82811061156c5761155e84610b58876040519384936040855260408501906137fd565b9083820360208501526137fd565b80611578600192614a82565b838060a01b0391549060031b1c166115908287613bae565b5261159a81614a82565b838060a01b0391549060031b1c168352600f602052818060a01b036040842054166115c58288613bae565b520161153b565b50346103115760403660031901126103115760406115e8613761565b9160043581525f5160206150615f395f51905f52602052209060018060a01b03165f52602052602060ff60405f2054166040519015158152f35b50346103115780600319360112610311575f5160206150015f395f51905f52546040516001600160a01b039091168152602090f35b50346103115780600319360112610311576116706142c7565b61167861475b565b600160ff195f5160206150815f395f51905f525416175f5160206150815f395f51905f52557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b5034610614576020366003190112610614576004356116e76142c7565b6116ff611238825f52600160205260405f2054151590565b805f52600360205260ff60405f2054166005811015611b5a5760016117249114613a11565b805f52600260205260405f206001810161175660ff82541661174581613975565b600181149081156113d95750613a54565b600882015460068301546001600160a01b03909116918215611b47576001925f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6020856117b460ff975f5160206150215f395f51905f5254613c16565b5f5160206150215f395f51905f52558484525f516020614fc15f395f51905f52825260408420818154019055604051908152a3845f52600360205260405f2060038319825416179055541661180881613975565b03611aca576009546002820180546040516373bacc5b60e01b8152600481018290529093926001600160a01b031690602081602481855afa801561199a576020915f91611aad575b5060405163187b0c3160e21b815260048101969096526001600160a01b03169491829060249082905afa90811561199a575f91611a8e575b50604051636eb1769f60e11b81523060048201526001600160a01b0391909116602482018190529092909190602084604481885afa93841561199a575f94611a59575b506005019283548091106119a5575b50548254823b156106145760445f92836040519586948593635be0a35560e01b8552600485015260248401525af1801561199a5761195d575b50916020917ffe342118b30db7f9445876707e254f48f40847121ad55e6e6011e5634ab048af93549085526012835261195160408620918254613a97565b9055604051908152a180f35b7ffe342118b30db7f9445876707e254f48f40847121ad55e6e6011e5634ab048af939194509161198f5f60209461378b565b5f9491935091611913565b6040513d5f823e3d90fd5b60405163095ea7b360e01b60208083019182526001600160a01b03861660248401526044808401949094529282529091905f906119e360648561378b565b83519082895af15f513d82611a3d575b50506118da57611a3790611a3160405163095ea7b360e01b60208201528560248201525f604482015260448152611a2b60648261378b565b87614a2a565b85614a2a565b5f6118da565b909150611a515750843b15155b5f806119f3565b600114611a4a565b9093506020813d602011611a86575b81611a756020938361378b565b8101031261061457519260056118cb565b3d9150611a68565b611aa7915060203d60201161073557610727818361378b565b5f611888565b611ac49150823d841161073557610727818361378b565b5f611850565b600a81018054600b830154600590930180547ffe342118b30db7f9445876707e254f48f40847121ad55e6e6011e5634ab048af95602095909493611b1b92916001600160a01b0390811691166142fa565b5490546001600160a01b03165f908152601284526040902080549091611b4091613a97565b905561136c565b63ec442f0560e01b5f525f60045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b34610614576020366003190112610614576020611b8c61078b61374b565b6040516001600160a01b039091168152f35b34610614576020366003190112610614576001600160a01b03611bbf61374b565b165f526012602052602060405f2054604051908152f35b3461061457602036600319011261061457611bef61374b565b611bf76142c7565b6001600160a01b039081165f818152600f602052604090205490911615611c6a576020817ff25aefc32b3c9def33df65eb3281ad00c9578c0b47953d8b8732f9a600390015925f52600f825260405f206001600160601b0360a01b8154169055611c6081614cd6565b50604051908152a1005b60405162461bcd60e51b81526020600482015260166024820152757661756c7420726f757465206e6f742065786973747360501b6044820152606490fd5b34610614575f36600319011261061457611cc06142c7565b5f5160206150015f395f51905f5280546001600160a01b031981169091555f906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610614576020366003190112610614576001600160a01b03611d3061374b565b165f525f516020614fc15f395f51905f52602052602060405f2054604051908152f35b3461061457602036600319011261061457600435611d6f6142c7565b600954604051631313084160e11b81526004810183905290602090829060249082906001600160a01b03165afa801561199a57611db3915f91611e3e575b50613b58565b611dc8815f52600660205260405f2054151590565b611df957602081611c607fd40c7dd7ca4862165f47de6beb02e0fdb1d61ff12b99f2aec91b62fe9553f15393614b7b565b60405162461bcd60e51b815260206004820152601860248201527f616c726561647920636f6e7461696e73206173736574494400000000000000006044820152606490fd5b611e57915060203d6020116106a257610694818361378b565b83611dad565b34610614575f3660031901126106145760206040517f938c45fe3baa5cbd047f2473358a27f57db22291e9af95379a15ad016886dfb78152f35b34610614575f36600319011261061457602060ff5f5160206150815f395f51905f5254166040519015158152f35b3461061457602036600319011261061457600435611ee16142c7565b611ef9611238825f52600160205260405f2054151590565b805f52600360205260ff60405f2054166005811015611b5a577f08598c58e7d4625272865a734dffcd03e88a72ac08aa94dea237d1a21c5b221691611f42600160209314613a11565b805f5260028252611fda60405f20611f66600260ff600184015416610d3281613975565b825f526003845260405f20600260ff1982541617905560058101908154305f5260138652611f9960405f20918254613a97565b9055600681015460018060a01b036003830154165f5260138652611fc260405f20918254613a97565b9055600801549054906001600160a01b0316306142fa565b604051908152a1005b34610614575f366003190112610614577f000000000000000000000000a62307106f891135154b0d63eaef8bd40f2ca91b6001600160a01b0316300361203a5760206040515f5160206150415f395f51905f528152f35b63703e46dd60e11b5f5260045ffd5b60403660031901126106145761205d61374b565b6024356001600160401b03811161061457366023820112156106145761208d9036906024816004013591016137c7565b6001600160a01b037f000000000000000000000000a62307106f891135154b0d63eaef8bd40f2ca91b16308114908115612207575b5061203a576120cf6142c7565b6040516352d1902d60e01b81526001600160a01b0383169290602081600481875afa5f91816121d3575b506121115783634c9c8ce360e01b5f5260045260245ffd5b805f5160206150415f395f51905f528592036121c15750813b156121af575f5160206150415f395f51905f5280546001600160a01b031916821790557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2815115612197575f8083602061219595519101845af461218f614e57565b91614f42565b005b5050346121a057005b63b398979f60e01b5f5260045ffd5b634c9c8ce360e01b5f5260045260245ffd5b632a87526960e21b5f5260045260245ffd5b9091506020813d6020116121ff575b816121ef6020938361378b565b81010312610614575190856120f9565b3d91506121e2565b5f5160206150415f395f51905f52546001600160a01b031614159050836120c2565b34610614576020366003190112610614576001600160a01b0361224a61374b565b165f52600f602052602060018060a01b0360405f205416604051908152f35b346106145760203660031901126106145761228261374b565b61228a6142c7565b6001600160a01b038116906122a0821515613ab8565b600e546001600160a01b0316906122b8821515613afc565b6040516370a0823160e01b8152306004820152602081602481875afa90811561199a575f916123c4575b50835f52601260205261230660405f2054855f52601360205260405f205490613c16565b81111561238b578361235f612367927fe603e9649c28b74edd6859199c6264fa2d833d570225c1d29095c0b8a0196c77965f52601260205261235960405f2054845f52601360205260405f205490613c16565b90613a97565b9384916142fa565b604080516001600160a01b039092168252602082019290925290819081015b0390a1005b60405162461bcd60e51b81526020600482015260116024820152706e6f7468696e6720746f2072657363756560781b6044820152606490fd5b90506020813d6020116123ee575b816123df6020938361378b565b810103126106145751846122e2565b3d91506123d2565b34610614576020366003190112610614576004355f52600a602052602060405f2054604051908152f35b34610614575f366003190112610614576124386142c7565b5f5160206150815f395f51905f525460ff81161561248f5760ff19165f5160206150815f395f51905f52557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b638dfc202b60e01b5f5260045ffd5b34610614575f366003190112610614576124b9600c54613be4565b600c545f5b8251811015612529578181101561251557600c5f527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c7810154600191906001600160a01b031661250e8286613bae565b52016124be565b634e487b7160e01b5f52603260045260245ffd5b60405160208082528190610b58908201866137fd565b3461061457604036600319011261061457612558613761565b336001600160a01b038216036125745761219590600435614603565b63334bd91960e11b5f5260045ffd5b34610614575f36600319011261061457602060405160088152f35b346106145760a0366003190112610614576125b761374b565b6125bf613761565b906044356001600160a01b03811690819003610614576064356001600160a01b0381169190829003610614576084356001600160401b03811161061457366023820112156106145761261b9036906024816004013591016137c7565b915f5160206150a15f395f51905f52549460ff8660401c1615956001600160401b03811680159081612d00575b6001149081612cf6575b159081612ced575b50612cde5767ffffffffffffffff1981166001175f5160206150a15f395f51905f525586612cb2575b5061268c614e2c565b612694614e2c565b61269d85614256565b6126a5614e2c565b6126ad613bc2565b6126b5613bc2565b906126be614e2c565b6126c6614e2c565b8051906001600160401b0382116129ea576126ee5f516020614fa15f395f51905f525461389e565b601f8111612c43575b50602090601f8311600114612bc65761272792915f9183612bbb575b50508160011b915f199060031b1c19161790565b5f516020614fa15f395f51905f52555b8051906001600160401b0382116129ea5761275f5f516020614fe15f395f51905f525461389e565b601f8111612b4c575b50602090601f8311600114612acf5761279792915f9183612ac45750508160011b915f199060031b1c19161790565b5f516020614fe15f395f51905f52555b6127af614e2c565b6127b7614e2c565b6127bf614e2c565b60ff195f5160206150815f395f51905f5254165f5160206150815f395f51905f52558215612a88578115612a43576001600160a01b03169182156129fe576001600160601b0360a01b60095416176009556001600160601b0360a01b60075416176007556001600160601b0360a01b60085416176008558051906001600160401b0382116129ea57612852600b5461389e565b601f8111612987575b50602090601f831160011461290057918061288f9261289795945f926128f55750508160011b915f199060031b1c19161790565b600b556144b0565b5061289e57005b68ff0000000000000000195f5160206150a15f395f51905f5254165f5160206150a15f395f51905f52557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b015190508680612713565b90601f19831691600b5f527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9925f5b81811061296f575091600193918561289797969410612957575b505050811b01600b556144b0565b01515f1960f88460031b161c19169055858080612949565b9293602060018192878601518155019501930161292f565b600b5f527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9601f840160051c810191602085106129e0575b601f0160051c01905b8181106129d5575061285b565b5f81556001016129c8565b90915081906129bf565b634e487b7160e01b5f52604160045260245ffd5b60405162461bcd60e51b815260206004820152601960248201527f7a65726f206f72646572207369676e65722061646472657373000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601960248201527f7a65726f2072656465656d20746f6b656e2061646472657373000000000000006044820152606490fd5b60405162461bcd60e51b81526020600482015260146024820152737a65726f20666163746f7279206164647265737360601b6044820152606490fd5b015190508980612713565b90601f198316915f516020614fe15f395f51905f525f52815f20925f5b818110612b345750908460019594939210612b1c575b505050811b015f516020614fe15f395f51905f52556127a7565b01515f1960f88460031b161c19169055888080612b02565b92936020600181928786015181550195019301612aec565b5f516020614fe15f395f51905f525f527f46a2803e59a4de4e7a4c574b1243f25977ac4c77d5a1a4a609b5394cebb4a2aa601f840160051c81019160208510612bb1575b601f0160051c01905b818110612ba65750612768565b5f8155600101612b99565b9091508190612b90565b015190508a80612713565b90601f198316915f516020614fa15f395f51905f525f52815f20925f5b818110612c2b5750908460019594939210612c13575b505050811b015f516020614fa15f395f51905f5255612737565b01515f1960f88460031b161c19169055898080612bf9565b92936020600181928786015181550195019301612be3565b5f516020614fa15f395f51905f525f527f2ae08a8e29253f69ac5d979a101956ab8f8d9d7ded63fa7a83b16fc47648eab0601f840160051c81019160208510612ca8575b601f0160051c01905b818110612c9d57506126f7565b5f8155600101612c90565b9091508190612c87565b68ffffffffffffffffff191668010000000000000001175f5160206150a15f395f51905f525586612683565b63f92ee8a960e01b5f5260045ffd5b9050158861265a565b303b159150612652565b889150612648565b34610614575f366003190112610614576007546040516001600160a01b039091168152602090f35b3461061457604036600319011261061457612195600435612d4f613761565b90612d75610b0b825f525f5160206150615f395f51905f52602052600160405f20015490565b61455f565b34610614576020366003190112610614576004355f52600360205260ff60405f2054166040516005821015611b5a576020918152f35b34610614575f36600319011261061457600554612de5612dcf82613b97565b91612ddd604051938461378b565b808352613b97565b6020820190601f19013682376005545f5b8351811015612e4457818110156125155760055f527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db081015460019190612e3d8287613bae565b5201612df6565b505090604051918291602083019060208452518091526040830191905f5b818110612e70575050500390f35b8251845285945060209384019390920191600101612e62565b3461061457602036600319011261061457600435612ea56142c7565b600954604051631313084160e11b81526004810183905290602090829060249082906001600160a01b03165afa801561199a57612ee8915f91611e3e5750613b58565b612efd815f52600660205260405f2054151590565b15612f2f57602081611c607fd353b91ef24b87233598a495783dabdd9d6b182c6cd964f6ecab24f70df6ea2b93614c17565b60405162461bcd60e51b815260206004820152601860248201527f61737365744944206973206e6f7420737570706f7274656400000000000000006044820152606490fd5b34610614576020366003190112610614576020612fab6004355f525f5160206150615f395f51905f52602052600160405f20015490565b604051908152f35b3461061457606036600319011261061457612fcc61374b565b612fd4613761565b60443590612fe183613839565b335f9081526020919091526040902054925f198410613005575b611139935061433d565b828410613070576001600160a01b0381161561305d57331561304a576111399361302e82613839565b60018060a01b0333165f526020528360405f2091039055612ffb565b634a1406b160e11b5f525f60045260245ffd5b63e602df0560e01b5f525f60045260245ffd5b8284637dc7a0d960e11b5f523360045260245260445260645ffd5b34610614576040366003190112610614576130a461374b565b6130ac613761565b6130b46142c7565b6001600160a01b038116916130ca831515613afc565b6001600160a01b038181165f818152600f602052604090205490949116811461315a5783613136917f30d682126baa75723af317029e67cda86b0334871b273c3f0676e0e475cc2971955f52600f60205260405f20906001600160601b0360a01b825416179055614b2b565b50604080516001600160a01b03928316815292909116602083015281908101612386565b60405162461bcd60e51b81526020600482015260166024820152757661756c7420726f757465206e6f74206368616e676560501b6044820152606490fd5b34610614576020366003190112610614576131b161374b565b6131b96142c7565b6001600160a01b03166131cd811515613ab8565b6131e2815f52600d60205260405f2054151590565b61321357602081611c607fe473c74f34be27c1464d6624f14a0d7fd4e301cbfa29c3eba425d378c8a7ebe093614ac5565b60405162461bcd60e51b815260206004820152601660248201527530b63932b0b23c9031b7b73a30b4b739903a37b5b2b760511b6044820152606490fd5b34610614575f3660031901126106145760205f5160206150215f395f51905f5254604051908152f35b34610614576040366003190112610614576004356024356132996142c7565b6132b1611238835f52600160205260405f2054151590565b815f52600360205260ff60405f2054166005811015611b5a5760016132d69114613a11565b815f52600260205260405f20906132f9600260ff600185015416610d3281613975565b825f52600360205260405f20600360ff1982541617905580155f14613528575060038101546040516370a0823160e01b81523060048201526001600160a01b0390911690602081602481855afa90811561199a575f916134f6575b5060068301548091106134b157600883015461337b926001600160a01b03909116906142fa565b60058101908154305f52601360205261339960405f20918254613a97565b9055600681015490600360018060a01b03910154165f5260136020526133c460405f20918254613a97565b90555490301561349e57305f525f516020614fc15f395f51905f5260205260405f205482811061348357905f837f7ad7174076b297a24f706a24c4f35617b4a2ac4b102f85e9f11654b46cd31512946020943084525f516020614fc15f395f51905f528652036040832055805f5160206150215f395f51905f5254035f5160206150215f395f51905f52556040519081527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef843092a3604051908152a1005b905063391434e360e21b5f523060045260245260445260645ffd5b634b637e8f60e11b5f525f60045260245ffd5b60405162461bcd60e51b815260206004820152601760248201527f6e6f7420656e6f7567682072656465656d20746f6b656e0000000000000000006044820152606490fd5b90506020813d602011613520575b816135116020938361378b565b81010312610614575184613354565b3d9150613504565b825f52600a60205260405f205561337b565b346106145760403660031901126106145761355361374b565b60243590331561305d576001600160a01b031690811561304a5761357633613839565b825f526020528060405f20556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b34610614575f366003190112610614576020604051620151808152f35b34610614575f366003190112610614576040515f5f516020614fa15f395f51905f52546136028161389e565b8084529060018116908115613694575060011461362a575b610b5883610b448185038261378b565b5f516020614fa15f395f51905f525f9081527f2ae08a8e29253f69ac5d979a101956ab8f8d9d7ded63fa7a83b16fc47648eab0939250905b80821061367a57509091508101602001610b4461361a565b919260018160209254838588010152019101909291613662565b60ff191660208086019190915291151560051b84019091019150610b44905061361a565b34610614575f3660031901126106145760205f54604051908152f35b34610614576020366003190112610614576004359063ffffffff60e01b821680920361061457602091637965db0b60e01b8114908115613716575b5015158152f35b6301ffc9a760e01b1490508361370f565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b600435906001600160a01b038216820361061457565b602435906001600160a01b038216820361061457565b35906001600160a01b038216820361061457565b90601f801991011681019081106001600160401b038211176129ea57604052565b6001600160401b0381116129ea57601f01601f191660200190565b9291926137d3826137ac565b916137e1604051938461378b565b829481845281830111610614578281602093845f960137010152565b90602080835192838152019201905f5b81811061381a5750505090565b82516001600160a01b031684526020938401939092019160010161380d565b6001600160a01b03165f9081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020526040902090565b9181601f84011215610614578235916001600160401b038311610614576020838186019501011161061457565b90600182811c921680156138cc575b60208310146138b857565b634e487b7160e01b5f52602260045260245ffd5b91607f16916138ad565b600b545f92916138e58261389e565b80825291600181169081156139595750600114613900575050565b600b5f9081529293509091907f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db95b83831061393f575060209250010190565b60018160209294939454838587010152019101919061392e565b9050602093945060ff929192191683830152151560051b010190565b60041115611b5a57565b906040600319830112610614576004356001600160401b0381116106145761018081840360031901126106145760040191602435906001600160401b038211610614576139ce91600401613871565b9091565b156139d957565b60405162461bcd60e51b815260206004820152601060248201526f6f72646572206e6f742065786973747360801b6044820152606490fd5b15613a1857565b60405162461bcd60e51b81526020600482015260146024820152736f72646572206973206e6f742070656e64696e6760601b6044820152606490fd5b15613a5b57565b60405162461bcd60e51b81526020600482015260146024820152730dee4c8cae440e8f2e0ca40dcdee840dac2e8c6d60631b6044820152606490fd5b91908203918211613aa457565b634e487b7160e01b5f52601160045260245ffd5b15613abf57565b60405162461bcd60e51b8152602060048201526015602482015274746f6b656e206973207a65726f206164647265737360581b6044820152606490fd5b15613b0357565b60405162461bcd60e51b81526020600482015260156024820152747661756c74206973207a65726f206164647265737360581b6044820152606490fd5b90816020910312610614575180151581036106145790565b15613b5f57565b60405162461bcd60e51b815260206004820152601060248201526f6173736574206e6f742065786973747360801b6044820152606490fd5b6001600160401b0381116129ea5760051b60200190565b80518210156125155760209160051b010190565b60405190613bd160408361378b565b60048252635553534960e01b6020830152565b90613bee82613b97565b613bfb604051918261378b565b8281528092613c0c601f1991613b97565b0190602036910137565b91908201809211613aa457565b6001600160a01b039081165f818152600f602052604090205490911615613c5e575f908152600f60205260409020546001600160a01b031690565b50600e546001600160a01b031690565b9081602091031261061457516001600160a01b03811681036106145790565b903590601e198136030182121561061457018035906001600160401b0382116106145760200191813603831361061457565b908060209392818452848401375f828201840152601f01601f1916010190565b356001600160a01b03811681036106145790565b929192604051602081019060208252613d12816103c6604082016138d6565b519020613d406103c6613d258480613c8d565b92906040519283916020830195602087526040840191613cbf565b5190200361406c576020810135600481101561061457613d5f81613975565b801561403257613d6e81613975565b60018114613fd8575b613d8081613975565b60028114613f12575b600390613d9581613975565b14613e8b575b60e001354211613e5c57613dba815f52600160205260405f2054151590565b613e2057613dd8613dde9360018060a01b03600854169336916137c7565b9161469f565b15613de557565b60405162461bcd60e51b81526020600482015260136024820152721cda59db985d1d5c99481b9bdd081d985b1a59606a1b6044820152606490fd5b60405162461bcd60e51b81526020600482015260146024820152736f7264657220616c72656164792065786973747360601b6044820152606490fd5b60405162461bcd60e51b8152602060048201526007602482015266195e1c1a5c995960ca1b6044820152606490fd5b613ed36101408201613eaf6001600160a01b03613ea783613cdf565b161515613ab8565b6001600160a01b0390613ec190613cdf565b165f52600d60205260405f2054151590565b613d9b5760405162461bcd60e51b81526020600482015260136024820152721d1bdad95b881b9bdd081cdd5c1c1bdc9d1959606a1b6044820152606490fd5b6001600160a01b03613f276101208401613cdf565b1615613f93576007546001600160a01b0390811690613f4860608501613cdf565b1614613d895760405162461bcd60e51b815260206004820152601a60248201527f72656465656d20746f6b656e206e6f7420737570706f727465640000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601860248201527f7265636569766572206973207a65726f206164647265737300000000000000006044820152606490fd5b613ff160408301355f52600660205260405f2054151590565b613d775760405162461bcd60e51b8152602060048201526015602482015274185cdcd95d1251081b9bdd081cdd5c1c1bdc9d1959605a1b6044820152606490fd5b60405162461bcd60e51b81526020600482015260126024820152716f726465722074797065206973206e6f6e6560701b6044820152606490fd5b60405162461bcd60e51b815260206004820152600f60248201526e0c6d0c2d2dc40dcdee840dac2e8c6d608b1b6044820152606490fd5b156140aa57565b60405162461bcd60e51b815260206004820152601b60248201527f6d73672073656e646572206973206e6f742072657175657374657200000000006044820152606490fd5b602081528135601e19833603018112156106145782016020813591016001600160401b038211610614578136038113610614576141399161018060208501526101a0840191613cbf565b916020810135906004821015610614578161415661018093613975565b60408401526040810135606084015260018060a01b0361417860608301613777565b166080840152608081013560a084015260a081013560c084015260c081013560e084015260e081013561010084015260018060a01b036141bb6101008301613777565b1661012084015260018060a01b036141d66101208301613777565b1661014084015260018060a01b036141f16101408301613777565b1661016084015261420c61016060018060a01b039201613777565b1691015290565b1561421a57565b60405162461bcd60e51b81526020600482015260146024820152736e6f7420656e6f75676820616c6c6f77616e636560601b6044820152606490fd5b6001600160a01b031680156142b4575f5160206150015f395f51905f5280546001600160a01b0319811683179091556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b631e4fbdf760e01b5f525f60045260245ffd5b5f5160206150015f395f51905f52546001600160a01b031633036142e757565b63118cdaa760e01b5f523360045260245ffd5b60405163a9059cbb60e01b60208201526001600160a01b0392909216602483015260448083019390935291815261433b9161433660648361378b565b614a2a565b565b6001600160a01b031690811561349e576001600160a01b0316918215611b4757815f525f516020614fc15f395f51905f5260205260405f20548181106143e257817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f516020614fc15f395f51905f5284520360405f2055845f525f516020614fc15f395f51905f52825260405f20818154019055604051908152a3565b8263391434e360e21b5f5260045260245260445260645ffd5b335f9081527fccf616fcc782ae4975b4090604ebc6d6877b665e3ab61c33e0108a88b1f19746602052604090205460ff161561443357565b63e2517d3f60e01b5f52336004527f938c45fe3baa5cbd047f2473358a27f57db22291e9af95379a15ad016886dfb760245260445ffd5b5f8181525f5160206150615f395f51905f526020908152604080832033845290915290205460ff161561449a5750565b63e2517d3f60e01b5f523360045260245260445ffd5b6001600160a01b0381165f9081527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d602052604090205460ff1661455a576001600160a01b03165f8181527fb7db2dd08fcb62d0c9e08c51941cae53c267786a0b75803fb7960902fc8ef97d60205260408120805460ff191660011790553391907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d8180a4600190565b505f90565b5f8181525f5160206150615f395f51905f52602090815260408083206001600160a01b038616845290915290205460ff166145fd575f8181525f5160206150615f395f51905f52602090815260408083206001600160a01b0395909516808452949091528120805460ff19166001179055339291907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9080a4600190565b50505f90565b5f8181525f5160206150615f395f51905f52602090815260408083206001600160a01b038616845290915290205460ff16156145fd575f8181525f5160206150615f395f51905f52602090815260408083206001600160a01b0395909516808452949091528120805460ff19169055339291907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9080a4600190565b9190823b6146da57906146b191614e86565b506146bb81613975565b1591826146c757505090565b6001600160a01b03918216911614919050565b915f926103c661471085946040519283916020830195630b135d3f60e11b87526024840152604060448401526064830190613727565b51915afa61471c614e57565b8161474d575b8161472b575090565b80516020808301935090820191909103126106145751630b135d3f60e11b1490565b905060208151101590614722565b60ff5f5160206150815f395f51905f52541661477357565b63d93c066560e01b5f5260045ffd5b805f52600260205260405f206147988380613c8d565b906001600160401b0382116129ea576147b1835461389e565b601f81116149a1575b505f90601f831160011461493d576147e892915f91836149325750508160011b915f199060031b1c19161790565b81555b602083013560048110156106145761490b61016061492f95600b93600186019061481481613975565b815460ff191660ff9190911617905560408101356002860155600780546003870180546001600160a01b039092166001600160a01b03199092169190911790556080820135600487015560a0820135600587015560c0820135600687015560e0820135908601556148886101008201613cdf565b6008860180546001600160a01b0319166001600160a01b039092169190911790556148b66101208201613cdf565b6009860180546001600160a01b0319166001600160a01b039092169190911790556148e46101408201613cdf565b600a860180546001600160a01b0319166001600160a01b0390921691909117905501613cdf565b910180546001600160a01b0319166001600160a01b03909216919091179055614bcb565b50565b013590505f80612713565b601f19831691845f5260205f20925f5b8181106149895750908460019594939210614970575b505050811b0181556147eb565b01355f19600384901b60f8161c191690555f8080614963565b9193602060018192878701358155019501920161494d565b835f5260205f20601f840160051c810191602085106149dc575b601f0160051c01905b8181106149d157506147ba565b5f81556001016149c4565b90915081906149bb565b6040516323b872dd60e01b60208201526001600160a01b03928316602482015292909116604483015260648083019390935291815261433b9161433660848361378b565b905f602091828151910182855af11561199a575f513d614a7957506001600160a01b0381163b155b614a595750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b60011415614a52565b6010548110156125155760105f5260205f2001905f90565b5f54811015612515575f805260205f2001905f90565b8054821015612515575f5260205f2001905f90565b805f52600d60205260405f2054155f1461455a57600c54600160401b8110156129ea57614b14614afe826001859401600c55600c614ab0565b819391549060031b91821b915f19901b19161790565b9055600c54905f52600d60205260405f2055600190565b805f52601160205260405f2054155f1461455a57601054600160401b8110156129ea57614b64614afe8260018594016010556010614ab0565b9055601054905f52601160205260405f2055600190565b805f52600660205260405f2054155f1461455a57600554600160401b8110156129ea57614bb4614afe8260018594016005556005614ab0565b9055600554905f52600660205260405f2055600190565b805f52600160205260405f2054155f1461455a575f54600160401b8110156129ea57614c01614afe8260018594015f555f614ab0565b90555f54905f52600160205260405f2055600190565b5f8181526006602052604090205480156145fd575f198101818111613aa4576005545f19810191908211613aa457818103614c9e575b5050506005548015614c8a575f1901614c67816005614ab0565b8154905f199060031b1b191690556005555f5260066020525f6040812055600190565b634e487b7160e01b5f52603160045260245ffd5b614cc0614caf614afe936005614ab0565b90549060031b1c9283926005614ab0565b90555f52600660205260405f20555f8080614c4d565b5f8181526011602052604090205480156145fd575f198101818111613aa4576010545f19810191908211613aa457818103614d49575b5050506010548015614c8a575f1901614d26816010614ab0565b8154905f199060031b1b191690556010555f5260116020525f6040812055600190565b614d6b614d5a614afe936010614ab0565b90549060031b1c9283926010614ab0565b90555f52601160205260405f20555f8080614d0c565b5f818152600d602052604090205480156145fd575f198101818111613aa457600c545f19810191908211613aa457818103614df4575b505050600c548015614c8a575f1901614dd181600c614ab0565b8154905f199060031b1b19169055600c555f52600d6020525f6040812055600190565b614e16614e05614afe93600c614ab0565b90549060031b1c928392600c614ab0565b90555f52600d60205260405f20555f8080614db7565b60ff5f5160206150a15f395f51905f525460401c1615614e4857565b631afcd79f60e31b5f5260045ffd5b3d15614e81573d90614e68826137ac565b91614e76604051938461378b565b82523d5f602084013e565b606090565b8151919060418303614eb657614eaf9250602082015190606060408401519301515f1a90614ec0565b9192909190565b50505f9160029190565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411614f37579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa1561199a575f516001600160a01b03811615614f2d57905f905f90565b505f906001905f90565b5050505f9160039190565b90614f665750805115614f5757805190602001fd5b63d6bda27560e01b5f5260045ffd5b81511580614f97575b614f77575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b15614f6f56fe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0352c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0052c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace049016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930052c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800cd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212209899a8da5b0b749f923a81f67c991aa5a13a110221aee65cff471850b120aeb964736f6c634300081c0033
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.