Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Loading...
Loading
Contract Name:
NFTLibV1
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
/*
Copyright 2023 Wanchain Foundation.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// _ _ _
// __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __
// \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / /
// \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V /
// \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/
//
//
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "./RapidityTxLib.sol";
import "./CrossTypes.sol";
import "../../interfaces/ITokenManager.sol";
import "./EtherTransfer.sol";
/**
* @title NFTLibV1
* @dev Library for managing NFT cross-chain operations
* This library provides functionality for:
* - NFT locking and unlocking
* - NFT minting and burning
* - Cross-chain NFT transfer management
*/
library NFTLibV1 {
using SafeMath for uint;
using RapidityTxLib for RapidityTxLib.Data;
/**
* @notice Enumeration of supported token types for cross-chain operations
* @dev Defines the types of tokens that can be transferred across chains
*/
enum TokenCrossType {ERC20, ERC721, ERC1155}
/**
* @notice Parameters for user-initiated NFT locking operations
* @dev Used when users want to lock their NFTs for cross-chain transfer
* @param smgID ID of the selected storeman group
* @param tokenPairID ID of the token pair for cross-chain transfer
* @param tokenIDs Array of NFT token IDs to be locked
* @param tokenValues Array of NFT token values (for ERC1155)
* @param currentChainID ID of the current blockchain
* @param tokenPairContractFee Fee for the token pair contract
* @param etherTransferGasLimit Gas limit for ether transfers
* @param destUserAccount Destination user account address
* @param smgFeeProxy Address of the proxy for storing storeman group fees
*/
struct RapidityUserLockNFTParams {
bytes32 smgID; /// ID of storeman group which user has selected
uint tokenPairID; /// token pair id on cross chain
uint[] tokenIDs; /// NFT token Ids
uint[] tokenValues; /// NFT token values
uint currentChainID; /// current chain ID
uint tokenPairContractFee; /// fee of token pair
uint etherTransferGasLimit; /// exchange token fee
bytes destUserAccount; /// account of shadow chain, used to receive token
address smgFeeProxy; /// address of the proxy to store fee for storeman group
}
/**
* @notice Parameters for storeman-initiated NFT minting operations
* @dev Used when storeman group mints NFTs on the destination chain
* @param uniqueID Unique identifier for the rapidity transaction
* @param smgID ID of the storeman group
* @param tokenPairID ID of the token pair
* @param tokenIDs Array of NFT token IDs to be minted
* @param tokenValues Array of NFT token values (for ERC1155)
* @param extData Additional data for storeman operations
* @param destTokenAccount Destination token contract address
* @param destUserAccount Destination user account address
*/
struct RapiditySmgMintNFTParams {
bytes32 uniqueID; /// Rapidity random number
bytes32 smgID; /// ID of storeman group which user has selected
uint tokenPairID; /// token pair id on cross chain
uint[] tokenIDs; /// NFT token Ids
uint[] tokenValues; /// NFT token values
bytes extData; /// storeman data
address destTokenAccount; /// shadow token account
address destUserAccount; /// account of shadow chain, used to receive token
}
/**
* @notice Parameters for user-initiated NFT burning operations
* @dev Used when users want to burn their NFTs for cross-chain transfer
* @param smgID ID of the selected storeman group
* @param tokenPairID ID of the token pair
* @param tokenIDs Array of NFT token IDs to be burned
* @param tokenValues Array of NFT token values (for ERC1155)
* @param currentChainID ID of the current blockchain
* @param tokenPairContractFee Fee for the token pair contract
* @param etherTransferGasLimit Gas limit for ether transfers
* @param srcTokenAccount Source token contract address
* @param destUserAccount Destination user account address
* @param smgFeeProxy Address of the proxy for storing storeman group fees
*/
struct RapidityUserBurnNFTParams {
bytes32 smgID; /// ID of storeman group which user has selected
uint tokenPairID; /// token pair id on cross chain
uint[] tokenIDs; /// NFT token Ids
uint[] tokenValues; /// NFT token values
uint currentChainID; /// current chain ID
uint tokenPairContractFee; /// fee of token pair
uint etherTransferGasLimit; /// exchange token fee
address srcTokenAccount; /// shadow token account
bytes destUserAccount; /// account of token destination chain, used to receive token
address smgFeeProxy; /// address of the proxy to store fee for storeman group
}
/**
* @notice Parameters for storeman-initiated NFT release operations
* @dev Used when storeman group releases NFTs on the original chain
* @param uniqueID Unique identifier for the rapidity transaction
* @param smgID ID of the storeman group
* @param tokenPairID ID of the token pair
* @param tokenIDs Array of NFT token IDs to be released
* @param tokenValues Array of NFT token values (for ERC1155)
* @param destTokenAccount Destination token contract address
* @param destUserAccount Destination user account address
*/
struct RapiditySmgReleaseNFTParams {
bytes32 uniqueID; /// Rapidity random number
bytes32 smgID; /// ID of storeman group which user has selected
uint tokenPairID; /// token pair id on cross chain
uint[] tokenIDs; /// NFT token Ids
uint[] tokenValues; /// NFT token values
address destTokenAccount; /// original token/coin account
address destUserAccount; /// account of token original chain, used to receive token
}
/**
* @notice Event emitted when NFTs are locked by a user
* @param smgID ID of the storeman group
* @param tokenPairID ID of the token pair
* @param tokenAccount Address of the token contract
* @param keys Array of event keys
* @param values Array of event values
*/
event UserLockNFT(bytes32 indexed smgID, uint indexed tokenPairID, address indexed tokenAccount, string[] keys, bytes[] values);
/**
* @notice Event emitted when NFTs are burned by a user
* @param smgID ID of the storeman group
* @param tokenPairID ID of the token pair
* @param tokenAccount Address of the token contract
* @param keys Array of event keys
* @param values Array of event values
*/
event UserBurnNFT(bytes32 indexed smgID, uint indexed tokenPairID, address indexed tokenAccount, string[] keys, bytes[] values);
/**
* @notice Event emitted when NFTs are minted by storeman group
* @param uniqueID Unique identifier for the rapidity transaction
* @param smgID ID of the storeman group
* @param tokenPairID ID of the token pair
* @param keys Array of event keys
* @param values Array of event values
*/
event SmgMintNFT(bytes32 indexed uniqueID, bytes32 indexed smgID, uint indexed tokenPairID, string[] keys, bytes[] values);
/**
* @notice Event emitted when NFTs are released by storeman group
* @param uniqueID Unique identifier for the rapidity transaction
* @param smgID ID of the storeman group
* @param tokenPairID ID of the token pair
* @param keys Array of event keys
* @param values Array of event values
*/
event SmgReleaseNFT(bytes32 indexed uniqueID, bytes32 indexed smgID, uint indexed tokenPairID, string[] keys, bytes[] values);
/**
* @notice Gets the token contract address and contract fee for a token pair
* @dev Calculates the appropriate contract fee based on chain IDs and batch size
* @param storageData Cross storage data
* @param tokenPairID ID of the token pair
* @param tokenPairContractFee Fee for the token pair contract
* @param currentChainID ID of the current blockchain
* @param batchLength Length of the batch operation
* @return tokenScAddr Address of the token contract
* @return contractFee Calculated contract fee
* Requirements:
* - Token pair must exist
* - Current chain ID must be valid
*/
function getTokenScAddrAndContractFee(CrossTypes.Data storage storageData, uint tokenPairID, uint tokenPairContractFee, uint currentChainID, uint batchLength)
public
view
returns (address, uint)
{
ITokenManager tokenManager = storageData.tokenManager;
uint fromChainID;
uint toChainID;
bytes memory fromTokenAccount;
bytes memory toTokenAccount;
(fromChainID,fromTokenAccount,toChainID,toTokenAccount) = tokenManager.getTokenPairInfo(tokenPairID);
require(fromChainID != 0, "Token does not exist");
uint contractFee = tokenPairContractFee;
address tokenScAddr;
if (currentChainID == fromChainID) {
if (contractFee == 0) {
contractFee = storageData.mapContractFee[fromChainID][toChainID];
}
if (contractFee == 0) {
contractFee = storageData.mapContractFee[fromChainID][0];
}
tokenScAddr = CrossTypes.bytesToAddress(fromTokenAccount);
} else if (currentChainID == toChainID) {
if (contractFee == 0) {
contractFee = storageData.mapContractFee[toChainID][fromChainID];
}
if (contractFee == 0) {
contractFee = storageData.mapContractFee[toChainID][0];
}
tokenScAddr = CrossTypes.bytesToAddress(toTokenAccount);
} else {
require(false, "Invalid token pair");
}
if (contractFee > 0) {
contractFee = contractFee.mul(9 + batchLength).div(10);
}
return (tokenScAddr, contractFee);
}
/**
* @notice Locks NFTs for cross-chain transfer
* @dev Handles the locking of ERC721 and ERC1155 tokens
* @param storageData Cross storage data
* @param params Parameters for the NFT locking operation
* Requirements:
* - NFT type must be valid (ERC721 or ERC1155)
* - User must have sufficient balance
* - Contract must have approval to transfer tokens
*/
function userLockNFT(CrossTypes.Data storage storageData, RapidityUserLockNFTParams memory params)
public
{
address tokenScAddr;
uint contractFee;
(tokenScAddr, contractFee) = getTokenScAddrAndContractFee(storageData, params.tokenPairID, params.tokenPairContractFee, params.currentChainID, params.tokenIDs.length);
if (contractFee > 0) {
EtherTransfer.sendValue(payable(params.smgFeeProxy), contractFee, params.etherTransferGasLimit);
}
uint left = (msg.value).sub(contractFee);
uint8 tokenCrossType = storageData.tokenManager.mapTokenPairType(params.tokenPairID);
if (tokenCrossType == uint8(TokenCrossType.ERC721)) {
for(uint idx = 0; idx < params.tokenIDs.length; ++idx) {
IERC721(tokenScAddr).safeTransferFrom(msg.sender, address(this), params.tokenIDs[idx], "");
}
} else if(tokenCrossType == uint8(TokenCrossType.ERC1155)) {
IERC1155(tokenScAddr).safeBatchTransferFrom(msg.sender, address(this), params.tokenIDs, params.tokenValues, "");
}
else{
require(false, "Invalid NFT type");
}
if (left != 0) {
EtherTransfer.sendValue(payable(msg.sender), left, params.etherTransferGasLimit);
}
string[] memory keys = new string[](4);
bytes[] memory values = new bytes[](4);
keys[0] = "tokenIDs:uint256[]";
values[0] = abi.encode(params.tokenIDs);
keys[1] = "tokenValues:uint256[]";
values[1] = abi.encode(params.tokenValues);
keys[2] = "userAccount:bytes";
values[2] = params.destUserAccount;
keys[3] = "contractFee:uint256";
values[3] = abi.encodePacked(contractFee);
emit UserLockNFT(params.smgID, params.tokenPairID, tokenScAddr, keys, values);
}
/**
* @notice Burns NFTs for cross-chain transfer
* @dev Handles the burning of ERC721 and ERC1155 tokens
* @param storageData Cross storage data
* @param params Parameters for the NFT burning operation
* Requirements:
* - NFT type must be valid (ERC721 or ERC1155)
* - User must have sufficient balance
* - Contract must have approval to burn tokens
*/
function userBurnNFT(CrossTypes.Data storage storageData, RapidityUserBurnNFTParams memory params)
public
{
address tokenScAddr;
uint contractFee;
(tokenScAddr, contractFee) = getTokenScAddrAndContractFee(storageData, params.tokenPairID, params.tokenPairContractFee, params.currentChainID, params.tokenIDs.length);
ITokenManager tokenManager = storageData.tokenManager;
uint8 tokenCrossType = tokenManager.mapTokenPairType(params.tokenPairID);
require((tokenCrossType == uint8(TokenCrossType.ERC721) || tokenCrossType == uint8(TokenCrossType.ERC1155)), "Invalid NFT type");
ITokenManager(tokenManager).burnNFT(uint(tokenCrossType), tokenScAddr, msg.sender, params.tokenIDs, params.tokenValues);
if (contractFee > 0) {
EtherTransfer.sendValue(payable(params.smgFeeProxy), contractFee, params.etherTransferGasLimit);
}
uint left = (msg.value).sub(contractFee);
if (left != 0) {
EtherTransfer.sendValue(payable(msg.sender), left, params.etherTransferGasLimit);
}
string[] memory keys = new string[](4);
bytes[] memory values = new bytes[](4);
keys[0] = "tokenIDs:uint256[]";
values[0] = abi.encode(params.tokenIDs);
keys[1] = "tokenValues:uint256[]";
values[1] = abi.encode(params.tokenValues);
keys[2] = "userAccount:bytes";
values[2] = params.destUserAccount;
keys[3] = "contractFee:uint256";
values[3] = abi.encodePacked(contractFee);
emit UserBurnNFT(params.smgID, params.tokenPairID, tokenScAddr, keys, values);
}
/**
* @notice Mints NFTs on the destination chain
* @dev Handles the minting of ERC721 and ERC1155 tokens
* @param storageData Cross storage data
* @param params Parameters for the NFT minting operation
* Requirements:
* - NFT type must be valid (ERC721 or ERC1155)
* - Storeman group must have permission to mint
*/
function smgMintNFT(CrossTypes.Data storage storageData, RapiditySmgMintNFTParams memory params)
public
{
storageData.rapidityTxData.addRapidityTx(params.uniqueID);
ITokenManager tokenManager = storageData.tokenManager;
uint8 tokenCrossType = tokenManager.mapTokenPairType(params.tokenPairID);
require((tokenCrossType == uint8(TokenCrossType.ERC721) || tokenCrossType == uint8(TokenCrossType.ERC1155)), "Invalid NFT type");
ITokenManager(tokenManager).mintNFT(uint(tokenCrossType), params.destTokenAccount, params.destUserAccount, params.tokenIDs, params.tokenValues, params.extData);
string[] memory keys = new string[](5);
bytes[] memory values = new bytes[](5);
keys[0] = "tokenIDs:uint256[]";
values[0] = abi.encode(params.tokenIDs);
keys[1] = "tokenValues:uint256[]";
values[1] = abi.encode(params.tokenValues);
keys[2] = "tokenAccount:address";
values[2] = abi.encodePacked(params.destTokenAccount);
keys[3] = "userAccount:address";
values[3] = abi.encodePacked(params.destUserAccount);
keys[4] = "extData:bytes";
values[4] = params.extData;
emit SmgMintNFT(params.uniqueID, params.smgID, params.tokenPairID, keys, values);
}
/**
* @notice Releases NFTs on the original chain
* @dev Handles the release of ERC721 and ERC1155 tokens
* @param storageData Cross storage data
* @param params Parameters for the NFT release operation
* Requirements:
* - NFT type must be valid (ERC721 or ERC1155)
* - Storeman group must have permission to release
*/
function smgReleaseNFT(CrossTypes.Data storage storageData, RapiditySmgReleaseNFTParams memory params)
public
{
storageData.rapidityTxData.addRapidityTx(params.uniqueID);
uint8 tokenCrossType = storageData.tokenManager.mapTokenPairType(params.tokenPairID);
if (tokenCrossType == uint8(TokenCrossType.ERC721)) {
for(uint idx = 0; idx < params.tokenIDs.length; ++idx) {
IERC721(params.destTokenAccount).safeTransferFrom(address(this), params.destUserAccount, params.tokenIDs[idx], "");
}
}
else if(tokenCrossType == uint8(TokenCrossType.ERC1155)) {
IERC1155(params.destTokenAccount).safeBatchTransferFrom(address(this), params.destUserAccount, params.tokenIDs, params.tokenValues, "");
}
else {
require(false, "Invalid NFT type");
}
string[] memory keys = new string[](4);
bytes[] memory values = new bytes[](4);
keys[0] = "tokenIDs:uint256[]";
values[0] = abi.encode(params.tokenIDs);
keys[1] = "tokenValues:uint256[]";
values[1] = abi.encode(params.tokenValues);
keys[2] = "tokenAccount:address";
values[2] = abi.encodePacked(params.destTokenAccount);
keys[3] = "userAccount:address";
values[3] = abi.encodePacked(params.destUserAccount);
emit SmgReleaseNFT(params.uniqueID, params.smgID, params.tokenPairID, keys, values);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*
* _Available since v3.1._
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the amount of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(
address[] calldata accounts,
uint256[] calldata ids
) external view returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}// SPDX-License-Identifier: MIT
/*
Copyright 2023 Wanchain Foundation.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// _ _ _
// __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __
// \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / /
// \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V /
// \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/
//
//
pragma solidity ^0.8.18;
import "../../interfaces/IRC20Protocol.sol";
import "../../interfaces/IQuota.sol";
import "../../interfaces/IStoremanGroup.sol";
import "../../interfaces/ITokenManager.sol";
import "../../interfaces/ISignatureVerifier.sol";
import "./HTLCTxLib.sol";
import "./RapidityTxLib.sol";
/**
* @title CrossTypes
* @dev Library containing common types and utilities for cross-chain operations
* This library provides:
* - Data structures for cross-chain transactions
* - Utility functions for address and token operations
*/
library CrossTypes {
using SafeMath for uint;
/**
* @notice Main data structure for cross-chain operations
* @dev Contains all necessary data and mappings for cross-chain functionality
*/
struct Data {
/**
* @notice HTLC transaction data storage
* @dev Stores information about Hash Time-Locked Contract transactions
*/
HTLCTxLib.Data htlcTxData;
/**
* @notice Rapidity transaction data storage
* @dev Stores information about rapid cross-chain transactions
*/
RapidityTxLib.Data rapidityTxData;
/**
* @notice Quota management interface for storeman group
* @dev Handles quota allocation and management for storeman groups
*/
IQuota quota;
/**
* @notice Token management interface
* @dev Handles token pair management and cross-chain token operations
*/
ITokenManager tokenManager;
/**
* @notice Storeman group admin interface
* @dev Manages storeman group administration and configuration
*/
IStoremanGroup smgAdminProxy;
/**
* @notice Storeman group fee admin address
* @dev Address responsible for managing storeman group fees
*/
address smgFeeProxy;
/**
* @notice Signature verification interface
* @dev Handles signature verification for cross-chain transactions
*/
ISignatureVerifier sigVerifier;
/**
* @notice Mapping of storeman group fees
* @dev Maps storeman group IDs to their respective fees
*/
mapping(bytes32 => uint) mapStoremanFee;
/**
* @notice Mapping of contract fees between chains
* @dev Maps source chain ID and destination chain ID to contract fees
*/
mapping(uint => mapping(uint =>uint)) mapContractFee;
/**
* @notice Mapping of agent fees between chains
* @dev Maps source chain ID and destination chain ID to agent fees
*/
mapping(uint => mapping(uint =>uint)) mapAgentFee;
}
/**
* @notice Converts bytes to address
* @dev Uses assembly to efficiently convert bytes to address
* @param b Bytes to convert
* @return addr The converted address
*/
function bytesToAddress(bytes memory b) internal pure returns (address addr) {
assembly {
addr := mload(add(b,20))
}
}
/**
* @notice Transfers tokens from the contract to a specified address
* @dev Verifies the transfer was successful by checking balance changes
* @param tokenScAddr Address of the token contract
* @param to Address to receive the tokens
* @param value Amount of tokens to transfer
* @return bool True if transfer was successful
* Requirements:
* - Transfer must succeed
* - Balance change must match the transfer amount
*/
function transfer(address tokenScAddr, address to, uint value)
internal
returns(bool)
{
uint beforeBalance;
uint afterBalance;
IRC20Protocol token = IRC20Protocol(tokenScAddr);
beforeBalance = token.balanceOf(to);
(bool success,) = tokenScAddr.call(abi.encodeWithSelector(token.transfer.selector, to, value));
require(success, "transfer failed");
afterBalance = token.balanceOf(to);
return afterBalance == beforeBalance.add(value);
}
/**
* @notice Transfers tokens from one address to another
* @dev Verifies the transfer was successful by checking balance changes
* @param tokenScAddr Address of the token contract
* @param from Address to transfer tokens from
* @param to Address to receive the tokens
* @param value Amount of tokens to transfer
* @return bool True if transfer was successful
* Requirements:
* - Transfer must succeed
* - Balance change must match the transfer amount
*/
function transferFrom(address tokenScAddr, address from, address to, uint value)
internal
returns(bool)
{
uint beforeBalance;
uint afterBalance;
IRC20Protocol token = IRC20Protocol(tokenScAddr);
beforeBalance = token.balanceOf(to);
(bool success,) = tokenScAddr.call(abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
require(success, "transferFrom failed");
afterBalance = token.balanceOf(to);
return afterBalance == beforeBalance.add(value);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;
/**
* @title EtherTransfer
* @dev Library for safe ether transfer operations
* This library provides a safer alternative to Solidity's native transfer function
* by allowing custom gas limits and better error handling
*/
library EtherTransfer {
/**
* @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/2023/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount, uint256 gasLimit) internal {
require(address(this).balance >= amount, "EtherTransfer: insufficient balance");
(bool success, ) = recipient.call{value: amount, gas: gasLimit}("");
require(success, "EtherTransfer: unable to send value, recipient may have reverted");
}
}// SPDX-License-Identifier: MIT
/*
Copyright 2023 Wanchain Foundation.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// _ _ _
// __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __
// \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / /
// \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V /
// \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/
//
//
pragma solidity ^0.8.18;
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
/**
* @title HTLCTxLib
* @dev Library for managing Hash Time-Locked Contract (HTLC) transactions
* This library provides functionality for:
* - User and storeman transaction management
* - Debt management between storeman groups
* - Transaction status tracking and verification
*/
library HTLCTxLib {
using SafeMath for uint;
/**
* @notice Enumeration of possible transaction statuses
* @dev Status flow:
* - None: Initial state
* - Locked: Transaction is locked and pending
* - Redeemed: Transaction has been completed
* - Revoked: Transaction has been cancelled
* - AssetLocked: Asset is locked in debt management
* - DebtLocked: Debt is locked in debt management
*/
enum TxStatus {None, Locked, Redeemed, Revoked, AssetLocked, DebtLocked}
/**
* @notice Parameters for user-initiated HTLC transactions
* @dev Used when creating new user transactions
* @param xHash Hash of the HTLC random number
* @param smgID ID of the selected storeman group
* @param tokenPairID ID of the token pair for cross-chain transfer
* @param value Amount of tokens to transfer
* @param lockFee Fee for the lock operation
* @param lockedTime Duration for which the transaction is locked
*/
struct HTLCUserParams {
bytes32 xHash;
bytes32 smgID;
uint tokenPairID;
uint value;
uint lockFee;
uint lockedTime;
}
/**
* @notice Base structure for all HTLC transactions
* @dev Contains common fields for all transaction types
* @param smgID ID of the storeman group
* @param lockedTime Duration for which the transaction is locked
* @param beginLockedTime Timestamp when the transaction was locked
* @param status Current status of the transaction
*/
struct BaseTx {
bytes32 smgID;
uint lockedTime;
uint beginLockedTime;
TxStatus status;
}
/**
* @notice Structure for user-initiated transactions
* @dev Extends BaseTx with user-specific information
* @param baseTx Base transaction information
* @param tokenPairID ID of the token pair
* @param value Amount of tokens
* @param fee Transaction fee
* @param userAccount Address of the user initiating the transaction
*/
struct UserTx {
BaseTx baseTx;
uint tokenPairID;
uint value;
uint fee;
address userAccount;
}
/**
* @notice Structure for storeman-initiated transactions
* @dev Extends BaseTx with storeman-specific information
* @param baseTx Base transaction information
* @param tokenPairID ID of the token pair
* @param value Amount of tokens
* @param userAccount Address of the user to receive tokens
*/
struct SmgTx {
BaseTx baseTx;
uint tokenPairID;
uint value;
address userAccount;
}
/**
* @notice Structure for storeman debt transactions
* @dev Extends BaseTx with debt-specific information
* @param baseTx Base transaction information
* @param srcSmgID ID of the source storeman group
*/
struct DebtTx {
BaseTx baseTx;
bytes32 srcSmgID;
}
/**
* @notice Main data structure for HTLC transactions
* @dev Contains mappings for all transaction types
* @param mapHashXUserTxs Mapping of transaction hashes to user transactions
* @param mapHashXSmgTxs Mapping of transaction hashes to storeman transactions
* @param mapHashXDebtTxs Mapping of transaction hashes to debt transactions
*/
struct Data {
mapping(bytes32 => UserTx) mapHashXUserTxs;
mapping(bytes32 => SmgTx) mapHashXSmgTxs;
mapping(bytes32 => DebtTx) mapHashXDebtTxs;
}
/**
* @notice Adds a new user transaction
* @dev Creates a new user transaction with the provided parameters
* @param self The storage data structure
* @param params Parameters for the new transaction
* Requirements:
* - Transaction must not already exist
*/
function addUserTx(Data storage self, HTLCUserParams memory params)
public
{
UserTx memory userTx = self.mapHashXUserTxs[params.xHash];
// UserTx storage userTx = self.mapHashXUserTxs[params.xHash];
// require(params.value != 0, "Value is invalid");
require(userTx.baseTx.status == TxStatus.None, "User tx exists");
userTx.baseTx.smgID = params.smgID;
userTx.baseTx.lockedTime = params.lockedTime;
userTx.baseTx.beginLockedTime = block.timestamp;
userTx.baseTx.status = TxStatus.Locked;
userTx.tokenPairID = params.tokenPairID;
userTx.value = params.value;
userTx.fee = params.lockFee;
userTx.userAccount = msg.sender;
self.mapHashXUserTxs[params.xHash] = userTx;
}
/**
* @notice Redeems a user transaction
* @dev Used for storeman redeem (outbound) operations
* @param self The storage data structure
* @param x The HTLC random number
* @return xHash The hash of the random number
* Requirements:
* - Transaction must be in Locked status
* - Transaction must not be expired
*/
function redeemUserTx(Data storage self, bytes32 x)
external
returns(bytes32 xHash)
{
xHash = sha256(abi.encodePacked(x));
UserTx storage userTx = self.mapHashXUserTxs[xHash];
require(userTx.baseTx.status == TxStatus.Locked, "Status is not locked");
require(block.timestamp < userTx.baseTx.beginLockedTime.add(userTx.baseTx.lockedTime), "Redeem timeout");
userTx.baseTx.status = TxStatus.Redeemed;
return xHash;
}
/**
* @notice Revokes a user transaction
* @dev Allows cancellation of expired transactions
* @param self The storage data structure
* @param xHash Hash of the HTLC random number
* Requirements:
* - Transaction must be in Locked status
* - Transaction must be expired
*/
function revokeUserTx(Data storage self, bytes32 xHash)
external
{
UserTx storage userTx = self.mapHashXUserTxs[xHash];
require(userTx.baseTx.status == TxStatus.Locked, "Status is not locked");
require(block.timestamp >= userTx.baseTx.beginLockedTime.add(userTx.baseTx.lockedTime), "Revoke is not permitted");
userTx.baseTx.status = TxStatus.Revoked;
}
/**
* @notice Retrieves user transaction information
* @dev Returns all relevant information about a user transaction
* @param self The storage data structure
* @param xHash Hash of the HTLC random number
* @return smgID ID of the storeman group
* @return tokenPairID ID of the token pair
* @return value Amount of tokens
* @return fee Transaction fee
* @return userAccount Address of the user
*/
function getUserTx(Data storage self, bytes32 xHash)
external
view
returns (bytes32, uint, uint, uint, address)
{
UserTx storage userTx = self.mapHashXUserTxs[xHash];
return (userTx.baseTx.smgID, userTx.tokenPairID, userTx.value, userTx.fee, userTx.userAccount);
}
/**
* @notice Adds a new storeman transaction
* @dev Creates a new storeman transaction with the provided parameters
* @param self The storage data structure
* @param xHash Hash of the HTLC random number
* @param smgID ID of the storeman group
* @param tokenPairID ID of the token pair
* @param value Amount of tokens
* @param userAccount Address of the user to receive tokens
* @param lockedTime Duration for which the transaction is locked
* Requirements:
* - Value must be non-zero
* - Transaction must not already exist
*/
function addSmgTx(Data storage self, bytes32 xHash, bytes32 smgID, uint tokenPairID, uint value, address userAccount, uint lockedTime)
external
{
SmgTx memory smgTx = self.mapHashXSmgTxs[xHash];
// SmgTx storage smgTx = self.mapHashXSmgTxs[xHash];
require(value != 0, "Value is invalid");
require(smgTx.baseTx.status == TxStatus.None, "Smg tx exists");
smgTx.baseTx.smgID = smgID;
smgTx.baseTx.status = TxStatus.Locked;
smgTx.baseTx.lockedTime = lockedTime;
smgTx.baseTx.beginLockedTime = block.timestamp;
smgTx.tokenPairID = tokenPairID;
smgTx.value = value;
smgTx.userAccount = userAccount;
self.mapHashXSmgTxs[xHash] = smgTx;
}
/**
* @notice Redeems a storeman transaction
* @dev Used for user redeem (inbound) operations
* @param self The storage data structure
* @param x The HTLC random number
* @return xHash The hash of the random number
* Requirements:
* - Transaction must be in Locked status
* - Transaction must not be expired
*/
function redeemSmgTx(Data storage self, bytes32 x)
external
returns(bytes32 xHash)
{
xHash = sha256(abi.encodePacked(x));
SmgTx storage smgTx = self.mapHashXSmgTxs[xHash];
require(smgTx.baseTx.status == TxStatus.Locked, "Status is not locked");
require(block.timestamp < smgTx.baseTx.beginLockedTime.add(smgTx.baseTx.lockedTime), "Redeem timeout");
smgTx.baseTx.status = TxStatus.Redeemed;
return xHash;
}
/**
* @notice Revokes a storeman transaction
* @dev Allows cancellation of expired transactions
* @param self The storage data structure
* @param xHash Hash of the HTLC random number
* Requirements:
* - Transaction must be in Locked status
* - Transaction must be expired
*/
function revokeSmgTx(Data storage self, bytes32 xHash)
external
{
SmgTx storage smgTx = self.mapHashXSmgTxs[xHash];
require(smgTx.baseTx.status == TxStatus.Locked, "Status is not locked");
require(block.timestamp >= smgTx.baseTx.beginLockedTime.add(smgTx.baseTx.lockedTime), "Revoke is not permitted");
smgTx.baseTx.status = TxStatus.Revoked;
}
/**
* @notice Retrieves storeman transaction information
* @dev Returns all relevant information about a storeman transaction
* @param self The storage data structure
* @param xHash Hash of the HTLC random number
* @return smgID ID of the storeman group
* @return tokenPairID ID of the token pair
* @return value Amount of tokens
* @return userAccount Address of the user to receive tokens
*/
function getSmgTx(Data storage self, bytes32 xHash)
external
view
returns (bytes32, uint, uint, address)
{
SmgTx storage smgTx = self.mapHashXSmgTxs[xHash];
return (smgTx.baseTx.smgID, smgTx.tokenPairID, smgTx.value, smgTx.userAccount);
}
/**
* @notice Adds a new debt transaction
* @dev Creates a new debt transaction between storeman groups
* @param self The storage data structure
* @param xHash Hash of the HTLC random number
* @param srcSmgID ID of the source storeman group
* @param destSmgID ID of the destination storeman group
* @param lockedTime Duration for which the transaction is locked
* @param status Initial status of the transaction
* Requirements:
* - Transaction must not already exist
* - Status must be either Locked or DebtLocked
*/
function addDebtTx(Data storage self, bytes32 xHash, bytes32 srcSmgID, bytes32 destSmgID, uint lockedTime, TxStatus status)
external
{
DebtTx memory debtTx = self.mapHashXDebtTxs[xHash];
// DebtTx storage debtTx = self.mapHashXDebtTxs[xHash];
require(debtTx.baseTx.status == TxStatus.None, "Debt tx exists");
debtTx.baseTx.smgID = destSmgID;
debtTx.baseTx.status = status;//TxStatus.Locked;
debtTx.baseTx.lockedTime = lockedTime;
debtTx.baseTx.beginLockedTime = block.timestamp;
debtTx.srcSmgID = srcSmgID;
self.mapHashXDebtTxs[xHash] = debtTx;
}
/**
* @notice Redeems a debt transaction
* @dev Used to complete debt transfer between storeman groups
* @param self The storage data structure
* @param x The HTLC random number
* @return xHash The hash of the random number
* Requirements:
* - Transaction must be in Locked or DebtLocked status
* - Transaction must not be expired
*/
function redeemDebtTx(Data storage self, bytes32 x, TxStatus status)
external
returns(bytes32 xHash)
{
xHash = sha256(abi.encodePacked(x));
DebtTx storage debtTx = self.mapHashXDebtTxs[xHash];
// require(debtTx.baseTx.status == TxStatus.Locked, "Status is not locked");
require(debtTx.baseTx.status == status, "Status is not locked");
require(block.timestamp < debtTx.baseTx.beginLockedTime.add(debtTx.baseTx.lockedTime), "Redeem timeout");
debtTx.baseTx.status = TxStatus.Redeemed;
return xHash;
}
/**
* @notice Revokes a debt transaction
* @dev Allows cancellation of expired debt transactions
* @param self The storage data structure
* @param xHash Hash of the HTLC random number
* Requirements:
* - Transaction must be in Locked or DebtLocked status
* - Transaction must be expired
*/
function revokeDebtTx(Data storage self, bytes32 xHash, TxStatus status)
external
{
DebtTx storage debtTx = self.mapHashXDebtTxs[xHash];
// require(debtTx.baseTx.status == TxStatus.Locked, "Status is not locked");
require(debtTx.baseTx.status == status, "Status is not locked");
require(block.timestamp >= debtTx.baseTx.beginLockedTime.add(debtTx.baseTx.lockedTime), "Revoke is not permitted");
debtTx.baseTx.status = TxStatus.Revoked;
}
/**
* @notice Retrieves debt transaction information
* @dev Returns all relevant information about a debt transaction
* @param self The storage data structure
* @param xHash Hash of the HTLC random number
* @return smgID ID of the storeman group
* @return srcSmgID ID of the source storeman group
*/
function getDebtTx(Data storage self, bytes32 xHash)
external
view
returns (bytes32, bytes32)
{
DebtTx storage debtTx = self.mapHashXDebtTxs[xHash];
return (debtTx.srcSmgID, debtTx.baseTx.smgID);
}
function getLeftTime(uint endTime) private view returns (uint) {
if (block.timestamp < endTime) {
return endTime.sub(block.timestamp);
}
return 0;
}
/// @notice function for get debt info
/// @param xHash hash of HTLC random number
/// @return leftTime the left lock time
function getLeftLockedTime(Data storage self, bytes32 xHash)
external
view
returns (uint leftTime)
{
UserTx storage userTx = self.mapHashXUserTxs[xHash];
if (userTx.baseTx.status != TxStatus.None) {
return getLeftTime(userTx.baseTx.beginLockedTime.add(userTx.baseTx.lockedTime));
}
SmgTx storage smgTx = self.mapHashXSmgTxs[xHash];
if (smgTx.baseTx.status != TxStatus.None) {
return getLeftTime(smgTx.baseTx.beginLockedTime.add(smgTx.baseTx.lockedTime));
}
DebtTx storage debtTx = self.mapHashXDebtTxs[xHash];
if (debtTx.baseTx.status != TxStatus.None) {
return getLeftTime(debtTx.baseTx.beginLockedTime.add(debtTx.baseTx.lockedTime));
}
require(false, 'invalid xHash');
}
}// SPDX-License-Identifier: MIT
/*
Copyright 2023 Wanchain Foundation.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// _ _ _
// __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __
// \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / /
// \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V /
// \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/
//
//
pragma solidity ^0.8.18;
/**
* @title RapidityTxLib
* @dev Library for managing rapid cross-chain transaction status
* This library provides functionality for:
* - Tracking transaction status
* - Managing rapid cross-chain transactions
*/
library RapidityTxLib {
/**
* @notice Enumeration of possible transaction statuses
* @dev Defines the states a rapidity transaction can be in
* - None: Initial state, transaction not yet processed
* - Redeemed: Transaction has been completed
*/
enum TxStatus {None, Redeemed}
/**
* @notice Main data structure for rapidity transactions
* @dev Contains mappings for tracking transaction statuses
* @param mapTxStatus Mapping of transaction unique IDs to their status
*/
struct Data {
mapping(bytes32 => TxStatus) mapTxStatus;
}
/**
* @notice Adds a new rapidity transaction
* @dev Marks a transaction as redeemed when it is added
* @param self The storage data structure
* @param uniqueID Unique identifier for the rapidity transaction
* Requirements:
* - Transaction must not already exist
*/
function addRapidityTx(Data storage self, bytes32 uniqueID)
internal
{
TxStatus status = self.mapTxStatus[uniqueID];
require(status == TxStatus.None, "Rapidity tx exists");
self.mapTxStatus[uniqueID] = TxStatus.Redeemed;
}
}// SPDX-License-Identifier: MIT
/*
Copyright 2023 Wanchain Foundation.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// _ _ _
// __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __
// \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / /
// \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V /
// \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/
//
//
pragma solidity ^0.8.18;
interface IQuota {
function userLock(uint tokenId, bytes32 storemanGroupId, uint value) external;
function userBurn(uint tokenId, bytes32 storemanGroupId, uint value) external;
function smgRelease(uint tokenId, bytes32 storemanGroupId, uint value) external;
function smgMint(uint tokenId, bytes32 storemanGroupId, uint value) external;
function upgrade(bytes32 storemanGroupId) external;
function transferAsset(bytes32 srcStoremanGroupId, bytes32 dstStoremanGroupId) external;
function receiveDebt(bytes32 srcStoremanGroupId, bytes32 dstStoremanGroupId) external;
function getUserMintQuota(uint tokenId, bytes32 storemanGroupId) external view returns (uint);
function getSmgMintQuota(uint tokenId, bytes32 storemanGroupId) external view returns (uint);
function getUserBurnQuota(uint tokenId, bytes32 storemanGroupId) external view returns (uint);
function getSmgBurnQuota(uint tokenId, bytes32 storemanGroupId) external view returns (uint);
function getAsset(uint tokenId, bytes32 storemanGroupId) external view returns (uint asset, uint asset_receivable, uint asset_payable);
function getDebt(uint tokenId, bytes32 storemanGroupId) external view returns (uint debt, uint debt_receivable, uint debt_payable);
function isDebtClean(bytes32 storemanGroupId) external view returns (bool);
}// SPDX-License-Identifier: MIT
/*
Copyright 2023 Wanchain Foundation.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// _ _ _
// __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __
// \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / /
// \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V /
// \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/
//
//
pragma solidity ^0.8.18;
interface IRC20Protocol {
function transfer(address, uint) external returns (bool);
function transferFrom(address, address, uint) external returns (bool);
function balanceOf(address _owner) external view returns (uint);
}// SPDX-License-Identifier: MIT
/*
Copyright 2023 Wanchain Foundation.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// _ _ _
// __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __
// \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / /
// \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V /
// \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/
//
//
pragma solidity ^0.8.18;
interface ISignatureVerifier {
function verify(
uint curveId,
bytes32 signature,
bytes32 groupKeyX,
bytes32 groupKeyY,
bytes32 randomPointX,
bytes32 randomPointY,
bytes32 message
) external returns (bool);
}// SPDX-License-Identifier: MIT
/*
Copyright 2023 Wanchain Foundation.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// _ _ _
// __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __
// \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / /
// \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V /
// \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/
//
//
pragma solidity ^0.8.18;
interface IStoremanGroup {
function getSelectedSmNumber(bytes32 groupId) external view returns(uint number);
function getStoremanGroupConfig(bytes32 id) external view returns(bytes32 groupId, uint8 status, uint deposit, uint chain1, uint chain2, uint curve1, uint curve2, bytes memory gpk1, bytes memory gpk2, uint startTime, uint endTime);
function getDeposit(bytes32 id) external view returns(uint);
function getStoremanGroupStatus(bytes32 id) external view returns(uint8 status, uint startTime, uint endTime);
function setGpk(bytes32 groupId, bytes memory gpk1, bytes memory gpk2) external;
function setInvalidSm(bytes32 groupId, uint[] memory indexs, uint8[] memory slashTypes) external returns(bool isContinue);
function getThresholdByGrpId(bytes32 groupId) external view returns (uint);
function getSelectedSmInfo(bytes32 groupId, uint index) external view returns(address wkAddr, bytes memory PK, bytes memory enodeId);
function recordSmSlash(address wk) external;
}// SPDX-License-Identifier: MIT
/*
Copyright 2023 Wanchain Foundation.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// _ _ _
// __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __
// \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / /
// \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V /
// \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/
//
//
pragma solidity ^0.8.18;
interface ITokenManager {
function getTokenPairInfo(uint id) external view
returns (uint origChainID, bytes memory tokenOrigAccount, uint shadowChainID, bytes memory tokenShadowAccount);
function getTokenPairInfoSlim(uint id) external view
returns (uint origChainID, bytes memory tokenOrigAccount, uint shadowChainID);
function getAncestorInfo(uint id) external view
returns (bytes memory account, string memory name, string memory symbol, uint8 decimals, uint chainId);
function mintToken(address tokenAddress, address to, uint value) external;
function burnToken(address tokenAddress, address from, uint value) external;
function mapTokenPairType(uint tokenPairID) external view
returns (uint8 tokenPairType);
// erc1155
function mintNFT(uint tokenCrossType, address tokenAddress, address to, uint[] calldata ids, uint[] calldata values, bytes calldata data) external;
function burnNFT(uint tokenCrossType, address tokenAddress, address from, uint[] calldata ids, uint[] calldata values) external;
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"uniqueID","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"smgID","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"tokenPairID","type":"uint256"},{"indexed":false,"internalType":"string[]","name":"keys","type":"string[]"},{"indexed":false,"internalType":"bytes[]","name":"values","type":"bytes[]"}],"name":"SmgMintNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"uniqueID","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"smgID","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"tokenPairID","type":"uint256"},{"indexed":false,"internalType":"string[]","name":"keys","type":"string[]"},{"indexed":false,"internalType":"bytes[]","name":"values","type":"bytes[]"}],"name":"SmgReleaseNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"smgID","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"tokenPairID","type":"uint256"},{"indexed":true,"internalType":"address","name":"tokenAccount","type":"address"},{"indexed":false,"internalType":"string[]","name":"keys","type":"string[]"},{"indexed":false,"internalType":"bytes[]","name":"values","type":"bytes[]"}],"name":"UserBurnNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"smgID","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"tokenPairID","type":"uint256"},{"indexed":true,"internalType":"address","name":"tokenAccount","type":"address"},{"indexed":false,"internalType":"string[]","name":"keys","type":"string[]"},{"indexed":false,"internalType":"bytes[]","name":"values","type":"bytes[]"}],"name":"UserLockNFT","type":"event"}]Contract Creation Code
61229061003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100615760003560e01c806306541aee146100665780632f1839fc14610088578063872cdb06146100a85780638a83a05c146100c8578063dfa67184146100e8575b600080fd5b81801561007257600080fd5b506100866100813660046119d9565b61011e565b005b81801561009457600080fd5b506100866100a3366004611af4565b610575565b8180156100b457600080fd5b506100866100c3366004611bd1565b610a5c565b8180156100d457600080fd5b506100866100e3366004611cd3565b610ef9565b6100fb6100f6366004611dca565b6113f2565b604080516001600160a01b03909316835260208301919091520160405180910390f35b60008061013f8484602001518560a0015186608001518760400151516113f2565b600586015460208601516040516375d2e27d60e01b81529395509193506001600160a01b03169160009183916375d2e27d916101819160040190815260200190565b602060405180830381865afa15801561019e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101c29190611e05565b905060ff8116600114806101d9575060ff81166002145b6101fe5760405162461bcd60e51b81526004016101f590611e45565b60405180910390fd5b816001600160a01b0316632859c5808260ff16863389604001518a606001516040518663ffffffff1660e01b815260040161023d959493929190611eaa565b600060405180830381600087803b15801561025757600080fd5b505af115801561026b573d6000803e3d6000fd5b50505050600083111561028c5761028c856101200151848760c00151611602565b60006102983485611732565b905080156102af576102af33828860c00151611602565b60408051600480825260a08201909252600091816020015b60608152602001906001900390816102c757505060408051600480825260a0820190925291925060009190602082015b60608152602001906001900390816102f757905050905060405180604001604052806012815260200171746f6b656e4944733a75696e743235365b5d60701b8152508260008151811061034c5761034c611efa565b6020026020010181905250876040015160405160200161036c9190611f10565b6040516020818303038152906040528160008151811061038e5761038e611efa565b602002602001018190525060405180604001604052806015815260200174746f6b656e56616c7565733a75696e743235365b5d60581b815250826001815181106103da576103da611efa565b602002602001018190525087606001516040516020016103fa9190611f10565b6040516020818303038152906040528160018151811061041c5761041c611efa565b602002602001018190525060405180604001604052806011815260200170757365724163636f756e743a627974657360781b8152508260028151811061046457610464611efa565b60200260200101819052508761010001518160028151811061048857610488611efa565b60200260200101819052506040518060400160405280601381526020017231b7b73a3930b1ba2332b29d3ab4b73a191a9b60691b815250826003815181106104d2576104d2611efa565b6020026020010181905250856040516020016104f091815260200190565b6040516020818303038152906040528160038151811061051257610512611efa565b6020026020010181905250866001600160a01b0316886020015189600001517f988781dff960cf5a144a15c9b0c4d1346196e415e64ea7ebd609c6ac0559bbbb8585604051610562929190611f73565b60405180910390a4505050505050505050565b8051610585906003840190611747565b600582015460408281015190516375d2e27d60e01b815260048101919091526000916001600160a01b0316906375d2e27d90602401602060405180830381865afa1580156105d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105fb9190611e05565b905060001960ff8216016106df5760005b8260600151518110156106d9578260a001516001600160a01b031663b88d4fde308560c001518660600151858151811061064857610648611efa565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152608060648201526000608482015260a401600060405180830381600087803b1580156106b057600080fd5b505af11580156106c4573d6000803e3d6000fd5b50505050806106d290612041565b905061060c565b5061077c565b60011960ff821601610764578160a001516001600160a01b0316632eb2c2d6308460c00151856060015186608001516040518563ffffffff1660e01b815260040161072d949392919061205a565b600060405180830381600087803b15801561074757600080fd5b505af115801561075b573d6000803e3d6000fd5b5050505061077c565b60405162461bcd60e51b81526004016101f590611e45565b60408051600480825260a08201909252600091816020015b606081526020019060019003908161079457505060408051600480825260a0820190925291925060009190602082015b60608152602001906001900390816107c457905050905060405180604001604052806012815260200171746f6b656e4944733a75696e743235365b5d60701b8152508260008151811061081957610819611efa565b602002602001018190525083606001516040516020016108399190611f10565b6040516020818303038152906040528160008151811061085b5761085b611efa565b602002602001018190525060405180604001604052806015815260200174746f6b656e56616c7565733a75696e743235365b5d60581b815250826001815181106108a7576108a7611efa565b602002602001018190525083608001516040516020016108c79190611f10565b604051602081830303815290604052816001815181106108e9576108e9611efa565b602002602001018190525060405180604001604052806014815260200173746f6b656e4163636f756e743a6164647265737360601b8152508260028151811061093457610934611efa565b60200260200101819052508360a0015160405160200161095491906120b5565b6040516020818303038152906040528160028151811061097657610976611efa565b602002602001018190525060405180604001604052806013815260200172757365724163636f756e743a6164647265737360681b815250826003815181106109c0576109c0611efa565b60200260200101819052508360c001516040516020016109e091906120b5565b60405160208183030381529060405281600381518110610a0257610a02611efa565b60200260200101819052508360400151846020015185600001517fba98d99dde5738beb90acb291bb9b140abeb4d2f93bd94d7dade6b9d9173bc738585604051610a4d929190611f73565b60405180910390a45050505050565b8051610a6c906003840190611747565b600582015460408083015190516375d2e27d60e01b81526001600160a01b039092169160009183916375d2e27d91610aaa9160040190815260200190565b602060405180830381865afa158015610ac7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aeb9190611e05565b905060ff811660011480610b02575060ff81166002145b610b1e5760405162461bcd60e51b81526004016101f590611e45565b816001600160a01b0316639947f9328260ff168560c001518660e00151876060015188608001518960a001516040518763ffffffff1660e01b8152600401610b6b969594939291906120d2565b600060405180830381600087803b158015610b8557600080fd5b505af1158015610b99573d6000803e3d6000fd5b506000925060059150610ba99050565b604051908082528060200260200182016040528015610bdc57816020015b6060815260200190600190039081610bc75790505b5060408051600580825260c0820190925291925060009190816020015b6060815260200190600190039081610bf957905050905060405180604001604052806012815260200171746f6b656e4944733a75696e743235365b5d60701b81525082600081518110610c4e57610c4e611efa565b60200260200101819052508460600151604051602001610c6e9190611f10565b60405160208183030381529060405281600081518110610c9057610c90611efa565b602002602001018190525060405180604001604052806015815260200174746f6b656e56616c7565733a75696e743235365b5d60581b81525082600181518110610cdc57610cdc611efa565b60200260200101819052508460800151604051602001610cfc9190611f10565b60405160208183030381529060405281600181518110610d1e57610d1e611efa565b602002602001018190525060405180604001604052806014815260200173746f6b656e4163636f756e743a6164647265737360601b81525082600281518110610d6957610d69611efa565b60200260200101819052508460c00151604051602001610d8991906120b5565b60405160208183030381529060405281600281518110610dab57610dab611efa565b602002602001018190525060405180604001604052806013815260200172757365724163636f756e743a6164647265737360681b81525082600381518110610df557610df5611efa565b60200260200101819052508460e00151604051602001610e1591906120b5565b60405160208183030381529060405281600381518110610e3757610e37611efa565b60200260200101819052506040518060400160405280600d81526020016c657874446174613a627974657360981b81525082600481518110610e7b57610e7b611efa565b60200260200101819052508460a0015181600481518110610e9e57610e9e611efa565b60200260200101819052508460400151856020015186600001517f4858e561d5a7ef18c29b934321d532519ca330e6141f44d4650c35d4481b43ed8585604051610ee9929190611f73565b60405180910390a4505050505050565b600080610f1a8484602001518560a0015186608001518760400151516113f2565b90925090508015610f3957610f39836101000151828560c00151611602565b6000610f453483611732565b600586015460208601516040516375d2e27d60e01b81529293506000926001600160a01b03909216916375d2e27d91610f849160040190815260200190565b602060405180830381865afa158015610fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc59190611e05565b905060001960ff8216016110a15760005b85604001515181101561109b57846001600160a01b031663b88d4fde33308960400151858151811061100a5761100a611efa565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152608060648201526000608482015260a401600060405180830381600087803b15801561107257600080fd5b505af1158015611086573d6000803e3d6000fd5b505050508061109490612041565b9050610fd6565b50611119565b60011960ff8216016107645760408086015160608701519151631759616b60e11b81526001600160a01b03871692632eb2c2d6926110e692339230929160040161205a565b600060405180830381600087803b15801561110057600080fd5b505af1158015611114573d6000803e3d6000fd5b505050505b811561112e5761112e33838760c00151611602565b60408051600480825260a08201909252600091816020015b606081526020019060019003908161114657505060408051600480825260a0820190925291925060009190602082015b606081526020019060019003908161117657905050905060405180604001604052806012815260200171746f6b656e4944733a75696e743235365b5d60701b815250826000815181106111cb576111cb611efa565b602002602001018190525086604001516040516020016111eb9190611f10565b6040516020818303038152906040528160008151811061120d5761120d611efa565b602002602001018190525060405180604001604052806015815260200174746f6b656e56616c7565733a75696e743235365b5d60581b8152508260018151811061125957611259611efa565b602002602001018190525086606001516040516020016112799190611f10565b6040516020818303038152906040528160018151811061129b5761129b611efa565b602002602001018190525060405180604001604052806011815260200170757365724163636f756e743a627974657360781b815250826002815181106112e3576112e3611efa565b60200260200101819052508660e001518160028151811061130657611306611efa565b60200260200101819052506040518060400160405280601381526020017231b7b73a3930b1ba2332b29d3ab4b73a191a9b60691b8152508260038151811061135057611350611efa565b60200260200101819052508460405160200161136e91815260200190565b6040516020818303038152906040528160038151811061139057611390611efa565b6020026020010181905250856001600160a01b0316876020015188600001517f62605e96f2f9cd2d124a846c58ea7d9982610ba45d052c99b14900c37a71868385856040516113e0929190611f73565b60405180910390a45050505050505050565b6005850154604051635c83993b60e11b81526004810186905260009182916001600160a01b0390911690829081906060908190859063b907327690602401600060405180830381865afa15801561144d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526114759190810190612184565b92965094509250905060008490036114c65760405162461bcd60e51b8152602060048201526014602482015273151bdad95b88191bd95cc81b9bdd08195e1a5cdd60621b60448201526064016101f5565b896000858b0361152b57816000036114f7576000868152600a8f016020908152604080832088845290915290205491505b8160000361151e576000868152600a8f016020908152604080832083805290915290205491505b60148401515b90506115c7565b848b0361158a5781600003611559576000858152600a8f016020908152604080832089845290915290205491505b81600003611580576000858152600a8f016020908152604080832083805290915290205491505b6014830151611524565b60405162461bcd60e51b815260206004820152601260248201527124b73b30b634b2103a37b5b2b7103830b4b960711b60448201526064016101f5565b81156115f0576115ed600a6115e76115e08d60096121fb565b85906117cb565b906117d7565b91505b9d909c509a5050505050505050505050565b8147101561165e5760405162461bcd60e51b815260206004820152602360248201527f45746865725472616e736665723a20696e73756666696369656e742062616c616044820152626e636560e81b60648201526084016101f5565b6000836001600160a01b0316838390604051600060405180830381858888f193505050503d80600081146116ae576040519150601f19603f3d011682016040523d82523d6000602084013e6116b3565b606091505b505090508061172c576040805162461bcd60e51b81526020600482015260248101919091527f45746865725472616e736665723a20756e61626c6520746f2073656e6420766160448201527f6c75652c20726563697069656e74206d6179206861766520726576657274656460648201526084016101f5565b50505050565b600061173e828461220e565b90505b92915050565b60008181526020839052604081205460ff169081600181111561176c5761176c611e2f565b146117ae5760405162461bcd60e51b815260206004820152601260248201527152617069646974792074782065786973747360701b60448201526064016101f5565b50600090815260209190915260409020805460ff19166001179055565b600061173e8284612221565b600061173e8284612238565b634e487b7160e01b600052604160045260246000fd5b604051610140810167ffffffffffffffff8111828210171561181d5761181d6117e3565b60405290565b60405160e0810167ffffffffffffffff8111828210171561181d5761181d6117e3565b604051610100810167ffffffffffffffff8111828210171561181d5761181d6117e3565b604051610120810167ffffffffffffffff8111828210171561181d5761181d6117e3565b604051601f8201601f1916810167ffffffffffffffff811182821017156118b7576118b76117e3565b604052919050565b600082601f8301126118d057600080fd5b8135602067ffffffffffffffff8211156118ec576118ec6117e3565b8160051b6118fb82820161188e565b928352848101820192828101908785111561191557600080fd5b83870192505b848310156119345782358252918301919083019061191b565b979650505050505050565b80356001600160a01b038116811461195657600080fd5b919050565b600067ffffffffffffffff821115611975576119756117e3565b50601f01601f191660200190565b600082601f83011261199457600080fd5b81356119a76119a28261195b565b61188e565b8181528460208386010111156119bc57600080fd5b816020850160208301376000918101602001919091529392505050565b600080604083850312156119ec57600080fd5b82359150602083013567ffffffffffffffff80821115611a0b57600080fd5b908401906101408287031215611a2057600080fd5b611a286117f9565b8235815260208301356020820152604083013582811115611a4857600080fd5b611a54888286016118bf565b604083015250606083013582811115611a6c57600080fd5b611a78888286016118bf565b6060830152506080830135608082015260a083013560a082015260c083013560c0820152611aa860e0840161193f565b60e08201526101008084013583811115611ac157600080fd5b611acd89828701611983565b8284015250506101209150611ae382840161193f565b828201528093505050509250929050565b60008060408385031215611b0757600080fd5b82359150602083013567ffffffffffffffff80821115611b2657600080fd5b9084019060e08287031215611b3a57600080fd5b611b42611823565b823581526020830135602082015260408301356040820152606083013582811115611b6c57600080fd5b611b78888286016118bf565b606083015250608083013582811115611b9057600080fd5b611b9c888286016118bf565b608083015250611bae60a0840161193f565b60a0820152611bbf60c0840161193f565b60c08201528093505050509250929050565b60008060408385031215611be457600080fd5b82359150602083013567ffffffffffffffff80821115611c0357600080fd5b908401906101008287031215611c1857600080fd5b611c20611846565b823581526020830135602082015260408301356040820152606083013582811115611c4a57600080fd5b611c56888286016118bf565b606083015250608083013582811115611c6e57600080fd5b611c7a888286016118bf565b60808301525060a083013582811115611c9257600080fd5b611c9e88828601611983565b60a083015250611cb060c0840161193f565b60c0820152611cc160e0840161193f565b60e08201528093505050509250929050565b60008060408385031215611ce657600080fd5b82359150602083013567ffffffffffffffff80821115611d0557600080fd5b908401906101208287031215611d1a57600080fd5b611d2261186a565b8235815260208301356020820152604083013582811115611d4257600080fd5b611d4e888286016118bf565b604083015250606083013582811115611d6657600080fd5b611d72888286016118bf565b6060830152506080830135608082015260a083013560a082015260c083013560c082015260e083013582811115611da857600080fd5b611db488828601611983565b60e0830152506101009150611ae382840161193f565b600080600080600060a08688031215611de257600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b600060208284031215611e1757600080fd5b815160ff81168114611e2857600080fd5b9392505050565b634e487b7160e01b600052602160045260246000fd5b60208082526010908201526f496e76616c6964204e4654207479706560801b604082015260600190565b600081518084526020808501945080840160005b83811015611e9f57815187529582019590820190600101611e83565b509495945050505050565b8581526001600160a01b0385811660208301528416604082015260a060608201819052600090611edc90830185611e6f565b8281036080840152611eee8185611e6f565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b60208152600061173e6020830184611e6f565b60005b83811015611f3e578181015183820152602001611f26565b50506000910152565b60008151808452611f5f816020860160208601611f23565b601f01601f19169290920160200192915050565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b83811015611fca57605f19888703018552611fb8868351611f47565b95509382019390820190600101611f9c565b505085840381870152865180855281850193509150600582901b8401810187820160005b8481101561201c57601f1987840301865261200a838351611f47565b95840195925090830190600101611fee565b50909998505050505050505050565b634e487b7160e01b600052601160045260246000fd5b6000600182016120535761205361202b565b5060010190565b6001600160a01b0385811682528416602082015260a06040820181905260009061208690830185611e6f565b82810360608401526120988185611e6f565b838103608090940193909352505060008152602001949350505050565b60609190911b6bffffffffffffffffffffffff1916815260140190565b8681526001600160a01b0386811660208301528516604082015260c06060820181905260009061210490830186611e6f565b82810360808401526121168186611e6f565b905082810360a084015261212a8185611f47565b9998505050505050505050565b600082601f83011261214857600080fd5b81516121566119a28261195b565b81815284602083860101111561216b57600080fd5b61217c826020830160208701611f23565b949350505050565b6000806000806080858703121561219a57600080fd5b84519350602085015167ffffffffffffffff808211156121b957600080fd5b6121c588838901612137565b94506040870151935060608701519150808211156121e257600080fd5b506121ef87828801612137565b91505092959194509250565b808201808211156117415761174161202b565b818103818111156117415761174161202b565b80820281158282048414176117415761174161202b565b60008261225557634e487b7160e01b600052601260045260246000fd5b50049056fea26469706673582212205d1b224e99fd19478280b8d103efe2b851f78a74ac298e017e721fc29fea84b964736f6c63430008120033
Deployed Bytecode
0x730f0bf93bf16fd28294c637d855fc73b917ef5fcc30146080604052600436106100615760003560e01c806306541aee146100665780632f1839fc14610088578063872cdb06146100a85780638a83a05c146100c8578063dfa67184146100e8575b600080fd5b81801561007257600080fd5b506100866100813660046119d9565b61011e565b005b81801561009457600080fd5b506100866100a3366004611af4565b610575565b8180156100b457600080fd5b506100866100c3366004611bd1565b610a5c565b8180156100d457600080fd5b506100866100e3366004611cd3565b610ef9565b6100fb6100f6366004611dca565b6113f2565b604080516001600160a01b03909316835260208301919091520160405180910390f35b60008061013f8484602001518560a0015186608001518760400151516113f2565b600586015460208601516040516375d2e27d60e01b81529395509193506001600160a01b03169160009183916375d2e27d916101819160040190815260200190565b602060405180830381865afa15801561019e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101c29190611e05565b905060ff8116600114806101d9575060ff81166002145b6101fe5760405162461bcd60e51b81526004016101f590611e45565b60405180910390fd5b816001600160a01b0316632859c5808260ff16863389604001518a606001516040518663ffffffff1660e01b815260040161023d959493929190611eaa565b600060405180830381600087803b15801561025757600080fd5b505af115801561026b573d6000803e3d6000fd5b50505050600083111561028c5761028c856101200151848760c00151611602565b60006102983485611732565b905080156102af576102af33828860c00151611602565b60408051600480825260a08201909252600091816020015b60608152602001906001900390816102c757505060408051600480825260a0820190925291925060009190602082015b60608152602001906001900390816102f757905050905060405180604001604052806012815260200171746f6b656e4944733a75696e743235365b5d60701b8152508260008151811061034c5761034c611efa565b6020026020010181905250876040015160405160200161036c9190611f10565b6040516020818303038152906040528160008151811061038e5761038e611efa565b602002602001018190525060405180604001604052806015815260200174746f6b656e56616c7565733a75696e743235365b5d60581b815250826001815181106103da576103da611efa565b602002602001018190525087606001516040516020016103fa9190611f10565b6040516020818303038152906040528160018151811061041c5761041c611efa565b602002602001018190525060405180604001604052806011815260200170757365724163636f756e743a627974657360781b8152508260028151811061046457610464611efa565b60200260200101819052508761010001518160028151811061048857610488611efa565b60200260200101819052506040518060400160405280601381526020017231b7b73a3930b1ba2332b29d3ab4b73a191a9b60691b815250826003815181106104d2576104d2611efa565b6020026020010181905250856040516020016104f091815260200190565b6040516020818303038152906040528160038151811061051257610512611efa565b6020026020010181905250866001600160a01b0316886020015189600001517f988781dff960cf5a144a15c9b0c4d1346196e415e64ea7ebd609c6ac0559bbbb8585604051610562929190611f73565b60405180910390a4505050505050505050565b8051610585906003840190611747565b600582015460408281015190516375d2e27d60e01b815260048101919091526000916001600160a01b0316906375d2e27d90602401602060405180830381865afa1580156105d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105fb9190611e05565b905060001960ff8216016106df5760005b8260600151518110156106d9578260a001516001600160a01b031663b88d4fde308560c001518660600151858151811061064857610648611efa565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152608060648201526000608482015260a401600060405180830381600087803b1580156106b057600080fd5b505af11580156106c4573d6000803e3d6000fd5b50505050806106d290612041565b905061060c565b5061077c565b60011960ff821601610764578160a001516001600160a01b0316632eb2c2d6308460c00151856060015186608001516040518563ffffffff1660e01b815260040161072d949392919061205a565b600060405180830381600087803b15801561074757600080fd5b505af115801561075b573d6000803e3d6000fd5b5050505061077c565b60405162461bcd60e51b81526004016101f590611e45565b60408051600480825260a08201909252600091816020015b606081526020019060019003908161079457505060408051600480825260a0820190925291925060009190602082015b60608152602001906001900390816107c457905050905060405180604001604052806012815260200171746f6b656e4944733a75696e743235365b5d60701b8152508260008151811061081957610819611efa565b602002602001018190525083606001516040516020016108399190611f10565b6040516020818303038152906040528160008151811061085b5761085b611efa565b602002602001018190525060405180604001604052806015815260200174746f6b656e56616c7565733a75696e743235365b5d60581b815250826001815181106108a7576108a7611efa565b602002602001018190525083608001516040516020016108c79190611f10565b604051602081830303815290604052816001815181106108e9576108e9611efa565b602002602001018190525060405180604001604052806014815260200173746f6b656e4163636f756e743a6164647265737360601b8152508260028151811061093457610934611efa565b60200260200101819052508360a0015160405160200161095491906120b5565b6040516020818303038152906040528160028151811061097657610976611efa565b602002602001018190525060405180604001604052806013815260200172757365724163636f756e743a6164647265737360681b815250826003815181106109c0576109c0611efa565b60200260200101819052508360c001516040516020016109e091906120b5565b60405160208183030381529060405281600381518110610a0257610a02611efa565b60200260200101819052508360400151846020015185600001517fba98d99dde5738beb90acb291bb9b140abeb4d2f93bd94d7dade6b9d9173bc738585604051610a4d929190611f73565b60405180910390a45050505050565b8051610a6c906003840190611747565b600582015460408083015190516375d2e27d60e01b81526001600160a01b039092169160009183916375d2e27d91610aaa9160040190815260200190565b602060405180830381865afa158015610ac7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aeb9190611e05565b905060ff811660011480610b02575060ff81166002145b610b1e5760405162461bcd60e51b81526004016101f590611e45565b816001600160a01b0316639947f9328260ff168560c001518660e00151876060015188608001518960a001516040518763ffffffff1660e01b8152600401610b6b969594939291906120d2565b600060405180830381600087803b158015610b8557600080fd5b505af1158015610b99573d6000803e3d6000fd5b506000925060059150610ba99050565b604051908082528060200260200182016040528015610bdc57816020015b6060815260200190600190039081610bc75790505b5060408051600580825260c0820190925291925060009190816020015b6060815260200190600190039081610bf957905050905060405180604001604052806012815260200171746f6b656e4944733a75696e743235365b5d60701b81525082600081518110610c4e57610c4e611efa565b60200260200101819052508460600151604051602001610c6e9190611f10565b60405160208183030381529060405281600081518110610c9057610c90611efa565b602002602001018190525060405180604001604052806015815260200174746f6b656e56616c7565733a75696e743235365b5d60581b81525082600181518110610cdc57610cdc611efa565b60200260200101819052508460800151604051602001610cfc9190611f10565b60405160208183030381529060405281600181518110610d1e57610d1e611efa565b602002602001018190525060405180604001604052806014815260200173746f6b656e4163636f756e743a6164647265737360601b81525082600281518110610d6957610d69611efa565b60200260200101819052508460c00151604051602001610d8991906120b5565b60405160208183030381529060405281600281518110610dab57610dab611efa565b602002602001018190525060405180604001604052806013815260200172757365724163636f756e743a6164647265737360681b81525082600381518110610df557610df5611efa565b60200260200101819052508460e00151604051602001610e1591906120b5565b60405160208183030381529060405281600381518110610e3757610e37611efa565b60200260200101819052506040518060400160405280600d81526020016c657874446174613a627974657360981b81525082600481518110610e7b57610e7b611efa565b60200260200101819052508460a0015181600481518110610e9e57610e9e611efa565b60200260200101819052508460400151856020015186600001517f4858e561d5a7ef18c29b934321d532519ca330e6141f44d4650c35d4481b43ed8585604051610ee9929190611f73565b60405180910390a4505050505050565b600080610f1a8484602001518560a0015186608001518760400151516113f2565b90925090508015610f3957610f39836101000151828560c00151611602565b6000610f453483611732565b600586015460208601516040516375d2e27d60e01b81529293506000926001600160a01b03909216916375d2e27d91610f849160040190815260200190565b602060405180830381865afa158015610fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc59190611e05565b905060001960ff8216016110a15760005b85604001515181101561109b57846001600160a01b031663b88d4fde33308960400151858151811061100a5761100a611efa565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152608060648201526000608482015260a401600060405180830381600087803b15801561107257600080fd5b505af1158015611086573d6000803e3d6000fd5b505050508061109490612041565b9050610fd6565b50611119565b60011960ff8216016107645760408086015160608701519151631759616b60e11b81526001600160a01b03871692632eb2c2d6926110e692339230929160040161205a565b600060405180830381600087803b15801561110057600080fd5b505af1158015611114573d6000803e3d6000fd5b505050505b811561112e5761112e33838760c00151611602565b60408051600480825260a08201909252600091816020015b606081526020019060019003908161114657505060408051600480825260a0820190925291925060009190602082015b606081526020019060019003908161117657905050905060405180604001604052806012815260200171746f6b656e4944733a75696e743235365b5d60701b815250826000815181106111cb576111cb611efa565b602002602001018190525086604001516040516020016111eb9190611f10565b6040516020818303038152906040528160008151811061120d5761120d611efa565b602002602001018190525060405180604001604052806015815260200174746f6b656e56616c7565733a75696e743235365b5d60581b8152508260018151811061125957611259611efa565b602002602001018190525086606001516040516020016112799190611f10565b6040516020818303038152906040528160018151811061129b5761129b611efa565b602002602001018190525060405180604001604052806011815260200170757365724163636f756e743a627974657360781b815250826002815181106112e3576112e3611efa565b60200260200101819052508660e001518160028151811061130657611306611efa565b60200260200101819052506040518060400160405280601381526020017231b7b73a3930b1ba2332b29d3ab4b73a191a9b60691b8152508260038151811061135057611350611efa565b60200260200101819052508460405160200161136e91815260200190565b6040516020818303038152906040528160038151811061139057611390611efa565b6020026020010181905250856001600160a01b0316876020015188600001517f62605e96f2f9cd2d124a846c58ea7d9982610ba45d052c99b14900c37a71868385856040516113e0929190611f73565b60405180910390a45050505050505050565b6005850154604051635c83993b60e11b81526004810186905260009182916001600160a01b0390911690829081906060908190859063b907327690602401600060405180830381865afa15801561144d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526114759190810190612184565b92965094509250905060008490036114c65760405162461bcd60e51b8152602060048201526014602482015273151bdad95b88191bd95cc81b9bdd08195e1a5cdd60621b60448201526064016101f5565b896000858b0361152b57816000036114f7576000868152600a8f016020908152604080832088845290915290205491505b8160000361151e576000868152600a8f016020908152604080832083805290915290205491505b60148401515b90506115c7565b848b0361158a5781600003611559576000858152600a8f016020908152604080832089845290915290205491505b81600003611580576000858152600a8f016020908152604080832083805290915290205491505b6014830151611524565b60405162461bcd60e51b815260206004820152601260248201527124b73b30b634b2103a37b5b2b7103830b4b960711b60448201526064016101f5565b81156115f0576115ed600a6115e76115e08d60096121fb565b85906117cb565b906117d7565b91505b9d909c509a5050505050505050505050565b8147101561165e5760405162461bcd60e51b815260206004820152602360248201527f45746865725472616e736665723a20696e73756666696369656e742062616c616044820152626e636560e81b60648201526084016101f5565b6000836001600160a01b0316838390604051600060405180830381858888f193505050503d80600081146116ae576040519150601f19603f3d011682016040523d82523d6000602084013e6116b3565b606091505b505090508061172c576040805162461bcd60e51b81526020600482015260248101919091527f45746865725472616e736665723a20756e61626c6520746f2073656e6420766160448201527f6c75652c20726563697069656e74206d6179206861766520726576657274656460648201526084016101f5565b50505050565b600061173e828461220e565b90505b92915050565b60008181526020839052604081205460ff169081600181111561176c5761176c611e2f565b146117ae5760405162461bcd60e51b815260206004820152601260248201527152617069646974792074782065786973747360701b60448201526064016101f5565b50600090815260209190915260409020805460ff19166001179055565b600061173e8284612221565b600061173e8284612238565b634e487b7160e01b600052604160045260246000fd5b604051610140810167ffffffffffffffff8111828210171561181d5761181d6117e3565b60405290565b60405160e0810167ffffffffffffffff8111828210171561181d5761181d6117e3565b604051610100810167ffffffffffffffff8111828210171561181d5761181d6117e3565b604051610120810167ffffffffffffffff8111828210171561181d5761181d6117e3565b604051601f8201601f1916810167ffffffffffffffff811182821017156118b7576118b76117e3565b604052919050565b600082601f8301126118d057600080fd5b8135602067ffffffffffffffff8211156118ec576118ec6117e3565b8160051b6118fb82820161188e565b928352848101820192828101908785111561191557600080fd5b83870192505b848310156119345782358252918301919083019061191b565b979650505050505050565b80356001600160a01b038116811461195657600080fd5b919050565b600067ffffffffffffffff821115611975576119756117e3565b50601f01601f191660200190565b600082601f83011261199457600080fd5b81356119a76119a28261195b565b61188e565b8181528460208386010111156119bc57600080fd5b816020850160208301376000918101602001919091529392505050565b600080604083850312156119ec57600080fd5b82359150602083013567ffffffffffffffff80821115611a0b57600080fd5b908401906101408287031215611a2057600080fd5b611a286117f9565b8235815260208301356020820152604083013582811115611a4857600080fd5b611a54888286016118bf565b604083015250606083013582811115611a6c57600080fd5b611a78888286016118bf565b6060830152506080830135608082015260a083013560a082015260c083013560c0820152611aa860e0840161193f565b60e08201526101008084013583811115611ac157600080fd5b611acd89828701611983565b8284015250506101209150611ae382840161193f565b828201528093505050509250929050565b60008060408385031215611b0757600080fd5b82359150602083013567ffffffffffffffff80821115611b2657600080fd5b9084019060e08287031215611b3a57600080fd5b611b42611823565b823581526020830135602082015260408301356040820152606083013582811115611b6c57600080fd5b611b78888286016118bf565b606083015250608083013582811115611b9057600080fd5b611b9c888286016118bf565b608083015250611bae60a0840161193f565b60a0820152611bbf60c0840161193f565b60c08201528093505050509250929050565b60008060408385031215611be457600080fd5b82359150602083013567ffffffffffffffff80821115611c0357600080fd5b908401906101008287031215611c1857600080fd5b611c20611846565b823581526020830135602082015260408301356040820152606083013582811115611c4a57600080fd5b611c56888286016118bf565b606083015250608083013582811115611c6e57600080fd5b611c7a888286016118bf565b60808301525060a083013582811115611c9257600080fd5b611c9e88828601611983565b60a083015250611cb060c0840161193f565b60c0820152611cc160e0840161193f565b60e08201528093505050509250929050565b60008060408385031215611ce657600080fd5b82359150602083013567ffffffffffffffff80821115611d0557600080fd5b908401906101208287031215611d1a57600080fd5b611d2261186a565b8235815260208301356020820152604083013582811115611d4257600080fd5b611d4e888286016118bf565b604083015250606083013582811115611d6657600080fd5b611d72888286016118bf565b6060830152506080830135608082015260a083013560a082015260c083013560c082015260e083013582811115611da857600080fd5b611db488828601611983565b60e0830152506101009150611ae382840161193f565b600080600080600060a08688031215611de257600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b600060208284031215611e1757600080fd5b815160ff81168114611e2857600080fd5b9392505050565b634e487b7160e01b600052602160045260246000fd5b60208082526010908201526f496e76616c6964204e4654207479706560801b604082015260600190565b600081518084526020808501945080840160005b83811015611e9f57815187529582019590820190600101611e83565b509495945050505050565b8581526001600160a01b0385811660208301528416604082015260a060608201819052600090611edc90830185611e6f565b8281036080840152611eee8185611e6f565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b60208152600061173e6020830184611e6f565b60005b83811015611f3e578181015183820152602001611f26565b50506000910152565b60008151808452611f5f816020860160208601611f23565b601f01601f19169290920160200192915050565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b83811015611fca57605f19888703018552611fb8868351611f47565b95509382019390820190600101611f9c565b505085840381870152865180855281850193509150600582901b8401810187820160005b8481101561201c57601f1987840301865261200a838351611f47565b95840195925090830190600101611fee565b50909998505050505050505050565b634e487b7160e01b600052601160045260246000fd5b6000600182016120535761205361202b565b5060010190565b6001600160a01b0385811682528416602082015260a06040820181905260009061208690830185611e6f565b82810360608401526120988185611e6f565b838103608090940193909352505060008152602001949350505050565b60609190911b6bffffffffffffffffffffffff1916815260140190565b8681526001600160a01b0386811660208301528516604082015260c06060820181905260009061210490830186611e6f565b82810360808401526121168186611e6f565b905082810360a084015261212a8185611f47565b9998505050505050505050565b600082601f83011261214857600080fd5b81516121566119a28261195b565b81815284602083860101111561216b57600080fd5b61217c826020830160208701611f23565b949350505050565b6000806000806080858703121561219a57600080fd5b84519350602085015167ffffffffffffffff808211156121b957600080fd5b6121c588838901612137565b94506040870151935060608701519150808211156121e257600080fd5b506121ef87828801612137565b91505092959194509250565b808201808211156117415761174161202b565b818103818111156117415761174161202b565b80820281158282048414176117415761174161202b565b60008261225557634e487b7160e01b600052601260045260246000fd5b50049056fea26469706673582212205d1b224e99fd19478280b8d103efe2b851f78a74ac298e017e721fc29fea84b964736f6c63430008120033
Loading...
Loading
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.