More Info
Private Name Tags
ContractCreator:
Sponsored
Latest 25 from a total of 446,487 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Destroy Sale Fro... | 38750413 | 421 days ago | IN | 0 MATIC | 0.01199612 | ||||
Destroy Sale Fro... | 38750413 | 421 days ago | IN | 0 MATIC | 0.01199612 | ||||
Destroy Sale Fro... | 38750413 | 421 days ago | IN | 0 MATIC | 0.01199612 | ||||
Destroy Sale Fro... | 38750413 | 421 days ago | IN | 0 MATIC | 0.01199612 | ||||
Destroy Sale Fro... | 38750413 | 421 days ago | IN | 0 MATIC | 0.01199612 | ||||
Destroy Sale Fro... | 38750413 | 421 days ago | IN | 0 MATIC | 0.01199612 | ||||
Destroy Sale Fro... | 38750413 | 421 days ago | IN | 0 MATIC | 0.01199612 | ||||
Destroy Sale Fro... | 38750413 | 421 days ago | IN | 0 MATIC | 0.01199612 | ||||
Destroy Sale Fro... | 38750413 | 421 days ago | IN | 0 MATIC | 0.01199612 | ||||
Destroy Sale Fro... | 38750413 | 421 days ago | IN | 0 MATIC | 0.01199612 | ||||
Destroy Sale Fro... | 38750413 | 421 days ago | IN | 0 MATIC | 0.01199612 | ||||
Destroy Sale Fro... | 38750413 | 421 days ago | IN | 0 MATIC | 0.01199612 | ||||
Destroy Sale Fro... | 38750413 | 421 days ago | IN | 0 MATIC | 0.01199612 | ||||
Destroy Sale Fro... | 38750352 | 421 days ago | IN | 0 MATIC | 0.00614189 | ||||
Destroy Sale Fro... | 38750352 | 421 days ago | IN | 0 MATIC | 0.00614189 | ||||
Destroy Sale Fro... | 38750352 | 421 days ago | IN | 0 MATIC | 0.00614189 | ||||
Destroy Sale Fro... | 38750305 | 421 days ago | IN | 0 MATIC | 0.00665649 | ||||
Destroy Sale Fro... | 38750305 | 421 days ago | IN | 0 MATIC | 0.00665649 | ||||
Destroy Sale Fro... | 38750305 | 421 days ago | IN | 0 MATIC | 0.00665878 | ||||
Destroy Sale Fro... | 38750305 | 421 days ago | IN | 0 MATIC | 0.00665649 | ||||
Destroy Sale Fro... | 38750305 | 421 days ago | IN | 0 MATIC | 0.00665649 | ||||
Destroy Sale Fro... | 38750305 | 421 days ago | IN | 0 MATIC | 0.00665649 | ||||
Destroy Sale Fro... | 38750304 | 421 days ago | IN | 0 MATIC | 0.00639331 | ||||
Destroy Sale Fro... | 38750304 | 421 days ago | IN | 0 MATIC | 0.00639111 | ||||
Destroy Sale Fro... | 38750304 | 421 days ago | IN | 0 MATIC | 0.00639111 |
Loading...
Loading
Contract Name:
ChampMarketplace
Compiler Version
v0.8.12+commit.f00d7308
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // Unagi Contracts v1.0.0 (ChampMarketplace.sol) pragma solidity 0.8.12; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC777/IERC777.sol"; import "@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol"; import "@openzeppelin/contracts/utils/introspection/IERC1820Registry.sol"; import "solidity-bytes-utils/contracts/BytesLib.sol"; import "@openzeppelin/contracts/utils/Multicall.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; /** * @title ChampMarketplace * @dev This contract allows CHAMP (Ultimate Champions Token) and NFCHAMP * (Non Fungible Ultimate Champions) holders to exchange theirs assets. * * A NFT holder can create, edit or delete a sale for one of his NFTs. * To create a sale, the NFT holder must give his approval for the ChampMarketplace * on the NFT he wants to sell. Then, the NFT holder must call the function * `createSaleFrom`. To remove the sale, the NFT holder must call the function * `destroySaleFrom`. * * A CHAMP holder can accept a sale. To accept a sale, the CHAMP holder must * send CHAMP tokens to the ChampMarketplace address with the `ERC77.send` * function from the ChampToken smartcontract. The NFT ID must be provided * as `data` parameter (See `ChampMarketplace.tokensReceived` for more details). * * Once a NFT is sold, a fee (readable through `marketplacePercentFees()`) * will be applied on the CHAMP payment and forwarded to the marketplace * fees receiver (readable through `marketplaceFeesReceiver()`). * The rest is sent to the seller. * * The fees is editable by FEE_MANAGER_ROLE. * The fee receiver is editable by FEE_MANAGER_ROLE. * * @custom:security-contact [email protected] */ contract ChampMarketplace is AccessControlEnumerable, IERC777Recipient, Multicall { using SafeMath for uint256; bytes32 public constant FEE_MANAGER_ROLE = keccak256("FEE_MANAGER_ROLE"); IERC777 public immutable _CHAMP_TOKEN_CONTRACT; IERC721 public immutable _NFCHAMP_CONTRACT; IERC1820Registry internal constant _ERC1820_REGISTRY = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24); bytes32 private constant _TOKENS_RECIPIENT_INTERFACE_HASH = keccak256("ERC777TokensRecipient"); // (nft ID => prices as CHAMP wei) mapping of sales mapping(uint256 => uint256) private _sales; // Percent fees applied on each sale. uint256 private _marketplacePercentFees; // Fees receiver address address private _marketplaceFeesReceiver; constructor(address champTokenAddress, address nfChampAddress) { _CHAMP_TOKEN_CONTRACT = IERC777(champTokenAddress); _NFCHAMP_CONTRACT = IERC721(nfChampAddress); _ERC1820_REGISTRY.setInterfaceImplementer( address(this), _TOKENS_RECIPIENT_INTERFACE_HASH, address(this) ); _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); _setupRole(FEE_MANAGER_ROLE, _msgSender()); } /** * @dev Returns true if a tokenID is on sale. */ function hasSale(uint64 tokenId) public view returns (bool) { return getSale(tokenId) > 0; } /** * @dev Returns the CHAMP wei price to buy a given NFCHAMP ID. * If the sale does not exists, the function returns 0. */ function getSale(uint64 tokenId) public view returns (uint256) { uint256 salePrice = _sales[tokenId]; if (_NFCHAMP_CONTRACT.getApproved(tokenId) != address(this)) { return 0; } return salePrice; } /** * @dev Setter for the marketplace fees. * * Emits a {MarketplaceFeesUpdated} event. * * Requirements: * * - nMarketplacePercentFees must be a percentage (Between 0 and 100 included). * - Caller must have role FEE_MANAGER_ROLE. */ function setMarketplacePercentFees(uint256 nMarketplacePercentFees) external onlyRole(FEE_MANAGER_ROLE) { require( nMarketplacePercentFees >= 0, "ChampMarketplace: nMarketplacePercentFees should be positive" ); require( nMarketplacePercentFees <= 100, "ChampMarketplace: nMarketplacePercentFees should be below 100" ); _marketplacePercentFees = nMarketplacePercentFees; emit MarketplaceFeesUpdated(_marketplacePercentFees); } /** * @dev Getter for the marketplace fees. */ function marketplacePercentFees() public view returns (uint256) { return _marketplacePercentFees; } /** * @dev Compute the current share for a given price. * Remainder is given to the seller. * Return a tuple of wei: * - First element is CHAMP wei for the seller. * - Second element is CHAMP wei fee. */ function computeSaleShares(uint256 weiPrice) public view returns (uint256, uint256) { uint256 saleFees = weiPrice.mul(marketplacePercentFees()).div(100); return (weiPrice.sub(saleFees), saleFees); } /** * @dev Setter for the marketplace fees receiver address. * * Emits a {MarketplaceFeesReceiverUpdated} event. * * Requirements: * * - Caller must have role FEE_MANAGER_ROLE. */ function setMarketplaceFeesReceiver(address nMarketplaceFeesReceiver) external onlyRole(FEE_MANAGER_ROLE) { _marketplaceFeesReceiver = nMarketplaceFeesReceiver; emit MarketplaceFeesReceiverUpdated(_marketplaceFeesReceiver); } /** * @dev Getter for the marketplace fees receiver address. */ function marketplaceFeesReceiver() public view returns (address) { return _marketplaceFeesReceiver; } /** * @dev Allow to create a sale for a given NFCHAMP ID at a given CHAMP wei price. * * Emits a {SaleCreated} event. * * Requirements: * * - tokenWeiPrice should be strictly positive. * - from must be the NFCHAMP owner. * - msg.sender should be either the NFCHAMP owner or approved by the NFCHAMP owner. * - ChampMarketplace contract should be approved for the given NFCHAMP ID. * - NFCHAMP ID should not be on sale. */ function createSaleFrom( address from, uint64 tokenId, uint256 tokenWeiPrice ) external { require( tokenWeiPrice > 0, "ChampMarketplace: Price should be strictly positive" ); address nftOwner = _NFCHAMP_CONTRACT.ownerOf(tokenId); require( nftOwner == from, "ChampMarketplace: Create sale of token that is not own" ); require( nftOwner == msg.sender || _NFCHAMP_CONTRACT.isApprovedForAll(nftOwner, msg.sender), "ChampMarketplace: Only the token owner or its operator are allowed to create a sale." ); require( _NFCHAMP_CONTRACT.getApproved(tokenId) == address(this), "ChampMarketplace: Contract should be approved by the token owner." ); require( !hasSale(tokenId), "ChampMarketplace: Sale already exists. Destroy the previous sale first." ); _sales[tokenId] = tokenWeiPrice; emit SaleCreated(tokenId, tokenWeiPrice, nftOwner); } /** * @dev Allow to edit a sale for a given NFCHAMP ID at a given CHAMP wei price. * * Emits a {SaleEdited} event. * * Requirements: * * - NFCHAMP ID should be on sale. * - tokenWeiPrice should be strictly positive. * - from must be the NFCHAMP owner. * - msg.sender should be either the NFCHAMP owner or approved by the NFCHAMP owner. * - ChampMarketplace contract should be approved for the given NFCHAMP ID. */ function editSaleFrom( address from, uint64 tokenId, uint256 tokenWeiPrice ) external { require(hasSale(tokenId), "ChampMarketplace: Sale does not exists"); address nftOwner = _NFCHAMP_CONTRACT.ownerOf(tokenId); require( nftOwner == from, "ChampMarketplace: Edit sale of token that is not own" ); require( nftOwner == msg.sender || _NFCHAMP_CONTRACT.isApprovedForAll(nftOwner, msg.sender), "ChampMarketplace: Only the token owner or its operator are allowed to edit a sale." ); require( tokenWeiPrice > 0, "ChampMarketplace: Price should be strictly positive" ); _sales[tokenId] = tokenWeiPrice; emit SaleEdited(tokenId, tokenWeiPrice, nftOwner); } /** * @dev Allow to destroy a sale for a given NFCHAMP ID. * * Emits a {SaleDestroyed} event. * * Requirements: * * - NFCHAMP ID should be on sale. * - from must be the NFCHAMP owner. * - msg.sender should be either the NFCHAMP owner or approved by the NFCHAMP owner. * - ChampMarketplace contract should be approved for the given NFCHAMP ID. */ function destroySaleFrom(address from, uint64 tokenId) external { require(hasSale(tokenId), "ChampMarketplace: Sale does not exists"); address nftOwner = _NFCHAMP_CONTRACT.ownerOf(tokenId); require( nftOwner == from, "ChampMarketplace: Destroy sale of token that is not own" ); require( nftOwner == msg.sender || _NFCHAMP_CONTRACT.isApprovedForAll(nftOwner, msg.sender), "ChampMarketplace: Only the token owner or its operator are allowed to destroy a sale." ); delete _sales[tokenId]; emit SaleDestroyed(tokenId, nftOwner); } /** * @dev Called by an {IERC777} CHAMP token contract whenever tokens are being * sent to the ChampMarketplace contract. * * This function is used to buy a NFCHAMP listed on the ChampMarketplace contract. * To buy a NFCHAMP, a CHAMP holder must send CHAMP wei price (or above) to the * ChampMarketplace contract with some extra data: * - MANDATORY: Bytes 0 to 7 (8 bytes, uint64) corresponds to the NFCHAMP ID to buy * - OPTIONAL: Bytes 8 to 27 (20 bytes, address) can be provided to customize * the wallet that will receive the NFCHAMP if the sale is executed. * * Once a NFT is sold, a fee will be applied on the CHAMP payment and forwarded * to the marketplace fees receiver. * * Emits a {SaleAccepted} event. * * Requirements: * * - Received tokens must be CHAMP. * - NFCHAMP ID must be on sale. * - Received tokens amount must be greater than sale price. */ function tokensReceived( address, address from, address to, uint256 amount, bytes calldata userData, bytes calldata ) external override { // // 1. // Requirements // require(to == address(this), "ChampMarketplace: Invalid recipient"); require( msg.sender == address(_CHAMP_TOKEN_CONTRACT), "ChampMarketplace: Invalid ERC777 token" ); // Read NFCHAMP ID uint64 tokenId = BytesLib.toUint64(userData, 0); // Read optional address that will receive NFCHAMP // By default, `from` will receive the NFCHAMP address nftReceiver = userData.length > 8 ? BytesLib.toAddress(userData, 8) : from; require(hasSale(tokenId), "ChampMarketplace: Sale does not exists"); require( amount >= _sales[tokenId], "ChampMarketplace: You must match the sale price to accept the sale." ); // // 2. // Process sale // address seller = _NFCHAMP_CONTRACT.ownerOf(tokenId); uint256 sellerTokenWeiShare; uint256 marketplaceFeesTokenWeiShare; (sellerTokenWeiShare, marketplaceFeesTokenWeiShare) = computeSaleShares( amount ); // // 3. // Execute sale // delete _sales[tokenId]; _NFCHAMP_CONTRACT.safeTransferFrom(seller, nftReceiver, tokenId); _CHAMP_TOKEN_CONTRACT.send(seller, sellerTokenWeiShare, ""); if (marketplaceFeesTokenWeiShare > 0) { _CHAMP_TOKEN_CONTRACT.send( marketplaceFeesReceiver(), marketplaceFeesTokenWeiShare, "" ); } emit SaleAccepted(tokenId, amount, seller, nftReceiver); } event MarketplaceFeesUpdated(uint256 percentFees); event MarketplaceFeesReceiverUpdated(address feesReceiver); event SaleCreated(uint64 tokenId, uint256 tokenWeiPrice, address seller); event SaleEdited(uint64 tokenId, uint256 tokenWeiPrice, address seller); event SaleAccepted( uint64 tokenId, uint256 tokenWeiPrice, address seller, address buyer ); event SaleDestroyed(uint64 tokenId, address seller); }
// SPDX-License-Identifier: Unlicense /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.8.0 <0.9.0; library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore(0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. )) } return tempBytes; } function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes.slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { require(_bytes.length >= _start + 1 , "toUint8_outOfBounds"); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (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 substraction 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 // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC1820Registry.sol) pragma solidity ^0.8.0; /** * @dev Interface of the global ERC1820 Registry, as defined in the * https://eips.ethereum.org/EIPS/eip-1820[EIP]. Accounts may register * implementers for interfaces in this registry, as well as query support. * * Implementers may be shared by multiple accounts, and can also implement more * than a single interface for each account. Contracts can implement interfaces * for themselves, but externally-owned accounts (EOA) must delegate this to a * contract. * * {IERC165} interfaces can also be queried via the registry. * * For an in-depth explanation and source code analysis, see the EIP text. */ interface IERC1820Registry { /** * @dev Sets `newManager` as the manager for `account`. A manager of an * account is able to set interface implementers for it. * * By default, each account is its own manager. Passing a value of `0x0` in * `newManager` will reset the manager to this initial state. * * Emits a {ManagerChanged} event. * * Requirements: * * - the caller must be the current manager for `account`. */ function setManager(address account, address newManager) external; /** * @dev Returns the manager for `account`. * * See {setManager}. */ function getManager(address account) external view returns (address); /** * @dev Sets the `implementer` contract as ``account``'s implementer for * `interfaceHash`. * * `account` being the zero address is an alias for the caller's address. * The zero address can also be used in `implementer` to remove an old one. * * See {interfaceHash} to learn how these are created. * * Emits an {InterfaceImplementerSet} event. * * Requirements: * * - the caller must be the current manager for `account`. * - `interfaceHash` must not be an {IERC165} interface id (i.e. it must not * end in 28 zeroes). * - `implementer` must implement {IERC1820Implementer} and return true when * queried for support, unless `implementer` is the caller. See * {IERC1820Implementer-canImplementInterfaceForAddress}. */ function setInterfaceImplementer( address account, bytes32 _interfaceHash, address implementer ) external; /** * @dev Returns the implementer of `interfaceHash` for `account`. If no such * implementer is registered, returns the zero address. * * If `interfaceHash` is an {IERC165} interface id (i.e. it ends with 28 * zeroes), `account` will be queried for support of it. * * `account` being the zero address is an alias for the caller's address. */ function getInterfaceImplementer(address account, bytes32 _interfaceHash) external view returns (address); /** * @dev Returns the interface hash for an `interfaceName`, as defined in the * corresponding * https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the EIP]. */ function interfaceHash(string calldata interfaceName) external pure returns (bytes32); /** * @notice Updates the cache with whether the contract implements an ERC165 interface or not. * @param account Address of the contract for which to update the cache. * @param interfaceId ERC165 interface for which to update the cache. */ function updateERC165Cache(address account, bytes4 interfaceId) external; /** * @notice Checks whether a contract implements an ERC165 interface or not. * If the result is not cached a direct lookup on the contract address is performed. * If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling * {updateERC165Cache} with the contract address. * @param account Address of the contract to check. * @param interfaceId ERC165 interface to check. * @return True if `account` implements `interfaceId`, false otherwise. */ function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool); /** * @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache. * @param account Address of the contract to check. * @param interfaceId ERC165 interface to check. * @return True if `account` implements `interfaceId`, false otherwise. */ function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool); event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer); event ManagerChanged(address indexed account, address indexed newManager); }
// 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 v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Multicall.sol) pragma solidity ^0.8.0; import "./Address.sol"; /** * @dev Provides a function to batch together multiple calls in a single external call. * * _Available since v4.1._ */ abstract contract Multicall { /** * @dev Receives and executes a batch of function calls on this contract. */ function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) { results = new bytes[](data.length); for (uint256 i = 0; i < data.length; i++) { results[i] = Address.functionDelegateCall(address(this), data[i]); } return results; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC777/IERC777Recipient.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC777TokensRecipient standard as defined in the EIP. * * Accounts can be notified of {IERC777} tokens being sent to them by having a * contract implement this interface (contract holders can be their own * implementer) and registering it on the * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry]. * * See {IERC1820Registry} and {ERC1820Implementer}. */ interface IERC777Recipient { /** * @dev Called by an {IERC777} token contract whenever tokens are being * moved or created into a registered account (`to`). The type of operation * is conveyed by `from` being the zero address or not. * * This call occurs _after_ the token contract's state is updated, so * {IERC777-balanceOf}, etc., can be used to query the post-operation state. * * This function may revert to prevent the operation from being executed. */ function tokensReceived( address operator, address from, address to, uint256 amount, bytes calldata userData, bytes calldata operatorData ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC777/IERC777.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC777Token standard as defined in the EIP. * * This contract uses the * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 registry standard] to let * token holders and recipients react to token movements by using setting implementers * for the associated interfaces in said registry. See {IERC1820Registry} and * {ERC1820Implementer}. */ interface IERC777 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() external view returns (string memory); /** * @dev Returns the smallest part of the token that is not divisible. This * means all token operations (creation, movement and destruction) must have * amounts that are a multiple of this number. * * For most token contracts, this value will equal 1. */ function granularity() external view returns (uint256); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by an account (`owner`). */ function balanceOf(address owner) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * If send or receive hooks are registered for the caller and `recipient`, * the corresponding functions will be called with `data` and empty * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * Emits a {Sent} event. * * Requirements * * - the caller must have at least `amount` tokens. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function send( address recipient, uint256 amount, bytes calldata data ) external; /** * @dev Destroys `amount` tokens from the caller's account, reducing the * total supply. * * If a send hook is registered for the caller, the corresponding function * will be called with `data` and empty `operatorData`. See {IERC777Sender}. * * Emits a {Burned} event. * * Requirements * * - the caller must have at least `amount` tokens. */ function burn(uint256 amount, bytes calldata data) external; /** * @dev Returns true if an account is an operator of `tokenHolder`. * Operators can send and burn tokens on behalf of their owners. All * accounts are their own operator. * * See {operatorSend} and {operatorBurn}. */ function isOperatorFor(address operator, address tokenHolder) external view returns (bool); /** * @dev Make an account an operator of the caller. * * See {isOperatorFor}. * * Emits an {AuthorizedOperator} event. * * Requirements * * - `operator` cannot be calling address. */ function authorizeOperator(address operator) external; /** * @dev Revoke an account's operator status for the caller. * * See {isOperatorFor} and {defaultOperators}. * * Emits a {RevokedOperator} event. * * Requirements * * - `operator` cannot be calling address. */ function revokeOperator(address operator) external; /** * @dev Returns the list of default operators. These accounts are operators * for all token holders, even if {authorizeOperator} was never called on * them. * * This list is immutable, but individual holders may revoke these via * {revokeOperator}, in which case {isOperatorFor} will return false. */ function defaultOperators() external view returns (address[] memory); /** * @dev Moves `amount` tokens from `sender` to `recipient`. The caller must * be an operator of `sender`. * * If send or receive hooks are registered for `sender` and `recipient`, * the corresponding functions will be called with `data` and * `operatorData`. See {IERC777Sender} and {IERC777Recipient}. * * Emits a {Sent} event. * * Requirements * * - `sender` cannot be the zero address. * - `sender` must have at least `amount` tokens. * - the caller must be an operator for `sender`. * - `recipient` cannot be the zero address. * - if `recipient` is a contract, it must implement the {IERC777Recipient} * interface. */ function operatorSend( address sender, address recipient, uint256 amount, bytes calldata data, bytes calldata operatorData ) external; /** * @dev Destroys `amount` tokens from `account`, reducing the total supply. * The caller must be an operator of `account`. * * If a send hook is registered for `account`, the corresponding function * will be called with `data` and `operatorData`. See {IERC777Sender}. * * Emits a {Burned} event. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. * - the caller must be an operator for `account`. */ function operatorBurn( address account, uint256 amount, bytes calldata data, bytes calldata operatorData ) external; event Sent( address indexed operator, address indexed from, address indexed to, uint256 amount, bytes data, bytes operatorData ); event Minted(address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData); event Burned(address indexed operator, address indexed from, uint256 amount, bytes data, bytes operatorData); event AuthorizedOperator(address indexed operator, address indexed tokenHolder); event RevokedOperator(address indexed operator, address indexed tokenHolder); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (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`, 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 be 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: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * 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 Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @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 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); /** * @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; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; /** * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. */ interface IAccessControlEnumerable is IAccessControl { /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) external view returns (address); /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControlEnumerable.sol"; import "./AccessControl.sol"; import "../utils/structs/EnumerableSet.sol"; /** * @dev Extension of {AccessControl} that allows enumerating the members of each role. */ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { using EnumerableSet for EnumerableSet.AddressSet; mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { return _roleMembers[role].at(index); } /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { return _roleMembers[role].length(); } /** * @dev Overload {_grantRole} to track enumerable memberships */ function _grantRole(bytes32 role, address account) internal virtual override { super._grantRole(role, account); _roleMembers[role].add(account); } /** * @dev Overload {_revokeRole} to track enumerable memberships */ function _revokeRole(bytes32 role, address account) internal virtual override { super._revokeRole(role, account); _roleMembers[role].remove(account); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role, _msgSender()); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(uint160(account), 20), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
{ "remappings": [], "optimizer": { "enabled": false, "runs": 200 }, "evmVersion": "london", "libraries": {}, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"champTokenAddress","type":"address"},{"internalType":"address","name":"nfChampAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feesReceiver","type":"address"}],"name":"MarketplaceFeesReceiverUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"percentFees","type":"uint256"}],"name":"MarketplaceFeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"tokenId","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"tokenWeiPrice","type":"uint256"},{"indexed":false,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"}],"name":"SaleAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"tokenId","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"tokenWeiPrice","type":"uint256"},{"indexed":false,"internalType":"address","name":"seller","type":"address"}],"name":"SaleCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"tokenId","type":"uint64"},{"indexed":false,"internalType":"address","name":"seller","type":"address"}],"name":"SaleDestroyed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"tokenId","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"tokenWeiPrice","type":"uint256"},{"indexed":false,"internalType":"address","name":"seller","type":"address"}],"name":"SaleEdited","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_CHAMP_TOKEN_CONTRACT","outputs":[{"internalType":"contract IERC777","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_NFCHAMP_CONTRACT","outputs":[{"internalType":"contract IERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"weiPrice","type":"uint256"}],"name":"computeSaleShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint64","name":"tokenId","type":"uint64"},{"internalType":"uint256","name":"tokenWeiPrice","type":"uint256"}],"name":"createSaleFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint64","name":"tokenId","type":"uint64"}],"name":"destroySaleFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint64","name":"tokenId","type":"uint64"},{"internalType":"uint256","name":"tokenWeiPrice","type":"uint256"}],"name":"editSaleFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"tokenId","type":"uint64"}],"name":"getSale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"tokenId","type":"uint64"}],"name":"hasSale","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketplaceFeesReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketplacePercentFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nMarketplaceFeesReceiver","type":"address"}],"name":"setMarketplaceFeesReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nMarketplacePercentFees","type":"uint256"}],"name":"setMarketplacePercentFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"tokensReceived","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c06040523480156200001157600080fd5b5060405162004779380380620047798339818101604052810190620000379190620004b3565b8173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1681525050731820a4b7618bde71dce8cdc73aab6c95905fad2473ffffffffffffffffffffffffffffffffffffffff166329965a1d307fb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b306040518463ffffffff1660e01b8152600401620001129392919062000526565b600060405180830381600087803b1580156200012d57600080fd5b505af115801562000142573d6000803e3d6000fd5b505050506200016a6000801b6200015e620001b360201b60201c565b620001bb60201b60201c565b620001ab7f6c0757dc3e6b28b2580c03fd9e96c274acf4f99d91fbec9b418fa1d70604ff1c6200019f620001b360201b60201c565b620001bb60201b60201c565b505062000563565b600033905090565b620001cd8282620001d160201b60201c565b5050565b620001e882826200021960201b62001ae91760201c565b6200021481600160008581526020019081526020016000206200030a60201b62001bc91790919060201c565b505050565b6200022b82826200034260201b60201c565b6200030657600160008084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550620002ab620001b360201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b60006200033a836000018373ffffffffffffffffffffffffffffffffffffffff1660001b620003ac60201b60201c565b905092915050565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6000620003c083836200042660201b60201c565b6200041b57826000018290806001815401808255809150506001900390600052602060002001600090919091909150558260000180549050836001016000848152602001908152602001600020819055506001905062000420565b600090505b92915050565b600080836001016000848152602001908152602001600020541415905092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200047b826200044e565b9050919050565b6200048d816200046e565b81146200049957600080fd5b50565b600081519050620004ad8162000482565b92915050565b60008060408385031215620004cd57620004cc62000449565b5b6000620004dd858286016200049c565b9250506020620004f0858286016200049c565b9150509250929050565b62000505816200046e565b82525050565b6000819050919050565b62000520816200050b565b82525050565b60006060820190506200053d6000830186620004fa565b6200054c602083018562000515565b6200055b6040830184620004fa565b949350505050565b60805160a051614195620005e46000396000818161071d015281816107ee01528181610acc01528181610cce01528181610e0d01528181611062015281816111a10152818161139c015281816114db015281816115ce0152611a7a01526000818161052d0152818161087d015281816109130152610ff401526141956000f3fe608060405234801561001057600080fd5b50600436106101575760003560e01c8063700dd569116100c3578063a217fddf1161007c578063a217fddf146103d5578063ac9650d8146103f3578063adc6e2a114610423578063affebac814610453578063ca15c87314610471578063d547741f146104a157610157565b8063700dd569146102ee57806377bda66d1461030c578063817dfafa146103285780639010d07c1461034457806391d148541461037457806393744d91146103a457610157565b80632708a85e116101155780632708a85e146102425780632f2ff15d1461025e57806336568abe1461027a5780633c04c62a146102965780635b97a2b8146102b45780636d2d7233146102d057610157565b806223de291461015c57806301ffc9a71461017857806305db2f41146101a857806307bf86bc146101c65780630e2ae58d146101f6578063248a9ca314610212575b600080fd5b610176600480360381019061017191906126ef565b6104bd565b005b610192600480360381019061018d9190612816565b6109f2565b60405161019f919061285e565b60405180910390f35b6101b0610a6c565b6040516101bd9190612892565b60405180910390f35b6101e060048036038101906101db91906128ed565b610a90565b6040516101ed9190612929565b60405180910390f35b610210600480360381019061020b9190612944565b610b93565b005b61022c6004803603810190610227919061299d565b610c63565b6040516102399190612892565b60405180910390f35b61025c600480360381019061025791906129ca565b610c82565b005b61027860048036038101906102739190612a0a565b610f46565b005b610294600480360381019061028f9190612a0a565b610f6f565b005b61029e610ff2565b6040516102ab9190612aa9565b60405180910390f35b6102ce60048036038101906102c99190612ac4565b611016565b005b6102d8611321565b6040516102e59190612b26565b60405180910390f35b6102f661134b565b6040516103039190612929565b60405180910390f35b61032660048036038101906103219190612ac4565b611355565b005b610342600480360381019061033d9190612b41565b611768565b005b61035e60048036038101906103599190612b6e565b611866565b60405161036b9190612b26565b60405180910390f35b61038e60048036038101906103899190612a0a565b611895565b60405161039b919061285e565b60405180910390f35b6103be60048036038101906103b99190612b41565b6118ff565b6040516103cc929190612bae565b60405180910390f35b6103dd611951565b6040516103ea9190612892565b60405180910390f35b61040d60048036038101906104089190612c2d565b611958565b60405161041a9190612dd5565b60405180910390f35b61043d600480360381019061043891906128ed565b611a64565b60405161044a919061285e565b60405180910390f35b61045b611a78565b6040516104689190612e18565b60405180910390f35b61048b6004803603810190610486919061299d565b611a9c565b6040516104989190612929565b60405180910390f35b6104bb60048036038101906104b69190612a0a565b611ac0565b005b3073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161461052b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052290612eb6565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105b090612f48565b60405180910390fd5b600061060a85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506000611bf9565b905060006008868690501161061f578861066f565b61066e86868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506008611c60565b5b905061067a82611a64565b6106b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b090612fda565b60405180910390fd5b600260008367ffffffffffffffff16815260200190815260200160002054871015610719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161071090613092565b60405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636352211e846040518263ffffffff1660e01b815260040161077491906130e3565b602060405180830381865afa158015610791573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b59190613113565b90506000806107c38a6118ff565b8092508193505050600260008667ffffffffffffffff168152602001908152602001600020600090557f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166342842e0e8486886040518463ffffffff1660e01b815260040161084993929190613140565b600060405180830381600087803b15801561086357600080fd5b505af1158015610877573d6000803e3d6000fd5b505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bd9bbc684846040518363ffffffff1660e01b81526004016108d69291906131ae565b600060405180830381600087803b1580156108f057600080fd5b505af1158015610904573d6000803e3d6000fd5b5050505060008111156109a6577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639bd9bbc6610955611321565b836040518363ffffffff1660e01b81526004016109739291906131ae565b600060405180830381600087803b15801561098d57600080fd5b505af11580156109a1573d6000803e3d6000fd5b505050505b7fb795734250f05f62688d9821039f68f05bd28530787e4c725d6f7553a96141e2858b85876040516109db94939291906131f9565b60405180910390a150505050505050505050505050565b60007f5a05180f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610a655750610a6482611cd6565b5b9050919050565b7f6c0757dc3e6b28b2580c03fd9e96c274acf4f99d91fbec9b418fa1d70604ff1c81565b600080600260008467ffffffffffffffff1681526020019081526020016000205490503073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663081812fc856040518263ffffffff1660e01b8152600401610b2391906130e3565b602060405180830381865afa158015610b40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b649190613113565b73ffffffffffffffffffffffffffffffffffffffff1614610b89576000915050610b8e565b809150505b919050565b7f6c0757dc3e6b28b2580c03fd9e96c274acf4f99d91fbec9b418fa1d70604ff1c610bc581610bc0611d50565b611d58565b81600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fd43306b8a29f2760c884dda32eeac3b84440da7668e020dde1eb74c1b9de49bb600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051610c579190612b26565b60405180910390a15050565b6000806000838152602001908152602001600020600101549050919050565b610c8b81611a64565b610cca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc190612fda565b60405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b8152600401610d2591906130e3565b602060405180830381865afa158015610d42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d669190613113565b90508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610dd6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dcd906132b0565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610ea857507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e985e9c582336040518363ffffffff1660e01b8152600401610e669291906132d0565b602060405180830381865afa158015610e83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea79190613325565b5b610ee7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ede906133ea565b60405180910390fd5b600260008367ffffffffffffffff168152602001908152602001600020600090557fe7c2ec1cd6ab60088a5d4113d5b54c12a691e6a7e8facc605ebd65d460e208ad8282604051610f3992919061340a565b60405180910390a1505050565b610f4f82610c63565b610f6081610f5b611d50565b611d58565b610f6a8383611df5565b505050565b610f77611d50565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610fe4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fdb906134a5565b60405180910390fd5b610fee8282611e29565b5050565b7f000000000000000000000000000000000000000000000000000000000000000081565b61101f82611a64565b61105e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105590612fda565b60405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636352211e846040518263ffffffff1660e01b81526004016110b991906130e3565b602060405180830381865afa1580156110d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110fa9190613113565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461116a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161116190613537565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061123c57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e985e9c582336040518363ffffffff1660e01b81526004016111fa9291906132d0565b602060405180830381865afa158015611217573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123b9190613325565b5b61127b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611272906135ef565b60405180910390fd5b600082116112be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112b590613681565b60405180910390fd5b81600260008567ffffffffffffffff168152602001908152602001600020819055507f96890cb3590dcf8b7943cd4741d13a3bf4aed03a6ce4ad7703b2f480fbdb521a838383604051611313939291906136a1565b60405180910390a150505050565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600354905090565b60008111611398576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161138f90613681565b60405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16636352211e846040518263ffffffff1660e01b81526004016113f391906130e3565b602060405180830381865afa158015611410573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114349190613113565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146114a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149b9061374a565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061157657507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e985e9c582336040518363ffffffff1660e01b81526004016115349291906132d0565b602060405180830381865afa158015611551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115759190613325565b5b6115b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115ac90613802565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663081812fc856040518263ffffffff1660e01b815260040161162591906130e3565b602060405180830381865afa158015611642573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116669190613113565b73ffffffffffffffffffffffffffffffffffffffff16146116bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116b3906138ba565b60405180910390fd5b6116c583611a64565b15611705576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116fc90613972565b60405180910390fd5b81600260008567ffffffffffffffff168152602001908152602001600020819055507f7ec11357c3c29ca4a5e716912fe2cd4e5a348b6925642fd2af24f68c127877f883838360405161175a939291906136a1565b60405180910390a150505050565b7f6c0757dc3e6b28b2580c03fd9e96c274acf4f99d91fbec9b418fa1d70604ff1c61179a81611795611d50565b611d58565b60008210156117de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117d590613a04565b60405180910390fd5b6064821115611822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161181990613a96565b60405180910390fd5b816003819055507f08a00e376872180dabf2547e649b6fb86636951ea09594b1f160d51c4807a59a60035460405161185a9190612929565b60405180910390a15050565b600061188d8260016000868152602001908152602001600020611e5d90919063ffffffff16565b905092915050565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6000806000611931606461192361191461134b565b87611e7790919063ffffffff16565b611e8d90919063ffffffff16565b90506119468185611ea390919063ffffffff16565b819250925050915091565b6000801b81565b60608282905067ffffffffffffffff81111561197757611976613ab6565b5b6040519080825280602002602001820160405280156119aa57816020015b60608152602001906001900390816119955790505b50905060005b83839050811015611a5d57611a2c308585848181106119d2576119d1613ae5565b5b90506020028101906119e49190613b23565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611eb9565b828281518110611a3f57611a3e613ae5565b5b60200260200101819052508080611a5590613bb5565b9150506119b0565b5092915050565b600080611a7083610a90565b119050919050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000611ab960016000848152602001908152602001600020611ee6565b9050919050565b611ac982610c63565b611ada81611ad5611d50565b611d58565b611ae48383611e29565b505050565b611af38282611895565b611bc557600160008084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611b6a611d50565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b6000611bf1836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611efb565b905092915050565b6000600882611c089190613bfe565b83511015611c4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c4290613ca0565b60405180910390fd5b60008260088501015190508091505092915050565b6000601482611c6f9190613bfe565b83511015611cb2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ca990613d0c565b60405180910390fd5b60006c01000000000000000000000000836020860101510490508091505092915050565b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611d495750611d4882611f6b565b5b9050919050565b600033905090565b611d628282611895565b611df157611d878173ffffffffffffffffffffffffffffffffffffffff166014611fd5565b611d958360001c6020611fd5565b604051602001611da6929190613e0b565b6040516020818303038152906040526040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de89190613e7e565b60405180910390fd5b5050565b611dff8282611ae9565b611e248160016000858152602001908152602001600020611bc990919063ffffffff16565b505050565b611e338282612211565b611e5881600160008581526020019081526020016000206122f290919063ffffffff16565b505050565b6000611e6c8360000183612322565b60001c905092915050565b60008183611e859190613ea0565b905092915050565b60008183611e9b9190613f29565b905092915050565b60008183611eb19190613f5a565b905092915050565b6060611ede83836040518060600160405280602781526020016141396027913961234d565b905092915050565b6000611ef48260000161241a565b9050919050565b6000611f07838361242b565b611f60578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611f65565b600090505b92915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b606060006002836002611fe89190613ea0565b611ff29190613bfe565b67ffffffffffffffff81111561200b5761200a613ab6565b5b6040519080825280601f01601f19166020018201604052801561203d5781602001600182028036833780820191505090505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061207557612074613ae5565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106120d9576120d8613ae5565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026121199190613ea0565b6121239190613bfe565b90505b60018111156121c3577f3031323334353637383961626364656600000000000000000000000000000000600f86166010811061216557612164613ae5565b5b1a60f81b82828151811061217c5761217b613ae5565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c9450806121bc90613f8e565b9050612126565b5060008414612207576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121fe90614004565b60405180910390fd5b8091505092915050565b61221b8282611895565b156122ee57600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550612293611d50565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b600061231a836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61244e565b905092915050565b600082600001828154811061233a57612339613ae5565b5b9060005260206000200154905092915050565b606061235884612562565b612397576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161238e90614096565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516123bf91906140f2565b600060405180830381855af49150503d80600081146123fa576040519150601f19603f3d011682016040523d82523d6000602084013e6123ff565b606091505b509150915061240f828286612585565b925050509392505050565b600081600001805490509050919050565b600080836001016000848152602001908152602001600020541415905092915050565b600080836001016000848152602001908152602001600020549050600081146125565760006001826124809190613f5a565b90506000600186600001805490506124989190613f5a565b90508181146125075760008660000182815481106124b9576124b8613ae5565b5b90600052602060002001549050808760000184815481106124dd576124dc613ae5565b5b90600052602060002001819055508387600101600083815260200190815260200160002081905550505b8560000180548061251b5761251a614109565b5b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061255c565b60009150505b92915050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60608315612595578290506125e5565b6000835111156125a85782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125dc9190613e7e565b60405180910390fd5b9392505050565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612621826125f6565b9050919050565b61263181612616565b811461263c57600080fd5b50565b60008135905061264e81612628565b92915050565b6000819050919050565b61266781612654565b811461267257600080fd5b50565b6000813590506126848161265e565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126126af576126ae61268a565b5b8235905067ffffffffffffffff8111156126cc576126cb61268f565b5b6020830191508360018202830111156126e8576126e7612694565b5b9250929050565b60008060008060008060008060c0898b03121561270f5761270e6125ec565b5b600061271d8b828c0161263f565b985050602061272e8b828c0161263f565b975050604061273f8b828c0161263f565b96505060606127508b828c01612675565b955050608089013567ffffffffffffffff811115612771576127706125f1565b5b61277d8b828c01612699565b945094505060a089013567ffffffffffffffff8111156127a05761279f6125f1565b5b6127ac8b828c01612699565b92509250509295985092959890939650565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6127f3816127be565b81146127fe57600080fd5b50565b600081359050612810816127ea565b92915050565b60006020828403121561282c5761282b6125ec565b5b600061283a84828501612801565b91505092915050565b60008115159050919050565b61285881612843565b82525050565b6000602082019050612873600083018461284f565b92915050565b6000819050919050565b61288c81612879565b82525050565b60006020820190506128a76000830184612883565b92915050565b600067ffffffffffffffff82169050919050565b6128ca816128ad565b81146128d557600080fd5b50565b6000813590506128e7816128c1565b92915050565b600060208284031215612903576129026125ec565b5b6000612911848285016128d8565b91505092915050565b61292381612654565b82525050565b600060208201905061293e600083018461291a565b92915050565b60006020828403121561295a576129596125ec565b5b60006129688482850161263f565b91505092915050565b61297a81612879565b811461298557600080fd5b50565b60008135905061299781612971565b92915050565b6000602082840312156129b3576129b26125ec565b5b60006129c184828501612988565b91505092915050565b600080604083850312156129e1576129e06125ec565b5b60006129ef8582860161263f565b9250506020612a00858286016128d8565b9150509250929050565b60008060408385031215612a2157612a206125ec565b5b6000612a2f85828601612988565b9250506020612a408582860161263f565b9150509250929050565b6000819050919050565b6000612a6f612a6a612a65846125f6565b612a4a565b6125f6565b9050919050565b6000612a8182612a54565b9050919050565b6000612a9382612a76565b9050919050565b612aa381612a88565b82525050565b6000602082019050612abe6000830184612a9a565b92915050565b600080600060608486031215612add57612adc6125ec565b5b6000612aeb8682870161263f565b9350506020612afc868287016128d8565b9250506040612b0d86828701612675565b9150509250925092565b612b2081612616565b82525050565b6000602082019050612b3b6000830184612b17565b92915050565b600060208284031215612b5757612b566125ec565b5b6000612b6584828501612675565b91505092915050565b60008060408385031215612b8557612b846125ec565b5b6000612b9385828601612988565b9250506020612ba485828601612675565b9150509250929050565b6000604082019050612bc3600083018561291a565b612bd0602083018461291a565b9392505050565b60008083601f840112612bed57612bec61268a565b5b8235905067ffffffffffffffff811115612c0a57612c0961268f565b5b602083019150836020820283011115612c2657612c25612694565b5b9250929050565b60008060208385031215612c4457612c436125ec565b5b600083013567ffffffffffffffff811115612c6257612c616125f1565b5b612c6e85828601612bd7565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612ce0578082015181840152602081019050612cc5565b83811115612cef576000848401525b50505050565b6000601f19601f8301169050919050565b6000612d1182612ca6565b612d1b8185612cb1565b9350612d2b818560208601612cc2565b612d3481612cf5565b840191505092915050565b6000612d4b8383612d06565b905092915050565b6000602082019050919050565b6000612d6b82612c7a565b612d758185612c85565b935083602082028501612d8785612c96565b8060005b85811015612dc35784840389528151612da48582612d3f565b9450612daf83612d53565b925060208a01995050600181019050612d8b565b50829750879550505050505092915050565b60006020820190508181036000830152612def8184612d60565b905092915050565b6000612e0282612a76565b9050919050565b612e1281612df7565b82525050565b6000602082019050612e2d6000830184612e09565b92915050565b600082825260208201905092915050565b7f4368616d704d61726b6574706c6163653a20496e76616c69642072656369706960008201527f656e740000000000000000000000000000000000000000000000000000000000602082015250565b6000612ea0602383612e33565b9150612eab82612e44565b604082019050919050565b60006020820190508181036000830152612ecf81612e93565b9050919050565b7f4368616d704d61726b6574706c6163653a20496e76616c69642045524337373760008201527f20746f6b656e0000000000000000000000000000000000000000000000000000602082015250565b6000612f32602683612e33565b9150612f3d82612ed6565b604082019050919050565b60006020820190508181036000830152612f6181612f25565b9050919050565b7f4368616d704d61726b6574706c6163653a2053616c6520646f6573206e6f742060008201527f6578697374730000000000000000000000000000000000000000000000000000602082015250565b6000612fc4602683612e33565b9150612fcf82612f68565b604082019050919050565b60006020820190508181036000830152612ff381612fb7565b9050919050565b7f4368616d704d61726b6574706c6163653a20596f75206d757374206d6174636860008201527f207468652073616c6520707269636520746f206163636570742074686520736160208201527f6c652e0000000000000000000000000000000000000000000000000000000000604082015250565b600061307c604383612e33565b915061308782612ffa565b606082019050919050565b600060208201905081810360008301526130ab8161306f565b9050919050565b60006130cd6130c86130c3846128ad565b612a4a565b612654565b9050919050565b6130dd816130b2565b82525050565b60006020820190506130f860008301846130d4565b92915050565b60008151905061310d81612628565b92915050565b600060208284031215613129576131286125ec565b5b6000613137848285016130fe565b91505092915050565b60006060820190506131556000830186612b17565b6131626020830185612b17565b61316f60408301846130d4565b949350505050565b600082825260208201905092915050565b50565b6000613198600083613177565b91506131a382613188565b600082019050919050565b60006060820190506131c36000830185612b17565b6131d0602083018461291a565b81810360408301526131e18161318b565b90509392505050565b6131f3816128ad565b82525050565b600060808201905061320e60008301876131ea565b61321b602083018661291a565b6132286040830185612b17565b6132356060830184612b17565b95945050505050565b7f4368616d704d61726b6574706c6163653a2044657374726f792073616c65206f60008201527f6620746f6b656e2074686174206973206e6f74206f776e000000000000000000602082015250565b600061329a603783612e33565b91506132a58261323e565b604082019050919050565b600060208201905081810360008301526132c98161328d565b9050919050565b60006040820190506132e56000830185612b17565b6132f26020830184612b17565b9392505050565b61330281612843565b811461330d57600080fd5b50565b60008151905061331f816132f9565b92915050565b60006020828403121561333b5761333a6125ec565b5b600061334984828501613310565b91505092915050565b7f4368616d704d61726b6574706c6163653a204f6e6c792074686520746f6b656e60008201527f206f776e6572206f7220697473206f70657261746f722061726520616c6c6f7760208201527f656420746f2064657374726f7920612073616c652e0000000000000000000000604082015250565b60006133d4605583612e33565b91506133df82613352565b606082019050919050565b60006020820190508181036000830152613403816133c7565b9050919050565b600060408201905061341f60008301856131ea565b61342c6020830184612b17565b9392505050565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b600061348f602f83612e33565b915061349a82613433565b604082019050919050565b600060208201905081810360008301526134be81613482565b9050919050565b7f4368616d704d61726b6574706c6163653a20456469742073616c65206f66207460008201527f6f6b656e2074686174206973206e6f74206f776e000000000000000000000000602082015250565b6000613521603483612e33565b915061352c826134c5565b604082019050919050565b6000602082019050818103600083015261355081613514565b9050919050565b7f4368616d704d61726b6574706c6163653a204f6e6c792074686520746f6b656e60008201527f206f776e6572206f7220697473206f70657261746f722061726520616c6c6f7760208201527f656420746f206564697420612073616c652e0000000000000000000000000000604082015250565b60006135d9605283612e33565b91506135e482613557565b606082019050919050565b60006020820190508181036000830152613608816135cc565b9050919050565b7f4368616d704d61726b6574706c6163653a2050726963652073686f756c64206260008201527f65207374726963746c7920706f73697469766500000000000000000000000000602082015250565b600061366b603383612e33565b91506136768261360f565b604082019050919050565b6000602082019050818103600083015261369a8161365e565b9050919050565b60006060820190506136b660008301866131ea565b6136c3602083018561291a565b6136d06040830184612b17565b949350505050565b7f4368616d704d61726b6574706c6163653a204372656174652073616c65206f6660008201527f20746f6b656e2074686174206973206e6f74206f776e00000000000000000000602082015250565b6000613734603683612e33565b915061373f826136d8565b604082019050919050565b6000602082019050818103600083015261376381613727565b9050919050565b7f4368616d704d61726b6574706c6163653a204f6e6c792074686520746f6b656e60008201527f206f776e6572206f7220697473206f70657261746f722061726520616c6c6f7760208201527f656420746f2063726561746520612073616c652e000000000000000000000000604082015250565b60006137ec605483612e33565b91506137f78261376a565b606082019050919050565b6000602082019050818103600083015261381b816137df565b9050919050565b7f4368616d704d61726b6574706c6163653a20436f6e74726163742073686f756c60008201527f6420626520617070726f7665642062792074686520746f6b656e206f776e657260208201527f2e00000000000000000000000000000000000000000000000000000000000000604082015250565b60006138a4604183612e33565b91506138af82613822565b606082019050919050565b600060208201905081810360008301526138d381613897565b9050919050565b7f4368616d704d61726b6574706c6163653a2053616c6520616c7265616479206560008201527f78697374732e2044657374726f79207468652070726576696f75732073616c6560208201527f2066697273742e00000000000000000000000000000000000000000000000000604082015250565b600061395c604783612e33565b9150613967826138da565b606082019050919050565b6000602082019050818103600083015261398b8161394f565b9050919050565b7f4368616d704d61726b6574706c6163653a206e4d61726b6574706c616365506560008201527f7263656e74466565732073686f756c6420626520706f73697469766500000000602082015250565b60006139ee603c83612e33565b91506139f982613992565b604082019050919050565b60006020820190508181036000830152613a1d816139e1565b9050919050565b7f4368616d704d61726b6574706c6163653a206e4d61726b6574706c616365506560008201527f7263656e74466565732073686f756c642062652062656c6f7720313030000000602082015250565b6000613a80603d83612e33565b9150613a8b82613a24565b604082019050919050565b60006020820190508181036000830152613aaf81613a73565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b600080fd5b600080fd5b60008083356001602003843603038112613b4057613b3f613b14565b5b80840192508235915067ffffffffffffffff821115613b6257613b61613b19565b5b602083019250600182023603831315613b7e57613b7d613b1e565b5b509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613bc082612654565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613bf357613bf2613b86565b5b600182019050919050565b6000613c0982612654565b9150613c1483612654565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115613c4957613c48613b86565b5b828201905092915050565b7f746f55696e7436345f6f75744f66426f756e6473000000000000000000000000600082015250565b6000613c8a601483612e33565b9150613c9582613c54565b602082019050919050565b60006020820190508181036000830152613cb981613c7d565b9050919050565b7f746f416464726573735f6f75744f66426f756e64730000000000000000000000600082015250565b6000613cf6601583612e33565b9150613d0182613cc0565b602082019050919050565b60006020820190508181036000830152613d2581613ce9565b9050919050565b600081905092915050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b6000613d6d601783613d2c565b9150613d7882613d37565b601782019050919050565b600081519050919050565b6000613d9982613d83565b613da38185613d2c565b9350613db3818560208601612cc2565b80840191505092915050565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b6000613df5601183613d2c565b9150613e0082613dbf565b601182019050919050565b6000613e1682613d60565b9150613e228285613d8e565b9150613e2d82613de8565b9150613e398284613d8e565b91508190509392505050565b6000613e5082613d83565b613e5a8185612e33565b9350613e6a818560208601612cc2565b613e7381612cf5565b840191505092915050565b60006020820190508181036000830152613e988184613e45565b905092915050565b6000613eab82612654565b9150613eb683612654565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613eef57613eee613b86565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613f3482612654565b9150613f3f83612654565b925082613f4f57613f4e613efa565b5b828204905092915050565b6000613f6582612654565b9150613f7083612654565b925082821015613f8357613f82613b86565b5b828203905092915050565b6000613f9982612654565b91506000821415613fad57613fac613b86565b5b600182039050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b6000613fee602083612e33565b9150613ff982613fb8565b602082019050919050565b6000602082019050818103600083015261401d81613fe1565b9050919050565b7f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60008201527f6e74726163740000000000000000000000000000000000000000000000000000602082015250565b6000614080602683612e33565b915061408b82614024565b604082019050919050565b600060208201905081810360008301526140af81614073565b9050919050565b600081905092915050565b60006140cc82612ca6565b6140d681856140b6565b93506140e6818560208601612cc2565b80840191505092915050565b60006140fe82846140c1565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212208ad442db3045e884dc76f910bcdf1831bc7d403a179765945bd6ac948528394e64736f6c634300080c0033000000000000000000000000ed755dba6ec1eb520076cec051a582a6d81a82530000000000000000000000007f61345bdd61b4192324d612fcecd795ce4b60bd
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101575760003560e01c8063700dd569116100c3578063a217fddf1161007c578063a217fddf146103d5578063ac9650d8146103f3578063adc6e2a114610423578063affebac814610453578063ca15c87314610471578063d547741f146104a157610157565b8063700dd569146102ee57806377bda66d1461030c578063817dfafa146103285780639010d07c1461034457806391d148541461037457806393744d91146103a457610157565b80632708a85e116101155780632708a85e146102425780632f2ff15d1461025e57806336568abe1461027a5780633c04c62a146102965780635b97a2b8146102b45780636d2d7233146102d057610157565b806223de291461015c57806301ffc9a71461017857806305db2f41146101a857806307bf86bc146101c65780630e2ae58d146101f6578063248a9ca314610212575b600080fd5b610176600480360381019061017191906126ef565b6104bd565b005b610192600480360381019061018d9190612816565b6109f2565b60405161019f919061285e565b60405180910390f35b6101b0610a6c565b6040516101bd9190612892565b60405180910390f35b6101e060048036038101906101db91906128ed565b610a90565b6040516101ed9190612929565b60405180910390f35b610210600480360381019061020b9190612944565b610b93565b005b61022c6004803603810190610227919061299d565b610c63565b6040516102399190612892565b60405180910390f35b61025c600480360381019061025791906129ca565b610c82565b005b61027860048036038101906102739190612a0a565b610f46565b005b610294600480360381019061028f9190612a0a565b610f6f565b005b61029e610ff2565b6040516102ab9190612aa9565b60405180910390f35b6102ce60048036038101906102c99190612ac4565b611016565b005b6102d8611321565b6040516102e59190612b26565b60405180910390f35b6102f661134b565b6040516103039190612929565b60405180910390f35b61032660048036038101906103219190612ac4565b611355565b005b610342600480360381019061033d9190612b41565b611768565b005b61035e60048036038101906103599190612b6e565b611866565b60405161036b9190612b26565b60405180910390f35b61038e60048036038101906103899190612a0a565b611895565b60405161039b919061285e565b60405180910390f35b6103be60048036038101906103b99190612b41565b6118ff565b6040516103cc929190612bae565b60405180910390f35b6103dd611951565b6040516103ea9190612892565b60405180910390f35b61040d60048036038101906104089190612c2d565b611958565b60405161041a9190612dd5565b60405180910390f35b61043d600480360381019061043891906128ed565b611a64565b60405161044a919061285e565b60405180910390f35b61045b611a78565b6040516104689190612e18565b60405180910390f35b61048b6004803603810190610486919061299d565b611a9c565b6040516104989190612929565b60405180910390f35b6104bb60048036038101906104b69190612a0a565b611ac0565b005b3073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161461052b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052290612eb6565b60405180910390fd5b7f000000000000000000000000ed755dba6ec1eb520076cec051a582a6d81a825373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146105b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105b090612f48565b60405180910390fd5b600061060a85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506000611bf9565b905060006008868690501161061f578861066f565b61066e86868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506008611c60565b5b905061067a82611a64565b6106b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b090612fda565b60405180910390fd5b600260008367ffffffffffffffff16815260200190815260200160002054871015610719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161071090613092565b60405180910390fd5b60007f0000000000000000000000007f61345bdd61b4192324d612fcecd795ce4b60bd73ffffffffffffffffffffffffffffffffffffffff16636352211e846040518263ffffffff1660e01b815260040161077491906130e3565b602060405180830381865afa158015610791573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b59190613113565b90506000806107c38a6118ff565b8092508193505050600260008667ffffffffffffffff168152602001908152602001600020600090557f0000000000000000000000007f61345bdd61b4192324d612fcecd795ce4b60bd73ffffffffffffffffffffffffffffffffffffffff166342842e0e8486886040518463ffffffff1660e01b815260040161084993929190613140565b600060405180830381600087803b15801561086357600080fd5b505af1158015610877573d6000803e3d6000fd5b505050507f000000000000000000000000ed755dba6ec1eb520076cec051a582a6d81a825373ffffffffffffffffffffffffffffffffffffffff16639bd9bbc684846040518363ffffffff1660e01b81526004016108d69291906131ae565b600060405180830381600087803b1580156108f057600080fd5b505af1158015610904573d6000803e3d6000fd5b5050505060008111156109a6577f000000000000000000000000ed755dba6ec1eb520076cec051a582a6d81a825373ffffffffffffffffffffffffffffffffffffffff16639bd9bbc6610955611321565b836040518363ffffffff1660e01b81526004016109739291906131ae565b600060405180830381600087803b15801561098d57600080fd5b505af11580156109a1573d6000803e3d6000fd5b505050505b7fb795734250f05f62688d9821039f68f05bd28530787e4c725d6f7553a96141e2858b85876040516109db94939291906131f9565b60405180910390a150505050505050505050505050565b60007f5a05180f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610a655750610a6482611cd6565b5b9050919050565b7f6c0757dc3e6b28b2580c03fd9e96c274acf4f99d91fbec9b418fa1d70604ff1c81565b600080600260008467ffffffffffffffff1681526020019081526020016000205490503073ffffffffffffffffffffffffffffffffffffffff167f0000000000000000000000007f61345bdd61b4192324d612fcecd795ce4b60bd73ffffffffffffffffffffffffffffffffffffffff1663081812fc856040518263ffffffff1660e01b8152600401610b2391906130e3565b602060405180830381865afa158015610b40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b649190613113565b73ffffffffffffffffffffffffffffffffffffffff1614610b89576000915050610b8e565b809150505b919050565b7f6c0757dc3e6b28b2580c03fd9e96c274acf4f99d91fbec9b418fa1d70604ff1c610bc581610bc0611d50565b611d58565b81600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fd43306b8a29f2760c884dda32eeac3b84440da7668e020dde1eb74c1b9de49bb600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051610c579190612b26565b60405180910390a15050565b6000806000838152602001908152602001600020600101549050919050565b610c8b81611a64565b610cca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cc190612fda565b60405180910390fd5b60007f0000000000000000000000007f61345bdd61b4192324d612fcecd795ce4b60bd73ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b8152600401610d2591906130e3565b602060405180830381865afa158015610d42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d669190613113565b90508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610dd6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dcd906132b0565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161480610ea857507f0000000000000000000000007f61345bdd61b4192324d612fcecd795ce4b60bd73ffffffffffffffffffffffffffffffffffffffff1663e985e9c582336040518363ffffffff1660e01b8152600401610e669291906132d0565b602060405180830381865afa158015610e83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea79190613325565b5b610ee7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ede906133ea565b60405180910390fd5b600260008367ffffffffffffffff168152602001908152602001600020600090557fe7c2ec1cd6ab60088a5d4113d5b54c12a691e6a7e8facc605ebd65d460e208ad8282604051610f3992919061340a565b60405180910390a1505050565b610f4f82610c63565b610f6081610f5b611d50565b611d58565b610f6a8383611df5565b505050565b610f77611d50565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610fe4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fdb906134a5565b60405180910390fd5b610fee8282611e29565b5050565b7f000000000000000000000000ed755dba6ec1eb520076cec051a582a6d81a825381565b61101f82611a64565b61105e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105590612fda565b60405180910390fd5b60007f0000000000000000000000007f61345bdd61b4192324d612fcecd795ce4b60bd73ffffffffffffffffffffffffffffffffffffffff16636352211e846040518263ffffffff1660e01b81526004016110b991906130e3565b602060405180830381865afa1580156110d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110fa9190613113565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461116a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161116190613537565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061123c57507f0000000000000000000000007f61345bdd61b4192324d612fcecd795ce4b60bd73ffffffffffffffffffffffffffffffffffffffff1663e985e9c582336040518363ffffffff1660e01b81526004016111fa9291906132d0565b602060405180830381865afa158015611217573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123b9190613325565b5b61127b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611272906135ef565b60405180910390fd5b600082116112be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112b590613681565b60405180910390fd5b81600260008567ffffffffffffffff168152602001908152602001600020819055507f96890cb3590dcf8b7943cd4741d13a3bf4aed03a6ce4ad7703b2f480fbdb521a838383604051611313939291906136a1565b60405180910390a150505050565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600354905090565b60008111611398576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161138f90613681565b60405180910390fd5b60007f0000000000000000000000007f61345bdd61b4192324d612fcecd795ce4b60bd73ffffffffffffffffffffffffffffffffffffffff16636352211e846040518263ffffffff1660e01b81526004016113f391906130e3565b602060405180830381865afa158015611410573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114349190613113565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146114a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161149b9061374a565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061157657507f0000000000000000000000007f61345bdd61b4192324d612fcecd795ce4b60bd73ffffffffffffffffffffffffffffffffffffffff1663e985e9c582336040518363ffffffff1660e01b81526004016115349291906132d0565b602060405180830381865afa158015611551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115759190613325565b5b6115b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115ac90613802565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff167f0000000000000000000000007f61345bdd61b4192324d612fcecd795ce4b60bd73ffffffffffffffffffffffffffffffffffffffff1663081812fc856040518263ffffffff1660e01b815260040161162591906130e3565b602060405180830381865afa158015611642573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116669190613113565b73ffffffffffffffffffffffffffffffffffffffff16146116bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116b3906138ba565b60405180910390fd5b6116c583611a64565b15611705576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116fc90613972565b60405180910390fd5b81600260008567ffffffffffffffff168152602001908152602001600020819055507f7ec11357c3c29ca4a5e716912fe2cd4e5a348b6925642fd2af24f68c127877f883838360405161175a939291906136a1565b60405180910390a150505050565b7f6c0757dc3e6b28b2580c03fd9e96c274acf4f99d91fbec9b418fa1d70604ff1c61179a81611795611d50565b611d58565b60008210156117de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117d590613a04565b60405180910390fd5b6064821115611822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161181990613a96565b60405180910390fd5b816003819055507f08a00e376872180dabf2547e649b6fb86636951ea09594b1f160d51c4807a59a60035460405161185a9190612929565b60405180910390a15050565b600061188d8260016000868152602001908152602001600020611e5d90919063ffffffff16565b905092915050565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6000806000611931606461192361191461134b565b87611e7790919063ffffffff16565b611e8d90919063ffffffff16565b90506119468185611ea390919063ffffffff16565b819250925050915091565b6000801b81565b60608282905067ffffffffffffffff81111561197757611976613ab6565b5b6040519080825280602002602001820160405280156119aa57816020015b60608152602001906001900390816119955790505b50905060005b83839050811015611a5d57611a2c308585848181106119d2576119d1613ae5565b5b90506020028101906119e49190613b23565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050611eb9565b828281518110611a3f57611a3e613ae5565b5b60200260200101819052508080611a5590613bb5565b9150506119b0565b5092915050565b600080611a7083610a90565b119050919050565b7f0000000000000000000000007f61345bdd61b4192324d612fcecd795ce4b60bd81565b6000611ab960016000848152602001908152602001600020611ee6565b9050919050565b611ac982610c63565b611ada81611ad5611d50565b611d58565b611ae48383611e29565b505050565b611af38282611895565b611bc557600160008084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611b6a611d50565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b6000611bf1836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611efb565b905092915050565b6000600882611c089190613bfe565b83511015611c4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c4290613ca0565b60405180910390fd5b60008260088501015190508091505092915050565b6000601482611c6f9190613bfe565b83511015611cb2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ca990613d0c565b60405180910390fd5b60006c01000000000000000000000000836020860101510490508091505092915050565b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611d495750611d4882611f6b565b5b9050919050565b600033905090565b611d628282611895565b611df157611d878173ffffffffffffffffffffffffffffffffffffffff166014611fd5565b611d958360001c6020611fd5565b604051602001611da6929190613e0b565b6040516020818303038152906040526040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de89190613e7e565b60405180910390fd5b5050565b611dff8282611ae9565b611e248160016000858152602001908152602001600020611bc990919063ffffffff16565b505050565b611e338282612211565b611e5881600160008581526020019081526020016000206122f290919063ffffffff16565b505050565b6000611e6c8360000183612322565b60001c905092915050565b60008183611e859190613ea0565b905092915050565b60008183611e9b9190613f29565b905092915050565b60008183611eb19190613f5a565b905092915050565b6060611ede83836040518060600160405280602781526020016141396027913961234d565b905092915050565b6000611ef48260000161241a565b9050919050565b6000611f07838361242b565b611f60578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611f65565b600090505b92915050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b606060006002836002611fe89190613ea0565b611ff29190613bfe565b67ffffffffffffffff81111561200b5761200a613ab6565b5b6040519080825280601f01601f19166020018201604052801561203d5781602001600182028036833780820191505090505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061207557612074613ae5565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106120d9576120d8613ae5565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026121199190613ea0565b6121239190613bfe565b90505b60018111156121c3577f3031323334353637383961626364656600000000000000000000000000000000600f86166010811061216557612164613ae5565b5b1a60f81b82828151811061217c5761217b613ae5565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c9450806121bc90613f8e565b9050612126565b5060008414612207576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121fe90614004565b60405180910390fd5b8091505092915050565b61221b8282611895565b156122ee57600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550612293611d50565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b600061231a836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61244e565b905092915050565b600082600001828154811061233a57612339613ae5565b5b9060005260206000200154905092915050565b606061235884612562565b612397576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161238e90614096565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516123bf91906140f2565b600060405180830381855af49150503d80600081146123fa576040519150601f19603f3d011682016040523d82523d6000602084013e6123ff565b606091505b509150915061240f828286612585565b925050509392505050565b600081600001805490509050919050565b600080836001016000848152602001908152602001600020541415905092915050565b600080836001016000848152602001908152602001600020549050600081146125565760006001826124809190613f5a565b90506000600186600001805490506124989190613f5a565b90508181146125075760008660000182815481106124b9576124b8613ae5565b5b90600052602060002001549050808760000184815481106124dd576124dc613ae5565b5b90600052602060002001819055508387600101600083815260200190815260200160002081905550505b8560000180548061251b5761251a614109565b5b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061255c565b60009150505b92915050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b60608315612595578290506125e5565b6000835111156125a85782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125dc9190613e7e565b60405180910390fd5b9392505050565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612621826125f6565b9050919050565b61263181612616565b811461263c57600080fd5b50565b60008135905061264e81612628565b92915050565b6000819050919050565b61266781612654565b811461267257600080fd5b50565b6000813590506126848161265e565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126126af576126ae61268a565b5b8235905067ffffffffffffffff8111156126cc576126cb61268f565b5b6020830191508360018202830111156126e8576126e7612694565b5b9250929050565b60008060008060008060008060c0898b03121561270f5761270e6125ec565b5b600061271d8b828c0161263f565b985050602061272e8b828c0161263f565b975050604061273f8b828c0161263f565b96505060606127508b828c01612675565b955050608089013567ffffffffffffffff811115612771576127706125f1565b5b61277d8b828c01612699565b945094505060a089013567ffffffffffffffff8111156127a05761279f6125f1565b5b6127ac8b828c01612699565b92509250509295985092959890939650565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6127f3816127be565b81146127fe57600080fd5b50565b600081359050612810816127ea565b92915050565b60006020828403121561282c5761282b6125ec565b5b600061283a84828501612801565b91505092915050565b60008115159050919050565b61285881612843565b82525050565b6000602082019050612873600083018461284f565b92915050565b6000819050919050565b61288c81612879565b82525050565b60006020820190506128a76000830184612883565b92915050565b600067ffffffffffffffff82169050919050565b6128ca816128ad565b81146128d557600080fd5b50565b6000813590506128e7816128c1565b92915050565b600060208284031215612903576129026125ec565b5b6000612911848285016128d8565b91505092915050565b61292381612654565b82525050565b600060208201905061293e600083018461291a565b92915050565b60006020828403121561295a576129596125ec565b5b60006129688482850161263f565b91505092915050565b61297a81612879565b811461298557600080fd5b50565b60008135905061299781612971565b92915050565b6000602082840312156129b3576129b26125ec565b5b60006129c184828501612988565b91505092915050565b600080604083850312156129e1576129e06125ec565b5b60006129ef8582860161263f565b9250506020612a00858286016128d8565b9150509250929050565b60008060408385031215612a2157612a206125ec565b5b6000612a2f85828601612988565b9250506020612a408582860161263f565b9150509250929050565b6000819050919050565b6000612a6f612a6a612a65846125f6565b612a4a565b6125f6565b9050919050565b6000612a8182612a54565b9050919050565b6000612a9382612a76565b9050919050565b612aa381612a88565b82525050565b6000602082019050612abe6000830184612a9a565b92915050565b600080600060608486031215612add57612adc6125ec565b5b6000612aeb8682870161263f565b9350506020612afc868287016128d8565b9250506040612b0d86828701612675565b9150509250925092565b612b2081612616565b82525050565b6000602082019050612b3b6000830184612b17565b92915050565b600060208284031215612b5757612b566125ec565b5b6000612b6584828501612675565b91505092915050565b60008060408385031215612b8557612b846125ec565b5b6000612b9385828601612988565b9250506020612ba485828601612675565b9150509250929050565b6000604082019050612bc3600083018561291a565b612bd0602083018461291a565b9392505050565b60008083601f840112612bed57612bec61268a565b5b8235905067ffffffffffffffff811115612c0a57612c0961268f565b5b602083019150836020820283011115612c2657612c25612694565b5b9250929050565b60008060208385031215612c4457612c436125ec565b5b600083013567ffffffffffffffff811115612c6257612c616125f1565b5b612c6e85828601612bd7565b92509250509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612ce0578082015181840152602081019050612cc5565b83811115612cef576000848401525b50505050565b6000601f19601f8301169050919050565b6000612d1182612ca6565b612d1b8185612cb1565b9350612d2b818560208601612cc2565b612d3481612cf5565b840191505092915050565b6000612d4b8383612d06565b905092915050565b6000602082019050919050565b6000612d6b82612c7a565b612d758185612c85565b935083602082028501612d8785612c96565b8060005b85811015612dc35784840389528151612da48582612d3f565b9450612daf83612d53565b925060208a01995050600181019050612d8b565b50829750879550505050505092915050565b60006020820190508181036000830152612def8184612d60565b905092915050565b6000612e0282612a76565b9050919050565b612e1281612df7565b82525050565b6000602082019050612e2d6000830184612e09565b92915050565b600082825260208201905092915050565b7f4368616d704d61726b6574706c6163653a20496e76616c69642072656369706960008201527f656e740000000000000000000000000000000000000000000000000000000000602082015250565b6000612ea0602383612e33565b9150612eab82612e44565b604082019050919050565b60006020820190508181036000830152612ecf81612e93565b9050919050565b7f4368616d704d61726b6574706c6163653a20496e76616c69642045524337373760008201527f20746f6b656e0000000000000000000000000000000000000000000000000000602082015250565b6000612f32602683612e33565b9150612f3d82612ed6565b604082019050919050565b60006020820190508181036000830152612f6181612f25565b9050919050565b7f4368616d704d61726b6574706c6163653a2053616c6520646f6573206e6f742060008201527f6578697374730000000000000000000000000000000000000000000000000000602082015250565b6000612fc4602683612e33565b9150612fcf82612f68565b604082019050919050565b60006020820190508181036000830152612ff381612fb7565b9050919050565b7f4368616d704d61726b6574706c6163653a20596f75206d757374206d6174636860008201527f207468652073616c6520707269636520746f206163636570742074686520736160208201527f6c652e0000000000000000000000000000000000000000000000000000000000604082015250565b600061307c604383612e33565b915061308782612ffa565b606082019050919050565b600060208201905081810360008301526130ab8161306f565b9050919050565b60006130cd6130c86130c3846128ad565b612a4a565b612654565b9050919050565b6130dd816130b2565b82525050565b60006020820190506130f860008301846130d4565b92915050565b60008151905061310d81612628565b92915050565b600060208284031215613129576131286125ec565b5b6000613137848285016130fe565b91505092915050565b60006060820190506131556000830186612b17565b6131626020830185612b17565b61316f60408301846130d4565b949350505050565b600082825260208201905092915050565b50565b6000613198600083613177565b91506131a382613188565b600082019050919050565b60006060820190506131c36000830185612b17565b6131d0602083018461291a565b81810360408301526131e18161318b565b90509392505050565b6131f3816128ad565b82525050565b600060808201905061320e60008301876131ea565b61321b602083018661291a565b6132286040830185612b17565b6132356060830184612b17565b95945050505050565b7f4368616d704d61726b6574706c6163653a2044657374726f792073616c65206f60008201527f6620746f6b656e2074686174206973206e6f74206f776e000000000000000000602082015250565b600061329a603783612e33565b91506132a58261323e565b604082019050919050565b600060208201905081810360008301526132c98161328d565b9050919050565b60006040820190506132e56000830185612b17565b6132f26020830184612b17565b9392505050565b61330281612843565b811461330d57600080fd5b50565b60008151905061331f816132f9565b92915050565b60006020828403121561333b5761333a6125ec565b5b600061334984828501613310565b91505092915050565b7f4368616d704d61726b6574706c6163653a204f6e6c792074686520746f6b656e60008201527f206f776e6572206f7220697473206f70657261746f722061726520616c6c6f7760208201527f656420746f2064657374726f7920612073616c652e0000000000000000000000604082015250565b60006133d4605583612e33565b91506133df82613352565b606082019050919050565b60006020820190508181036000830152613403816133c7565b9050919050565b600060408201905061341f60008301856131ea565b61342c6020830184612b17565b9392505050565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b600061348f602f83612e33565b915061349a82613433565b604082019050919050565b600060208201905081810360008301526134be81613482565b9050919050565b7f4368616d704d61726b6574706c6163653a20456469742073616c65206f66207460008201527f6f6b656e2074686174206973206e6f74206f776e000000000000000000000000602082015250565b6000613521603483612e33565b915061352c826134c5565b604082019050919050565b6000602082019050818103600083015261355081613514565b9050919050565b7f4368616d704d61726b6574706c6163653a204f6e6c792074686520746f6b656e60008201527f206f776e6572206f7220697473206f70657261746f722061726520616c6c6f7760208201527f656420746f206564697420612073616c652e0000000000000000000000000000604082015250565b60006135d9605283612e33565b91506135e482613557565b606082019050919050565b60006020820190508181036000830152613608816135cc565b9050919050565b7f4368616d704d61726b6574706c6163653a2050726963652073686f756c64206260008201527f65207374726963746c7920706f73697469766500000000000000000000000000602082015250565b600061366b603383612e33565b91506136768261360f565b604082019050919050565b6000602082019050818103600083015261369a8161365e565b9050919050565b60006060820190506136b660008301866131ea565b6136c3602083018561291a565b6136d06040830184612b17565b949350505050565b7f4368616d704d61726b6574706c6163653a204372656174652073616c65206f6660008201527f20746f6b656e2074686174206973206e6f74206f776e00000000000000000000602082015250565b6000613734603683612e33565b915061373f826136d8565b604082019050919050565b6000602082019050818103600083015261376381613727565b9050919050565b7f4368616d704d61726b6574706c6163653a204f6e6c792074686520746f6b656e60008201527f206f776e6572206f7220697473206f70657261746f722061726520616c6c6f7760208201527f656420746f2063726561746520612073616c652e000000000000000000000000604082015250565b60006137ec605483612e33565b91506137f78261376a565b606082019050919050565b6000602082019050818103600083015261381b816137df565b9050919050565b7f4368616d704d61726b6574706c6163653a20436f6e74726163742073686f756c60008201527f6420626520617070726f7665642062792074686520746f6b656e206f776e657260208201527f2e00000000000000000000000000000000000000000000000000000000000000604082015250565b60006138a4604183612e33565b91506138af82613822565b606082019050919050565b600060208201905081810360008301526138d381613897565b9050919050565b7f4368616d704d61726b6574706c6163653a2053616c6520616c7265616479206560008201527f78697374732e2044657374726f79207468652070726576696f75732073616c6560208201527f2066697273742e00000000000000000000000000000000000000000000000000604082015250565b600061395c604783612e33565b9150613967826138da565b606082019050919050565b6000602082019050818103600083015261398b8161394f565b9050919050565b7f4368616d704d61726b6574706c6163653a206e4d61726b6574706c616365506560008201527f7263656e74466565732073686f756c6420626520706f73697469766500000000602082015250565b60006139ee603c83612e33565b91506139f982613992565b604082019050919050565b60006020820190508181036000830152613a1d816139e1565b9050919050565b7f4368616d704d61726b6574706c6163653a206e4d61726b6574706c616365506560008201527f7263656e74466565732073686f756c642062652062656c6f7720313030000000602082015250565b6000613a80603d83612e33565b9150613a8b82613a24565b604082019050919050565b60006020820190508181036000830152613aaf81613a73565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b600080fd5b600080fd5b60008083356001602003843603038112613b4057613b3f613b14565b5b80840192508235915067ffffffffffffffff821115613b6257613b61613b19565b5b602083019250600182023603831315613b7e57613b7d613b1e565b5b509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613bc082612654565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613bf357613bf2613b86565b5b600182019050919050565b6000613c0982612654565b9150613c1483612654565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115613c4957613c48613b86565b5b828201905092915050565b7f746f55696e7436345f6f75744f66426f756e6473000000000000000000000000600082015250565b6000613c8a601483612e33565b9150613c9582613c54565b602082019050919050565b60006020820190508181036000830152613cb981613c7d565b9050919050565b7f746f416464726573735f6f75744f66426f756e64730000000000000000000000600082015250565b6000613cf6601583612e33565b9150613d0182613cc0565b602082019050919050565b60006020820190508181036000830152613d2581613ce9565b9050919050565b600081905092915050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b6000613d6d601783613d2c565b9150613d7882613d37565b601782019050919050565b600081519050919050565b6000613d9982613d83565b613da38185613d2c565b9350613db3818560208601612cc2565b80840191505092915050565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b6000613df5601183613d2c565b9150613e0082613dbf565b601182019050919050565b6000613e1682613d60565b9150613e228285613d8e565b9150613e2d82613de8565b9150613e398284613d8e565b91508190509392505050565b6000613e5082613d83565b613e5a8185612e33565b9350613e6a818560208601612cc2565b613e7381612cf5565b840191505092915050565b60006020820190508181036000830152613e988184613e45565b905092915050565b6000613eab82612654565b9150613eb683612654565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613eef57613eee613b86565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000613f3482612654565b9150613f3f83612654565b925082613f4f57613f4e613efa565b5b828204905092915050565b6000613f6582612654565b9150613f7083612654565b925082821015613f8357613f82613b86565b5b828203905092915050565b6000613f9982612654565b91506000821415613fad57613fac613b86565b5b600182039050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b6000613fee602083612e33565b9150613ff982613fb8565b602082019050919050565b6000602082019050818103600083015261401d81613fe1565b9050919050565b7f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60008201527f6e74726163740000000000000000000000000000000000000000000000000000602082015250565b6000614080602683612e33565b915061408b82614024565b604082019050919050565b600060208201905081810360008301526140af81614073565b9050919050565b600081905092915050565b60006140cc82612ca6565b6140d681856140b6565b93506140e6818560208601612cc2565b80840191505092915050565b60006140fe82846140c1565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212208ad442db3045e884dc76f910bcdf1831bc7d403a179765945bd6ac948528394e64736f6c634300080c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ed755dba6ec1eb520076cec051a582a6d81a82530000000000000000000000007f61345bdd61b4192324d612fcecd795ce4b60bd
-----Decoded View---------------
Arg [0] : champTokenAddress (address): 0xED755dBa6Ec1eb520076Cec051a582A6d81A8253
Arg [1] : nfChampAddress (address): 0x7f61345BDd61b4192324d612fcECD795cE4b60bd
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000ed755dba6ec1eb520076cec051a582a6d81a8253
Arg [1] : 0000000000000000000000007f61345bdd61b4192324d612fcecd795ce4b60bd
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.