Overview
ETH Balance
0.0455475 ETH
Eth Value
$168.51 (@ $3,699.56/ETH)More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 380 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw Ethscri... | 21313156 | 35 days ago | IN | 0 ETH | 0.00066171 | ||||
Withdraw Ethscri... | 21252458 | 44 days ago | IN | 0 ETH | 0.00053929 | ||||
Withdraw Ethscri... | 21252457 | 44 days ago | IN | 0 ETH | 0.00053441 | ||||
Withdraw Ethscri... | 20504446 | 148 days ago | IN | 0 ETH | 0.00008062 | ||||
Delist Ethscript... | 19245339 | 324 days ago | IN | 0 ETH | 0.00056896 | ||||
List Ethscriptio... | 19223969 | 327 days ago | IN | 0 ETH | 0.00172901 | ||||
0xaa356477 | 19223965 | 327 days ago | IN | 0 ETH | 0.00104744 | ||||
Withdraw Ethscri... | 19218794 | 328 days ago | IN | 0 ETH | 0.00094148 | ||||
List Ethscriptio... | 19210698 | 329 days ago | IN | 0 ETH | 0.00223704 | ||||
0x2809f113 | 19210696 | 329 days ago | IN | 0 ETH | 0.0013114 | ||||
Delist Ethscript... | 19181236 | 333 days ago | IN | 0 ETH | 0.00131869 | ||||
List Ethscriptio... | 19180964 | 333 days ago | IN | 0 ETH | 0.00364491 | ||||
0x485c8f3d | 19180959 | 333 days ago | IN | 0 ETH | 0.00181213 | ||||
List Ethscriptio... | 19180905 | 333 days ago | IN | 0 ETH | 0.00323334 | ||||
0x9be0146e | 19180903 | 333 days ago | IN | 0 ETH | 0.0017287 | ||||
Buy Ethscription | 19172877 | 334 days ago | IN | 0.0069 ETH | 0.00149388 | ||||
List Ethscriptio... | 19171591 | 334 days ago | IN | 0 ETH | 0.00401505 | ||||
0xaec2eeea | 19171581 | 334 days ago | IN | 0 ETH | 0.00180122 | ||||
Withdraw Ethscri... | 19157949 | 336 days ago | IN | 0 ETH | 0.00063849 | ||||
List Ethscriptio... | 19154022 | 337 days ago | IN | 0 ETH | 0.00202564 | ||||
0xa1e8fd1d | 19154020 | 337 days ago | IN | 0 ETH | 0.00111369 | ||||
Delist Ethscript... | 19139273 | 339 days ago | IN | 0 ETH | 0.00081266 | ||||
List Ethscriptio... | 19139202 | 339 days ago | IN | 0 ETH | 0.00245778 | ||||
0xf33e8e64 | 19139180 | 339 days ago | IN | 0 ETH | 0.00111527 | ||||
List Ethscriptio... | 19133950 | 340 days ago | IN | 0 ETH | 0.00317038 |
Latest 15 internal transactions
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
19172877 | 334 days ago | 0.0067275 ETH | ||||
19131159 | 340 days ago | 0.273 ETH | ||||
19102699 | 344 days ago | 0.067275 ETH | ||||
19094080 | 345 days ago | 0.032175 ETH | ||||
19031391 | 354 days ago | 0.24375 ETH | ||||
18994783 | 359 days ago | 0.119925 ETH | ||||
18988540 | 360 days ago | 0.24375 ETH | ||||
18988406 | 360 days ago | 0.14625 ETH | ||||
18981651 | 361 days ago | 0.234 ETH | ||||
18981478 | 361 days ago | 0.0975 ETH | ||||
18981381 | 361 days ago | 0.0975 ETH | ||||
18981362 | 361 days ago | 0.067275 ETH | ||||
18980848 | 361 days ago | 0.0975 ETH | ||||
18980781 | 361 days ago | 0.000975 ETH | ||||
18975334 | 362 days ago | 0.04875 ETH |
Loading...
Loading
Contract Name:
MemeScribeMarket
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
No with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.8.17; import "@solidstate/contracts/security/reentrancy_guard/ReentrancyGuard.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "solady/src/utils/SafeTransferLib.sol"; import "solady/src/utils/ECDSA.sol"; import "solady/src/utils/ERC1967FactoryConstants.sol"; import "./EthscriptionsEscrower.sol"; contract MemeScribeMarket is ReentrancyGuard, EthscriptionsEscrower, Ownable { using SafeTransferLib for address; using ECDSA for bytes32; constructor() Ownable(msg.sender) { // Your constructor logic here } uint public fee = 250; // 2.5% uint public constant FEE_DENOMINATOR = 10000; uint public feesAccumulated = 0; struct Listing { bool isForSale; bytes32 ethscriptionId; address seller; uint price; } mapping(bytes32 => Listing) public ethscriptionsOfferedForSale; event EthscriptionListed( bytes32 indexed ethscriptionId, uint price, address indexed seller ); event EthscriptionDelisted( bytes32 indexed ethscriptionId, address indexed seller ); event EthscriptionPurchased( bytes32 indexed ethscriptionId, uint price, address indexed seller, address indexed buyer ); function listEthscription( bytes32 ethscriptionId, uint price ) external nonReentrant { _listEthscription(ethscriptionId, price); } function _listEthscription(bytes32 ethscriptionId, uint price) internal { require( !userEthscriptionDefinitelyNotStored(msg.sender, ethscriptionId), "Sender is not depositor" ); ethscriptionsOfferedForSale[ethscriptionId] = Listing({ isForSale: true, ethscriptionId: ethscriptionId, seller: msg.sender, price: price }); emit EthscriptionListed(ethscriptionId, price, msg.sender); } function delistEthscription(bytes32 ethscriptionId) public nonReentrant { require( !userEthscriptionDefinitelyNotStored(msg.sender, ethscriptionId), "Sender is not depositor" ); ethscriptionsOfferedForSale[ethscriptionId] = Listing( false, ethscriptionId, msg.sender, 0 ); emit EthscriptionDelisted(ethscriptionId, msg.sender); } function batchListEthscriptions( bytes32[] memory ethscriptionIds, uint[] memory prices ) external nonReentrant { require( ethscriptionIds.length == prices.length, "Array lengths do not match" ); for (uint i = 0; i < ethscriptionIds.length; i++) { _listEthscription(ethscriptionIds[i], prices[i]); } } function buyEthscription( bytes32 ethscriptionId, uint price ) public payable nonReentrant { _buyEthscription(ethscriptionId, price); } function _buyEthscription(bytes32 ethscriptionId, uint price) internal { Listing memory listing = ethscriptionsOfferedForSale[ethscriptionId]; if (!listing.isForSale) revert("Ethscription is not for sale"); if (msg.value != listing.price) revert("Not enough ether"); address seller = listing.seller; if (seller == msg.sender) revert("Seller is buyer"); ethscriptionsOfferedForSale[ethscriptionId] = Listing( false, ethscriptionId, msg.sender, 0 ); _transferEthscription(seller, msg.sender, ethscriptionId); // send ether to seller uint feeAmount = (listing.price * fee) / FEE_DENOMINATOR; uint amountToSendtoSeller = listing.price - feeAmount; feesAccumulated += feeAmount; payable(seller).transfer(amountToSendtoSeller); emit EthscriptionPurchased( ethscriptionId, listing.price, seller, msg.sender ); } function batchBuyEthscription( bytes32[] calldata ethscriptionIds, uint[] calldata prices ) external payable nonReentrant { require( ethscriptionIds.length == prices.length, "Array lengths do not match" ); uint totalSalePrice = 0; for (uint i = 0; i < ethscriptionIds.length; i++) { _buyEthscription(ethscriptionIds[i], prices[i]); totalSalePrice += prices[i]; } require(msg.value == totalSalePrice, "Incorrect total Ether sent"); } function withdrawEthscription(bytes32 ethscriptionId) public override { require( !userEthscriptionDefinitelyNotStored(msg.sender, ethscriptionId), "Sender is not depositor" ); // Withdraw ethscription super.withdrawEthscription(ethscriptionId); Listing memory listing = ethscriptionsOfferedForSale[ethscriptionId]; // Check that the offer is valid if (listing.isForSale) { // Invalidate listing _invalidateListing(ethscriptionId); } } function _invalidateListing(bytes32 ethscriptionId) internal { ethscriptionsOfferedForSale[ethscriptionId] = Listing( false, ethscriptionId, msg.sender, 0 ); emit EthscriptionDelisted(ethscriptionId, msg.sender); } // Owner functions function setMarketPlaceFee(uint updatedFee) public onlyOwner { fee = updatedFee; } function withdrawFees() public onlyOwner { uint amount = feesAccumulated; feesAccumulated = 0; payable(msg.sender).transfer(amount); } function transferContractOwner(address newOwner) public onlyOwner { transferOwnership(newOwner); } // Overrides function _onPotentialEthscriptionDeposit( address previousOwner, bytes memory userCallData ) internal virtual override { require(userCallData.length % 32 == 0, "InvalidEthscriptionLength"); // Process each ethscriptionId for (uint256 i = 0; i < userCallData.length / 32; i++) { bytes32 potentialEthscriptionId = abi.decode( slice(userCallData, i * 32, 32), (bytes32) ); if ( userEthscriptionPossiblyStored( previousOwner, potentialEthscriptionId ) ) { revert EthscriptionAlreadyReceivedFromSender(); } EthscriptionsEscrowerStorage.s().ethscriptionReceivedOnBlockNumber[ previousOwner ][potentialEthscriptionId] = block.number; } } // Utils function slice( bytes memory data, uint256 start, uint256 len ) internal pure returns (bytes memory) { bytes memory b = new bytes(len); for (uint256 i = 0; i < len; i++) { b[i] = data[i + start]; } return b; } fallback() external { _onPotentialEthscriptionDeposit(msg.sender, msg.data); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC20Internal } from './IERC20Internal.sol'; /** * @title ERC20 interface * @dev see https://eips.ethereum.org/EIPS/eip-20 */ interface IERC20 is IERC20Internal { /** * @notice query the total minted token supply * @return token supply */ function totalSupply() external view returns (uint256); /** * @notice query the token balance of given account * @param account address to query * @return token balance */ function balanceOf(address account) external view returns (uint256); /** * @notice query the allowance granted from given holder to given spender * @param holder approver of allowance * @param spender recipient of allowance * @return token allowance */ function allowance( address holder, address spender ) external view returns (uint256); /** * @notice grant approval to spender to spend tokens * @dev prefer ERC20Extended functions to avoid transaction-ordering vulnerability (see https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729) * @param spender recipient of allowance * @param amount quantity of tokens approved for spending * @return success status (always true; otherwise function should revert) */ function approve(address spender, uint256 amount) external returns (bool); /** * @notice transfer tokens to given recipient * @param recipient beneficiary of token transfer * @param amount quantity of tokens to transfer * @return success status (always true; otherwise function should revert) */ function transfer( address recipient, uint256 amount ) external returns (bool); /** * @notice transfer tokens to given recipient on behalf of given holder * @param holder holder of tokens prior to transfer * @param recipient beneficiary of token transfer * @param amount quantity of tokens to transfer * @return success status (always true; otherwise function should revert) */ function transferFrom( address holder, address recipient, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; /** * @title Partial ERC20 interface needed by internal functions */ interface IERC20Internal { event Transfer(address indexed from, address indexed to, uint256 value); event Approval( address indexed owner, address indexed spender, uint256 value ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IReentrancyGuard { error ReentrancyGuard__ReentrantCall(); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IReentrancyGuard } from './IReentrancyGuard.sol'; import { ReentrancyGuardStorage } from './ReentrancyGuardStorage.sol'; /** * @title Utility contract for preventing reentrancy attacks */ abstract contract ReentrancyGuard is IReentrancyGuard { uint256 internal constant REENTRANCY_STATUS_LOCKED = 2; uint256 internal constant REENTRANCY_STATUS_UNLOCKED = 1; modifier nonReentrant() virtual { if (_isReentrancyGuardLocked()) revert ReentrancyGuard__ReentrantCall(); _lockReentrancyGuard(); _; _unlockReentrancyGuard(); } /** * @notice returns true if the reentrancy guard is locked, false otherwise */ function _isReentrancyGuardLocked() internal view virtual returns (bool) { return ReentrancyGuardStorage.layout().status == REENTRANCY_STATUS_LOCKED; } /** * @notice lock functions that use the nonReentrant modifier */ function _lockReentrancyGuard() internal virtual { ReentrancyGuardStorage.layout().status = REENTRANCY_STATUS_LOCKED; } /** * @notice unlock functions that use the nonReentrant modifier */ function _unlockReentrancyGuard() internal virtual { ReentrancyGuardStorage.layout().status = REENTRANCY_STATUS_UNLOCKED; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; library ReentrancyGuardStorage { struct Layout { uint256 status; } bytes32 internal constant STORAGE_SLOT = keccak256('solidstate.contracts.storage.ReentrancyGuard'); function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC20 } from '../../../interfaces/IERC20.sol'; import { IERC20Base } from './IERC20Base.sol'; import { ERC20BaseInternal } from './ERC20BaseInternal.sol'; import { ERC20BaseStorage } from './ERC20BaseStorage.sol'; /** * @title Base ERC20 implementation, excluding optional extensions */ abstract contract ERC20Base is IERC20Base, ERC20BaseInternal { /** * @inheritdoc IERC20 */ function totalSupply() external view returns (uint256) { return _totalSupply(); } /** * @inheritdoc IERC20 */ function balanceOf(address account) external view returns (uint256) { return _balanceOf(account); } /** * @inheritdoc IERC20 */ function allowance( address holder, address spender ) external view returns (uint256) { return _allowance(holder, spender); } /** * @inheritdoc IERC20 */ function approve(address spender, uint256 amount) external returns (bool) { return _approve(msg.sender, spender, amount); } /** * @inheritdoc IERC20 */ function transfer( address recipient, uint256 amount ) external returns (bool) { return _transfer(msg.sender, recipient, amount); } /** * @inheritdoc IERC20 */ function transferFrom( address holder, address recipient, uint256 amount ) external returns (bool) { return _transferFrom(holder, recipient, amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC20BaseInternal } from './IERC20BaseInternal.sol'; import { ERC20BaseStorage } from './ERC20BaseStorage.sol'; /** * @title Base ERC20 internal functions, excluding optional extensions */ abstract contract ERC20BaseInternal is IERC20BaseInternal { /** * @notice query the total minted token supply * @return token supply */ function _totalSupply() internal view virtual returns (uint256) { return ERC20BaseStorage.layout().totalSupply; } /** * @notice query the token balance of given account * @param account address to query * @return token balance */ function _balanceOf( address account ) internal view virtual returns (uint256) { return ERC20BaseStorage.layout().balances[account]; } /** * @notice query the allowance granted from given holder to given spender * @param holder approver of allowance * @param spender recipient of allowance * @return token allowance */ function _allowance( address holder, address spender ) internal view virtual returns (uint256) { return ERC20BaseStorage.layout().allowances[holder][spender]; } /** * @notice enable spender to spend tokens on behalf of holder * @param holder address on whose behalf tokens may be spent * @param spender recipient of allowance * @param amount quantity of tokens approved for spending * @return success status (always true; otherwise function should revert) */ function _approve( address holder, address spender, uint256 amount ) internal virtual returns (bool) { if (holder == address(0)) revert ERC20Base__ApproveFromZeroAddress(); if (spender == address(0)) revert ERC20Base__ApproveToZeroAddress(); ERC20BaseStorage.layout().allowances[holder][spender] = amount; emit Approval(holder, spender, amount); return true; } /** * @notice decrease spend amount granted by holder to spender * @param holder address on whose behalf tokens may be spent * @param spender address whose allowance to decrease * @param amount quantity by which to decrease allowance */ function _decreaseAllowance( address holder, address spender, uint256 amount ) internal { uint256 allowance = _allowance(holder, spender); if (amount > allowance) revert ERC20Base__InsufficientAllowance(); unchecked { _approve(holder, spender, allowance - amount); } } /** * @notice mint tokens for given account * @param account recipient of minted tokens * @param amount quantity of tokens minted */ function _mint(address account, uint256 amount) internal virtual { if (account == address(0)) revert ERC20Base__MintToZeroAddress(); _beforeTokenTransfer(address(0), account, amount); ERC20BaseStorage.Layout storage l = ERC20BaseStorage.layout(); l.totalSupply += amount; l.balances[account] += amount; emit Transfer(address(0), account, amount); } /** * @notice burn tokens held by given account * @param account holder of burned tokens * @param amount quantity of tokens burned */ function _burn(address account, uint256 amount) internal virtual { if (account == address(0)) revert ERC20Base__BurnFromZeroAddress(); _beforeTokenTransfer(account, address(0), amount); ERC20BaseStorage.Layout storage l = ERC20BaseStorage.layout(); uint256 balance = l.balances[account]; if (amount > balance) revert ERC20Base__BurnExceedsBalance(); unchecked { l.balances[account] = balance - amount; } l.totalSupply -= amount; emit Transfer(account, address(0), amount); } /** * @notice transfer tokens from holder to recipient * @param holder owner of tokens to be transferred * @param recipient beneficiary of transfer * @param amount quantity of tokens transferred * @return success status (always true; otherwise function should revert) */ function _transfer( address holder, address recipient, uint256 amount ) internal virtual returns (bool) { if (holder == address(0)) revert ERC20Base__TransferFromZeroAddress(); if (recipient == address(0)) revert ERC20Base__TransferToZeroAddress(); _beforeTokenTransfer(holder, recipient, amount); ERC20BaseStorage.Layout storage l = ERC20BaseStorage.layout(); uint256 holderBalance = l.balances[holder]; if (amount > holderBalance) revert ERC20Base__TransferExceedsBalance(); unchecked { l.balances[holder] = holderBalance - amount; } l.balances[recipient] += amount; emit Transfer(holder, recipient, amount); return true; } /** * @notice transfer tokens to given recipient on behalf of given holder * @param holder holder of tokens prior to transfer * @param recipient beneficiary of token transfer * @param amount quantity of tokens to transfer * @return success status (always true; otherwise function should revert) */ function _transferFrom( address holder, address recipient, uint256 amount ) internal virtual returns (bool) { _decreaseAllowance(holder, msg.sender, amount); _transfer(holder, recipient, amount); return true; } /** * @notice ERC20 hook, called before all transfers including mint and burn * @dev function should be overridden and new implementation must call super * @param from sender of tokens * @param to receiver of tokens * @param amount quantity of tokens transferred */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; library ERC20BaseStorage { struct Layout { mapping(address => uint256) balances; mapping(address => mapping(address => uint256)) allowances; uint256 totalSupply; } bytes32 internal constant STORAGE_SLOT = keccak256('solidstate.contracts.storage.ERC20Base'); function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC20 } from '../../../interfaces/IERC20.sol'; import { IERC20BaseInternal } from './IERC20BaseInternal.sol'; /** * @title ERC20 base interface */ interface IERC20Base is IERC20BaseInternal, IERC20 { }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC20Internal } from '../../../interfaces/IERC20Internal.sol'; /** * @title ERC20 base interface */ interface IERC20BaseInternal is IERC20Internal { error ERC20Base__ApproveFromZeroAddress(); error ERC20Base__ApproveToZeroAddress(); error ERC20Base__BurnExceedsBalance(); error ERC20Base__BurnFromZeroAddress(); error ERC20Base__InsufficientAllowance(); error ERC20Base__MintToZeroAddress(); error ERC20Base__TransferExceedsBalance(); error ERC20Base__TransferFromZeroAddress(); error ERC20Base__TransferToZeroAddress(); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.20; import "@solidstate/contracts/token/ERC20/base/ERC20Base.sol"; library EthscriptionsEscrowerStorage { struct Layout { mapping(address => mapping(bytes32 => uint256)) ethscriptionReceivedOnBlockNumber; } bytes32 internal constant STORAGE_SLOT = keccak256( "ethscriptions.contracts.storage.EthscriptionsEscrowerStorage" ); function s() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } } contract EthscriptionsEscrower { error EthscriptionNotDeposited(); error EthscriptionAlreadyReceivedFromSender(); error InvalidEthscriptionLength(); error AdditionalCooldownRequired(uint256 additionalBlocksNeeded); event ethscriptions_protocol_TransferEthscriptionForPreviousOwner( address indexed previousOwner, address indexed recipient, bytes32 indexed id ); event PotentialEthscriptionDeposited( address indexed owner, bytes32 indexed potentialEthscriptionId ); event PotentialEthscriptionWithdrawn( address indexed owner, bytes32 indexed potentialEthscriptionId ); uint256 public constant ETHSCRIPTION_TRANSFER_COOLDOWN_BLOCKS = 5; function _transferEthscription( address previousOwner, address to, bytes32 ethscriptionId ) internal virtual { _validateTransferEthscription(previousOwner, to, ethscriptionId); emit ethscriptions_protocol_TransferEthscriptionForPreviousOwner( previousOwner, to, ethscriptionId ); _afterTransferEthscription(previousOwner, to, ethscriptionId); } function withdrawEthscription(bytes32 ethscriptionId) public virtual { _transferEthscription(msg.sender, msg.sender, ethscriptionId); emit PotentialEthscriptionWithdrawn(msg.sender, ethscriptionId); } function _onPotentialEthscriptionDeposit( address previousOwner, bytes memory userCalldata ) internal virtual { if (userCalldata.length != 32) revert InvalidEthscriptionLength(); bytes32 potentialEthscriptionId = abi.decode(userCalldata, (bytes32)); if ( userEthscriptionPossiblyStored( previousOwner, potentialEthscriptionId ) ) { revert EthscriptionAlreadyReceivedFromSender(); } EthscriptionsEscrowerStorage.s().ethscriptionReceivedOnBlockNumber[ previousOwner ][potentialEthscriptionId] = block.number; emit PotentialEthscriptionDeposited( previousOwner, potentialEthscriptionId ); } function _validateTransferEthscription( address previousOwner, address to, bytes32 ethscriptionId ) internal view virtual { if ( userEthscriptionDefinitelyNotStored(previousOwner, ethscriptionId) ) { revert EthscriptionNotDeposited(); } uint256 blocksRemaining = blocksRemainingUntilValidTransfer( previousOwner, ethscriptionId ); if (blocksRemaining != 0) { revert AdditionalCooldownRequired(blocksRemaining); } } function _afterTransferEthscription( address previousOwner, address to, bytes32 ethscriptionId ) internal virtual { delete EthscriptionsEscrowerStorage .s() .ethscriptionReceivedOnBlockNumber[previousOwner][ethscriptionId]; } function blocksRemainingUntilValidTransfer( address previousOwner, bytes32 ethscriptionId ) public view virtual returns (uint256) { uint256 receivedBlockNumber = EthscriptionsEscrowerStorage .s() .ethscriptionReceivedOnBlockNumber[previousOwner][ethscriptionId]; if (receivedBlockNumber == 0) { revert EthscriptionNotDeposited(); } uint256 blocksPassed = block.number - receivedBlockNumber; return blocksPassed < ETHSCRIPTION_TRANSFER_COOLDOWN_BLOCKS ? ETHSCRIPTION_TRANSFER_COOLDOWN_BLOCKS - blocksPassed : 0; } function userEthscriptionDefinitelyNotStored( address owner, bytes32 ethscriptionId ) public view virtual returns (bool) { return EthscriptionsEscrowerStorage.s().ethscriptionReceivedOnBlockNumber[ owner ][ethscriptionId] == 0; } function userEthscriptionPossiblyStored( address owner, bytes32 ethscriptionId ) public view virtual returns (bool) { return !userEthscriptionDefinitelyNotStored(owner, ethscriptionId); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Gas optimized ECDSA wrapper. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol) /// /// @dev Note: /// - The recovery functions use the ecrecover precompile (0x1). /// /// WARNING! Do NOT use signatures as unique identifiers. /// Please use EIP712 with a nonce included in the digest to prevent replay attacks. /// This implementation does NOT check if a signature is non-malleable. library ECDSA { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The signature is invalid. error InvalidSignature(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* RECOVERY OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // Note: as of Solady version 0.0.68, these functions will // revert upon recovery failure for more safety by default. /// @dev Recovers the signer's address from a message digest `hash`, /// and the `signature`. /// /// This function does NOT accept EIP-2098 short form signatures. /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098 /// short form signatures instead. function recover(bytes32 hash, bytes memory signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. let signatureLength := mload(signature) mstore(0x00, hash) mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`. mstore(0x40, mload(add(signature, 0x20))) // `r`. mstore(0x60, mload(add(signature, 0x40))) // `s`. result := mload( staticcall( gas(), // Amount of gas left for the transaction. eq(signatureLength, 65), // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the `signature`. /// /// This function does NOT accept EIP-2098 short form signatures. /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098 /// short form signatures instead. function recoverCalldata(bytes32 hash, bytes calldata signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`. calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`. result := mload( staticcall( gas(), // Amount of gas left for the transaction. eq(signature.length, 65), // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the EIP-2098 short form signature defined by `r` and `vs`. /// /// This function only accepts EIP-2098 short form signatures. /// See: https://eips.ethereum.org/EIPS/eip-2098 function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, r) mstore(0x60, shr(1, shl(1, vs))) // `s`. result := mload( staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the signature defined by `v`, `r`, `s`. function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, and(v, 0xff)) mstore(0x40, r) mstore(0x60, s) result := mload( staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* TRY-RECOVER OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // WARNING! // These functions will NOT revert upon recovery failure. // Instead, they will return the zero address upon recovery failure. // It is critical that the returned address is NEVER compared against // a zero address (e.g. an uninitialized address variable). /// @dev Recovers the signer's address from a message digest `hash`, /// and the `signature`. /// /// This function does NOT accept EIP-2098 short form signatures. /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098 /// short form signatures instead. function tryRecover(bytes32 hash, bytes memory signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. let signatureLength := mload(signature) mstore(0x00, hash) mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`. mstore(0x40, mload(add(signature, 0x20))) // `r`. mstore(0x60, mload(add(signature, 0x40))) // `s`. pop( staticcall( gas(), // Amount of gas left for the transaction. eq(signatureLength, 65), // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the `signature`. /// /// This function does NOT accept EIP-2098 short form signatures. /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098 /// short form signatures instead. function tryRecoverCalldata(bytes32 hash, bytes calldata signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`. calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`. pop( staticcall( gas(), // Amount of gas left for the transaction. eq(signature.length, 65), // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the EIP-2098 short form signature defined by `r` and `vs`. /// /// This function only accepts EIP-2098 short form signatures. /// See: https://eips.ethereum.org/EIPS/eip-2098 function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, r) mstore(0x60, shr(1, shl(1, vs))) // `s`. pop( staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the signature defined by `v`, `r`, `s`. function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, and(v, 0xff)) mstore(0x40, r) mstore(0x60, s) pop( staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HASHING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an Ethereum Signed Message, created from a `hash`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, hash) // Store into scratch space for keccak256. mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes. result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`. } } /// @dev Returns an Ethereum Signed Message, created from `s`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. /// Note: Supports lengths of `s` up to 999999 bytes. function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { let sLength := mload(s) let o := 0x20 mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded. mstore(0x00, 0x00) // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`. for { let temp := sLength } 1 {} { o := sub(o, 1) mstore8(o, add(48, mod(temp, 10))) temp := div(temp, 10) if iszero(temp) { break } } let n := sub(0x3a, o) // Header length: `26 + 32 - o`. // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes. returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20)) mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header. result := keccak256(add(s, sub(0x20, n)), add(n, sLength)) mstore(s, sLength) // Restore the length. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EMPTY CALLDATA HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an empty calldata bytes. function emptySignature() internal pure returns (bytes calldata signature) { /// @solidity memory-safe-assembly assembly { signature.length := 0 } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice The address and bytecode of the canonical ERC1967Factory deployment. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ERC1967FactoryLib.sol) /// @author jtriley-eth (https://github.com/jtriley-eth/minimum-viable-proxy) /// /// @dev The canonical ERC1967Factory is deployed permissionlessly via /// 0age's ImmutableCreate2Factory located at 0x0000000000FFe8B47B3e2130213B802212439497. /// /// `ADDRESS = immutableCreate2Factory.safeCreate2(SALT, INITCODE)` /// /// If the canonical ERC1967Factory has not been deployed on your EVM chain of choice, /// please feel free to deploy via 0age's ImmutableCreate2Factory. /// /// If 0age's ImmutableCreate2Factory has not been deployed on your EVM chain of choice, /// please refer to 0age's ImmutableCreate2Factory deployment instructions at: /// https://github.com/ProjectOpenSea/seaport/blob/main/docs/Deployment.md /// /// Contract verification: /// - Source code: /// https://github.com/Vectorized/solady/blob/5212e50fef1f2ff1b1b5e03a5d276a0d23c02713/src/utils/ERC1967Factory.sol /// (The EXACT source code is required. Use the file at the commit instead of the latest copy.) /// - Optimization Enabled: Yes with 1000000 runs /// - Compiler Version: v0.8.19+commit.7dd6d404 /// - Other Settings: default evmVersion, MIT license library ERC1967FactoryConstants { /// @dev The canonical ERC1967Factory address for EVM chains. address internal constant ADDRESS = 0x0000000000006396FF2a80c067f99B3d2Ab4Df24; /// @dev The canonical ERC1967Factory bytecode for EVM chains. /// Useful for forge tests: /// `vm.etch(ADDRESS, BYTECODE)`. bytes internal constant BYTECODE = hex"6080604052600436106100b15760003560e01c8063545e7c611161006957806399a88ec41161004e57806399a88ec41461019d578063a97b90d5146101b0578063db4c545e146101c357600080fd5b8063545e7c61146101775780639623609d1461018a57600080fd5b80633729f9221161009a5780633729f922146101315780634314f120146101445780635414dff01461015757600080fd5b80631acfd02a146100b65780632abbef15146100d8575b600080fd5b3480156100c257600080fd5b506100d66100d1366004610604565b6101e6565b005b3480156100e457600080fd5b506101076100f3366004610637565b30600c908152600091909152602090205490565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61010761013f366004610652565b610237565b6101076101523660046106d7565b61024e565b34801561016357600080fd5b50610107610172366004610738565b610267565b610107610185366004610604565b61029a565b6100d66101983660046106d7565b6102af565b6100d66101ab366004610604565b61035f565b6101076101be366004610751565b610370565b3480156101cf57600080fd5b506101d86103a9565b604051908152602001610128565b30600c52816000526020600c2033815414610209576382b429006000526004601cfd5b81905580827f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f600080a35050565b60006102468484843685610370565b949350505050565b600061025e8585838087876103c2565b95945050505050565b6000806102726103a9565b905060ff600053806035523060601b6001528260155260556000209150600060355250919050565b60006102a88383368461024e565b9392505050565b30600c5283600052336020600c2054146102d1576382b429006000526004601cfd5b6040518381527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc602082015281836040830137600080836040018334895af1610331573d610327576355299b496000526004601cfd5b3d6000803e3d6000fd5b5082847f5d611f318680d00598bb735d61bacf0c514c6b50e1e5ad30040a4df2b12791c7600080a350505050565b61036c82823660006102af565b5050565b60008360601c33148460601c151761039057632f6348366000526004601cfd5b61039f868686600187876103c2565b9695505050505050565b6000806103b461049c565b608960139091012092915050565b6000806103cd61049c565b90508480156103e757866089601384016000f592506103f3565b6089601383016000f092505b50816104075763301164256000526004601cfd5b8781527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc602082015282846040830137600080846040018334865af161045a573d6103275763301164256000526004601cfd5b30600c5281600052866020600c20558688837fc95935a66d15e0da5e412aca0ad27ae891d20b2fb91cf3994b6a3bf2b8178082600080a4509695505050505050565b6040513060701c801561054257666052573d6000fd607b8301527f3d356020355560408036111560525736038060403d373d3d355af43d6000803e60748301527f3735a920a3ca505d382bbc545af43d6000803e6052573d6000fd5b3d6000f35b60548301527f14605757363d3d37363d7f360894a13ba1a3210667c828492db98dca3e2076cc60348301523060148301526c607f3d8160093d39f33d3d337382525090565b66604c573d6000fd60758301527f3d3560203555604080361115604c5736038060403d373d3d355af43d6000803e606e8301527f3735a920a3ca505d382bbc545af43d6000803e604c573d6000fd5b3d6000f35b604e8301527f14605157363d3d37363d7f360894a13ba1a3210667c828492db98dca3e2076cc602e83015230600e8301526c60793d8160093d39f33d3d336d82525090565b803573ffffffffffffffffffffffffffffffffffffffff811681146105ff57600080fd5b919050565b6000806040838503121561061757600080fd5b610620836105db565b915061062e602084016105db565b90509250929050565b60006020828403121561064957600080fd5b6102a8826105db565b60008060006060848603121561066757600080fd5b610670846105db565b925061067e602085016105db565b9150604084013590509250925092565b60008083601f8401126106a057600080fd5b50813567ffffffffffffffff8111156106b857600080fd5b6020830191508360208285010111156106d057600080fd5b9250929050565b600080600080606085870312156106ed57600080fd5b6106f6856105db565b9350610704602086016105db565b9250604085013567ffffffffffffffff81111561072057600080fd5b61072c8782880161068e565b95989497509550505050565b60006020828403121561074a57600080fd5b5035919050565b60008060008060006080868803121561076957600080fd5b610772866105db565b9450610780602087016105db565b935060408601359250606086013567ffffffffffffffff8111156107a357600080fd5b6107af8882890161068e565b96999598509396509294939250505056fea26469706673582212200ac7c3ccbc2d311c48bf5465b021542e0e306fe3c462c060ba6a3d2f81ff6c5f64736f6c63430008130033"; /// @dev The initcode used to deploy the canonical ERC1967Factory. bytes internal constant INITCODE = abi.encodePacked( hex"608060405234801561001057600080fd5b506107f6806100206000396000f3fe", BYTECODE ); /// @dev For deterministic deployment via 0age's ImmutableCreate2Factory. bytes32 internal constant SALT = 0x0000000000000000000000000000000000000000e75e4f228818c80007508f33; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// /// @dev Note: /// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection. /// - For ERC20s, this implementation won't check that a token has code, /// responsibility is delegated to the caller. library SafeTransferLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ETH transfer has failed. error ETHTransferFailed(); /// @dev The ERC20 `transferFrom` has failed. error TransferFromFailed(); /// @dev The ERC20 `transfer` has failed. error TransferFailed(); /// @dev The ERC20 `approve` has failed. error ApproveFailed(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes. uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300; /// @dev Suggested gas stipend for contract receiving ETH to perform a few /// storage reads and writes, but low enough to prevent griefing. uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ETH OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants. // // The regular variants: // - Forwards all remaining gas to the target. // - Reverts if the target reverts. // - Reverts if the current contract has insufficient balance. // // The force variants: // - Forwards with an optional gas stipend // (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases). // - If the target reverts, or if the gas stipend is exhausted, // creates a temporary contract to force send the ETH via `SELFDESTRUCT`. // Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758. // - Reverts if the current contract has insufficient balance. // // The try variants: // - Forwards with a mandatory gas stipend. // - Instead of reverting, returns whether the transfer succeeded. /// @dev Sends `amount` (in wei) ETH to `to`. function safeTransferETH(address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } } } /// @dev Sends all the ETH in the current contract to `to`. function safeTransferAllETH(address to) internal { /// @solidity memory-safe-assembly assembly { // Transfer all the ETH and check if it succeeded or not. if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`. function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal { /// @solidity memory-safe-assembly assembly { if lt(selfbalance(), amount) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`. function forceSafeTransferAllETH(address to, uint256 gasStipend) internal { /// @solidity memory-safe-assembly assembly { if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`. function forceSafeTransferETH(address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { if lt(selfbalance(), amount) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`. function forceSafeTransferAllETH(address to) internal { /// @solidity memory-safe-assembly assembly { // forgefmt: disable-next-item if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`. function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00) } } /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`. function trySafeTransferAllETH(address to, uint256 gasStipend) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sends `amount` of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have at least `amount` approved for /// the current contract to manage. function safeTransferFrom(address token, address from, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x60, amount) // Store the `amount` argument. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends all of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have their entire balance approved for /// the current contract to manage. function safeTransferAllFrom(address token, address from, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`. // Read the balance, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`. amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransfer(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Sends all of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransferAll(address token, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`. mstore(0x20, address()) // Store the address of the current contract. // Read the balance, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20) ) ) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } mstore(0x14, to) // Store the `to` argument. amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it. mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// Reverts upon failure. function safeApprove(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. // Perform the approval, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`. revert(0x1c, 0x04) } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// If the initial attempt to approve fails, attempts to reset the approved amount to zero, /// then retries the approval again (some tokens, e.g. USDT, requires this). /// Reverts upon failure. function safeApproveWithRetry(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. // Perform the approval, retrying upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x34, 0) // Store 0 for the `amount`. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. pop(call(gas(), token, 0, 0x10, 0x44, 0x00, 0x00)) // Reset the approval. mstore(0x34, amount) // Store back the original `amount`. // Retry the approval, reverting upon failure. if iszero( and( or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`. revert(0x1c, 0x04) } } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Returns the amount of ERC20 `token` owned by `account`. /// Returns zero if the `token` does not exist. function balanceOf(address token, address account) internal view returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x14, account) // Store the `account` argument. mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`. amount := mul( mload(0x20), and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20) ) ) } } }
{ "evmVersion": "paris", "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"additionalBlocksNeeded","type":"uint256"}],"name":"AdditionalCooldownRequired","type":"error"},{"inputs":[],"name":"EthscriptionAlreadyReceivedFromSender","type":"error"},{"inputs":[],"name":"EthscriptionNotDeposited","type":"error"},{"inputs":[],"name":"InvalidEthscriptionLength","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuard__ReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"ethscriptionId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"seller","type":"address"}],"name":"EthscriptionDelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"ethscriptionId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":true,"internalType":"address","name":"seller","type":"address"}],"name":"EthscriptionListed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"ethscriptionId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"address","name":"buyer","type":"address"}],"name":"EthscriptionPurchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"bytes32","name":"potentialEthscriptionId","type":"bytes32"}],"name":"PotentialEthscriptionDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"bytes32","name":"potentialEthscriptionId","type":"bytes32"}],"name":"PotentialEthscriptionWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"ethscriptions_protocol_TransferEthscriptionForPreviousOwner","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"ETHSCRIPTION_TRANSFER_COOLDOWN_BLOCKS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"ethscriptionIds","type":"bytes32[]"},{"internalType":"uint256[]","name":"prices","type":"uint256[]"}],"name":"batchBuyEthscription","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"ethscriptionIds","type":"bytes32[]"},{"internalType":"uint256[]","name":"prices","type":"uint256[]"}],"name":"batchListEthscriptions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"previousOwner","type":"address"},{"internalType":"bytes32","name":"ethscriptionId","type":"bytes32"}],"name":"blocksRemainingUntilValidTransfer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"ethscriptionId","type":"bytes32"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"buyEthscription","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"ethscriptionId","type":"bytes32"}],"name":"delistEthscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"ethscriptionsOfferedForSale","outputs":[{"internalType":"bool","name":"isForSale","type":"bool"},{"internalType":"bytes32","name":"ethscriptionId","type":"bytes32"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"uint256","name":"price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feesAccumulated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"ethscriptionId","type":"bytes32"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"listEthscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"updatedFee","type":"uint256"}],"name":"setMarketPlaceFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferContractOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"ethscriptionId","type":"bytes32"}],"name":"userEthscriptionDefinitelyNotStored","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes32","name":"ethscriptionId","type":"bytes32"}],"name":"userEthscriptionPossiblyStored","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"ethscriptionId","type":"bytes32"}],"name":"withdrawEthscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawFees","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405260fa60015560006002553480156200001b57600080fd5b5033600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000925760006040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620000899190620001b3565b60405180910390fd5b620000a381620000aa60201b60201c565b50620001d0565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200019b826200016e565b9050919050565b620001ad816200018e565b82525050565b6000602082019050620001ca6000830184620001a2565b92915050565b61257f80620001e06000396000f3fe6080604052600436106101235760003560e01c80638da5cb5b116100a0578063d73792a911610064578063d73792a9146103f0578063ddca3f431461041b578063e7b59bf314610446578063e9bf95a21461046f578063f2fde38b146104ac57610124565b80638da5cb5b1461030b578063aa3bf60e14610336578063c20925c914610373578063c465e49f1461039c578063ccad70f1146103c757610124565b80635db74d20116100e75780635db74d2014610246578063642b31da14610286578063715018a6146102a25780637229e670146102b9578063892d15da146102e257610124565b806318349111146101825780633ddf97f1146101ad578063476343ee146101c95780634f868776146101e05780635cad65a11461020957610124565b5b34801561013057600080fd5b50610180336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506104d5565b005b34801561018e57600080fd5b50610197610624565b6040516101a491906119b1565b60405180910390f35b6101c760048036038101906101c29190611a9b565b61062a565b005b3480156101d557600080fd5b506101de610790565b005b3480156101ec57600080fd5b5061020760048036038101906102029190611b7e565b6107f1565b005b34801561021557600080fd5b50610230600480360381019061022b9190611c1c565b61084e565b60405161023d9190611c77565b60405180910390f35b34801561025257600080fd5b5061026d60048036038101906102689190611c92565b610863565b60405161027d9493929190611cdd565b60405180910390f35b6102a0600480360381019061029b9190611b7e565b6108c0565b005b3480156102ae57600080fd5b506102b761091d565b005b3480156102c557600080fd5b506102e060048036038101906102db9190611f34565b610931565b005b3480156102ee57600080fd5b5061030960048036038101906103049190611c92565b610a26565b005b34801561031757600080fd5b50610320610bd2565b60405161032d9190611fac565b60405180910390f35b34801561034257600080fd5b5061035d60048036038101906103589190611c1c565b610bfb565b60405161036a9190611c77565b60405180910390f35b34801561037f57600080fd5b5061039a60048036038101906103959190611fc7565b610c61565b005b3480156103a857600080fd5b506103b1610c73565b6040516103be91906119b1565b60405180910390f35b3480156103d357600080fd5b506103ee60048036038101906103e99190611c92565b610c78565b005b3480156103fc57600080fd5b50610405610d8a565b60405161041291906119b1565b60405180910390f35b34801561042757600080fd5b50610430610d90565b60405161043d91906119b1565b60405180910390f35b34801561045257600080fd5b5061046d60048036038101906104689190611ff4565b610d96565b005b34801561047b57600080fd5b5061049660048036038101906104919190611c1c565b610daa565b6040516104a391906119b1565b60405180910390f35b3480156104b857600080fd5b506104d360048036038101906104ce9190611ff4565b610e7a565b005b6000602082516104e59190612050565b14610525576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161051c906120de565b60405180910390fd5b60005b60208251610536919061212d565b81101561061f57600061055783602084610550919061215e565b6020610f00565b80602001905181019061056a91906121b5565b9050610576848261084e565b156105ad576040517f92aa23a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b436105b6610fe8565b60000160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550508080610617906121e2565b915050610528565b505050565b60025481565b610632611015565b15610669576040517fbb6b8f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61067161102b565b8181905084849050146106b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b090612276565b60405180910390fd5b6000805b8585905081101561073e576107048686838181106106de576106dd612296565b5b905060200201358585848181106106f8576106f7612296565b5b9050602002013561103e565b83838281811061071757610716612296565b5b905060200201358261072991906122c5565b91508080610736906121e2565b9150506106bd565b50803414610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077890612345565b60405180910390fd5b5061078a6113c6565b50505050565b6107986113d9565b6000600254905060006002819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156107ed573d6000803e3d6000fd5b5050565b6107f9611015565b15610830576040517fbb6b8f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61083861102b565b6108428282611460565b61084a6113c6565b5050565b600061085a8383610bfb565b15905092915050565b60036020528060005260406000206000915090508060000160009054906101000a900460ff16908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060030154905084565b6108c8611015565b156108ff576040517fbb6b8f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61090761102b565b610911828261103e565b6109196113c6565b5050565b6109256113d9565b61092f60006115c8565b565b610939611015565b15610970576040517fbb6b8f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61097861102b565b80518251146109bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109b390612276565b60405180910390fd5b60005b8251811015610a1957610a068382815181106109de576109dd612296565b5b60200260200101518383815181106109f9576109f8612296565b5b6020026020010151611460565b8080610a11906121e2565b9150506109bf565b50610a226113c6565b5050565b610a2e611015565b15610a65576040517fbb6b8f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a6d61102b565b610a773382610bfb565b15610ab7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aae906123b1565b60405180910390fd5b60405180608001604052806000151581526020018281526020013373ffffffffffffffffffffffffffffffffffffffff16815260200160008152506003600083815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050503373ffffffffffffffffffffffffffffffffffffffff16817ffbe304b5920fbd69012a7c05a0ebc9a10c224363ac30d77cc2f0fd7c87c329ef60405160405180910390a3610bcf6113c6565b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080610c06610fe8565b60000160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000205414905092915050565b610c696113d9565b8060018190555050565b600581565b610c823382610bfb565b15610cc2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cb9906123b1565b60405180910390fd5b610ccb8161168c565b6000600360008381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff16151515158152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820154815250509050806000015115610d8657610d85826116de565b5b5050565b61271081565b60015481565b610d9e6113d9565b610da781610e7a565b50565b600080610db5610fe8565b60000160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905060008103610e43576040517f62ef5a1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008143610e5191906123d1565b905060058110610e62576000610e70565b806005610e6f91906123d1565b5b9250505092915050565b610e826113d9565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610ef45760006040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401610eeb9190611fac565b60405180910390fd5b610efd816115c8565b50565b606060008267ffffffffffffffff811115610f1e57610f1d611d33565b5b6040519080825280601f01601f191660200182016040528015610f505781602001600182028036833780820191505090505b50905060005b83811015610fdc57858582610f6b91906122c5565b81518110610f7c57610f7b612296565b5b602001015160f81c60f81b828281518110610f9a57610f99612296565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080610fd4906121e2565b915050610f56565b50809150509392505050565b6000807fa282d38759ca2a57f8989aea0c5822bcfbf65ad49415379bdbc35dbb78efd8da90508091505090565b600060026110216117f1565b6000015414905090565b60026110356117f1565b60000181905550565b6000600360008481526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff16151515158152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160038201548152505090508060000151611129576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161112090612451565b60405180910390fd5b8060600151341461116f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611166906124bd565b60405180910390fd5b6000816040015190503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036111e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111dd90612529565b60405180910390fd5b60405180608001604052806000151581526020018581526020013373ffffffffffffffffffffffffffffffffffffffff16815260200160008152506003600086815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050506112bd81338661181e565b600061271060015484606001516112d4919061215e565b6112de919061212d565b905060008184606001516112f291906123d1565b9050816002600082825461130691906122c5565b925050819055508273ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611353573d6000803e3d6000fd5b503373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16877ff85d0c07d27fabeb455264c591cac3a67f6958aaa9f46fba618eed45c283b49987606001516040516113b691906119b1565b60405180910390a4505050505050565b60016113d06117f1565b60000181905550565b6113e1611894565b73ffffffffffffffffffffffffffffffffffffffff166113ff610bd2565b73ffffffffffffffffffffffffffffffffffffffff161461145e57611422611894565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016114559190611fac565b60405180910390fd5b565b61146a3383610bfb565b156114aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114a1906123b1565b60405180910390fd5b60405180608001604052806001151581526020018381526020013373ffffffffffffffffffffffffffffffffffffffff168152602001828152506003600084815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050503373ffffffffffffffffffffffffffffffffffffffff16827fe3f89e533982f732fc486dee2bc0e466acc85c387ae7f40a9e3233a2948c9aa7836040516115bc91906119b1565b60405180910390a35050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b61169733338361181e565b803373ffffffffffffffffffffffffffffffffffffffff167f745e9ff25e7b8746bcb27c63375e46ce8ad40fd3a91c1349613f7edba7c411fe60405160405180910390a350565b60405180608001604052806000151581526020018281526020013373ffffffffffffffffffffffffffffffffffffffff16815260200160008152506003600083815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050503373ffffffffffffffffffffffffffffffffffffffff16817ffbe304b5920fbd69012a7c05a0ebc9a10c224363ac30d77cc2f0fd7c87c329ef60405160405180910390a350565b6000807f09acf4e54214992e70883cf7dcd6957ff2c71cd9e14df4bec4383bc0d11607dc90508091505090565b61182983838361189c565b808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff1d95ed4d1680e6f665104f19c296ae52c1f64cd8114e84d55dc6349dbdafea360405160405180910390a461188f838383611936565b505050565b600033905090565b6118a68382610bfb565b156118dd576040517f62ef5a1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006118e98483610daa565b90506000811461193057806040517fc91eebe400000000000000000000000000000000000000000000000000000000815260040161192791906119b1565b60405180910390fd5b50505050565b61193e610fe8565b60000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082815260200190815260200160002060009055505050565b6000819050919050565b6119ab81611998565b82525050565b60006020820190506119c660008301846119a2565b92915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f840112611a0557611a046119e0565b5b8235905067ffffffffffffffff811115611a2257611a216119e5565b5b602083019150836020820283011115611a3e57611a3d6119ea565b5b9250929050565b60008083601f840112611a5b57611a5a6119e0565b5b8235905067ffffffffffffffff811115611a7857611a776119e5565b5b602083019150836020820283011115611a9457611a936119ea565b5b9250929050565b60008060008060408587031215611ab557611ab46119d6565b5b600085013567ffffffffffffffff811115611ad357611ad26119db565b5b611adf878288016119ef565b9450945050602085013567ffffffffffffffff811115611b0257611b016119db565b5b611b0e87828801611a45565b925092505092959194509250565b6000819050919050565b611b2f81611b1c565b8114611b3a57600080fd5b50565b600081359050611b4c81611b26565b92915050565b611b5b81611998565b8114611b6657600080fd5b50565b600081359050611b7881611b52565b92915050565b60008060408385031215611b9557611b946119d6565b5b6000611ba385828601611b3d565b9250506020611bb485828601611b69565b9150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611be982611bbe565b9050919050565b611bf981611bde565b8114611c0457600080fd5b50565b600081359050611c1681611bf0565b92915050565b60008060408385031215611c3357611c326119d6565b5b6000611c4185828601611c07565b9250506020611c5285828601611b3d565b9150509250929050565b60008115159050919050565b611c7181611c5c565b82525050565b6000602082019050611c8c6000830184611c68565b92915050565b600060208284031215611ca857611ca76119d6565b5b6000611cb684828501611b3d565b91505092915050565b611cc881611b1c565b82525050565b611cd781611bde565b82525050565b6000608082019050611cf26000830187611c68565b611cff6020830186611cbf565b611d0c6040830185611cce565b611d1960608301846119a2565b95945050505050565b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b611d6b82611d22565b810181811067ffffffffffffffff82111715611d8a57611d89611d33565b5b80604052505050565b6000611d9d6119cc565b9050611da98282611d62565b919050565b600067ffffffffffffffff821115611dc957611dc8611d33565b5b602082029050602081019050919050565b6000611ded611de884611dae565b611d93565b90508083825260208201905060208402830185811115611e1057611e0f6119ea565b5b835b81811015611e395780611e258882611b3d565b845260208401935050602081019050611e12565b5050509392505050565b600082601f830112611e5857611e576119e0565b5b8135611e68848260208601611dda565b91505092915050565b600067ffffffffffffffff821115611e8c57611e8b611d33565b5b602082029050602081019050919050565b6000611eb0611eab84611e71565b611d93565b90508083825260208201905060208402830185811115611ed357611ed26119ea565b5b835b81811015611efc5780611ee88882611b69565b845260208401935050602081019050611ed5565b5050509392505050565b600082601f830112611f1b57611f1a6119e0565b5b8135611f2b848260208601611e9d565b91505092915050565b60008060408385031215611f4b57611f4a6119d6565b5b600083013567ffffffffffffffff811115611f6957611f686119db565b5b611f7585828601611e43565b925050602083013567ffffffffffffffff811115611f9657611f956119db565b5b611fa285828601611f06565b9150509250929050565b6000602082019050611fc16000830184611cce565b92915050565b600060208284031215611fdd57611fdc6119d6565b5b6000611feb84828501611b69565b91505092915050565b60006020828403121561200a576120096119d6565b5b600061201884828501611c07565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061205b82611998565b915061206683611998565b92508261207657612075612021565b5b828206905092915050565b600082825260208201905092915050565b7f496e76616c6964457468736372697074696f6e4c656e67746800000000000000600082015250565b60006120c8601983612081565b91506120d382612092565b602082019050919050565b600060208201905081810360008301526120f7816120bb565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061213882611998565b915061214383611998565b92508261215357612152612021565b5b828204905092915050565b600061216982611998565b915061217483611998565b925082820261218281611998565b91508282048414831517612199576121986120fe565b5b5092915050565b6000815190506121af81611b26565b92915050565b6000602082840312156121cb576121ca6119d6565b5b60006121d9848285016121a0565b91505092915050565b60006121ed82611998565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361221f5761221e6120fe565b5b600182019050919050565b7f4172726179206c656e6774687320646f206e6f74206d61746368000000000000600082015250565b6000612260601a83612081565b915061226b8261222a565b602082019050919050565b6000602082019050818103600083015261228f81612253565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006122d082611998565b91506122db83611998565b92508282019050808211156122f3576122f26120fe565b5b92915050565b7f496e636f727265637420746f74616c2045746865722073656e74000000000000600082015250565b600061232f601a83612081565b915061233a826122f9565b602082019050919050565b6000602082019050818103600083015261235e81612322565b9050919050565b7f53656e646572206973206e6f74206465706f7369746f72000000000000000000600082015250565b600061239b601783612081565b91506123a682612365565b602082019050919050565b600060208201905081810360008301526123ca8161238e565b9050919050565b60006123dc82611998565b91506123e783611998565b92508282039050818111156123ff576123fe6120fe565b5b92915050565b7f457468736372697074696f6e206973206e6f7420666f722073616c6500000000600082015250565b600061243b601c83612081565b915061244682612405565b602082019050919050565b6000602082019050818103600083015261246a8161242e565b9050919050565b7f4e6f7420656e6f75676820657468657200000000000000000000000000000000600082015250565b60006124a7601083612081565b91506124b282612471565b602082019050919050565b600060208201905081810360008301526124d68161249a565b9050919050565b7f53656c6c65722069732062757965720000000000000000000000000000000000600082015250565b6000612513600f83612081565b915061251e826124dd565b602082019050919050565b6000602082019050818103600083015261254281612506565b905091905056fea2646970667358221220a7403deeaae6becd3b997b8e51fbc26a9444721b1ddc81d76441f389126791ce64736f6c63430008140033
Deployed Bytecode
0x6080604052600436106101235760003560e01c80638da5cb5b116100a0578063d73792a911610064578063d73792a9146103f0578063ddca3f431461041b578063e7b59bf314610446578063e9bf95a21461046f578063f2fde38b146104ac57610124565b80638da5cb5b1461030b578063aa3bf60e14610336578063c20925c914610373578063c465e49f1461039c578063ccad70f1146103c757610124565b80635db74d20116100e75780635db74d2014610246578063642b31da14610286578063715018a6146102a25780637229e670146102b9578063892d15da146102e257610124565b806318349111146101825780633ddf97f1146101ad578063476343ee146101c95780634f868776146101e05780635cad65a11461020957610124565b5b34801561013057600080fd5b50610180336000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506104d5565b005b34801561018e57600080fd5b50610197610624565b6040516101a491906119b1565b60405180910390f35b6101c760048036038101906101c29190611a9b565b61062a565b005b3480156101d557600080fd5b506101de610790565b005b3480156101ec57600080fd5b5061020760048036038101906102029190611b7e565b6107f1565b005b34801561021557600080fd5b50610230600480360381019061022b9190611c1c565b61084e565b60405161023d9190611c77565b60405180910390f35b34801561025257600080fd5b5061026d60048036038101906102689190611c92565b610863565b60405161027d9493929190611cdd565b60405180910390f35b6102a0600480360381019061029b9190611b7e565b6108c0565b005b3480156102ae57600080fd5b506102b761091d565b005b3480156102c557600080fd5b506102e060048036038101906102db9190611f34565b610931565b005b3480156102ee57600080fd5b5061030960048036038101906103049190611c92565b610a26565b005b34801561031757600080fd5b50610320610bd2565b60405161032d9190611fac565b60405180910390f35b34801561034257600080fd5b5061035d60048036038101906103589190611c1c565b610bfb565b60405161036a9190611c77565b60405180910390f35b34801561037f57600080fd5b5061039a60048036038101906103959190611fc7565b610c61565b005b3480156103a857600080fd5b506103b1610c73565b6040516103be91906119b1565b60405180910390f35b3480156103d357600080fd5b506103ee60048036038101906103e99190611c92565b610c78565b005b3480156103fc57600080fd5b50610405610d8a565b60405161041291906119b1565b60405180910390f35b34801561042757600080fd5b50610430610d90565b60405161043d91906119b1565b60405180910390f35b34801561045257600080fd5b5061046d60048036038101906104689190611ff4565b610d96565b005b34801561047b57600080fd5b5061049660048036038101906104919190611c1c565b610daa565b6040516104a391906119b1565b60405180910390f35b3480156104b857600080fd5b506104d360048036038101906104ce9190611ff4565b610e7a565b005b6000602082516104e59190612050565b14610525576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161051c906120de565b60405180910390fd5b60005b60208251610536919061212d565b81101561061f57600061055783602084610550919061215e565b6020610f00565b80602001905181019061056a91906121b5565b9050610576848261084e565b156105ad576040517f92aa23a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b436105b6610fe8565b60000160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550508080610617906121e2565b915050610528565b505050565b60025481565b610632611015565b15610669576040517fbb6b8f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61067161102b565b8181905084849050146106b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b090612276565b60405180910390fd5b6000805b8585905081101561073e576107048686838181106106de576106dd612296565b5b905060200201358585848181106106f8576106f7612296565b5b9050602002013561103e565b83838281811061071757610716612296565b5b905060200201358261072991906122c5565b91508080610736906121e2565b9150506106bd565b50803414610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077890612345565b60405180910390fd5b5061078a6113c6565b50505050565b6107986113d9565b6000600254905060006002819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156107ed573d6000803e3d6000fd5b5050565b6107f9611015565b15610830576040517fbb6b8f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61083861102b565b6108428282611460565b61084a6113c6565b5050565b600061085a8383610bfb565b15905092915050565b60036020528060005260406000206000915090508060000160009054906101000a900460ff16908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060030154905084565b6108c8611015565b156108ff576040517fbb6b8f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61090761102b565b610911828261103e565b6109196113c6565b5050565b6109256113d9565b61092f60006115c8565b565b610939611015565b15610970576040517fbb6b8f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61097861102b565b80518251146109bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109b390612276565b60405180910390fd5b60005b8251811015610a1957610a068382815181106109de576109dd612296565b5b60200260200101518383815181106109f9576109f8612296565b5b6020026020010151611460565b8080610a11906121e2565b9150506109bf565b50610a226113c6565b5050565b610a2e611015565b15610a65576040517fbb6b8f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a6d61102b565b610a773382610bfb565b15610ab7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aae906123b1565b60405180910390fd5b60405180608001604052806000151581526020018281526020013373ffffffffffffffffffffffffffffffffffffffff16815260200160008152506003600083815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050503373ffffffffffffffffffffffffffffffffffffffff16817ffbe304b5920fbd69012a7c05a0ebc9a10c224363ac30d77cc2f0fd7c87c329ef60405160405180910390a3610bcf6113c6565b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080610c06610fe8565b60000160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008481526020019081526020016000205414905092915050565b610c696113d9565b8060018190555050565b600581565b610c823382610bfb565b15610cc2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cb9906123b1565b60405180910390fd5b610ccb8161168c565b6000600360008381526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff16151515158152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016003820154815250509050806000015115610d8657610d85826116de565b5b5050565b61271081565b60015481565b610d9e6113d9565b610da781610e7a565b50565b600080610db5610fe8565b60000160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905060008103610e43576040517f62ef5a1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008143610e5191906123d1565b905060058110610e62576000610e70565b806005610e6f91906123d1565b5b9250505092915050565b610e826113d9565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610ef45760006040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401610eeb9190611fac565b60405180910390fd5b610efd816115c8565b50565b606060008267ffffffffffffffff811115610f1e57610f1d611d33565b5b6040519080825280601f01601f191660200182016040528015610f505781602001600182028036833780820191505090505b50905060005b83811015610fdc57858582610f6b91906122c5565b81518110610f7c57610f7b612296565b5b602001015160f81c60f81b828281518110610f9a57610f99612296565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508080610fd4906121e2565b915050610f56565b50809150509392505050565b6000807fa282d38759ca2a57f8989aea0c5822bcfbf65ad49415379bdbc35dbb78efd8da90508091505090565b600060026110216117f1565b6000015414905090565b60026110356117f1565b60000181905550565b6000600360008481526020019081526020016000206040518060800160405290816000820160009054906101000a900460ff16151515158152602001600182015481526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160038201548152505090508060000151611129576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161112090612451565b60405180910390fd5b8060600151341461116f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611166906124bd565b60405180910390fd5b6000816040015190503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036111e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111dd90612529565b60405180910390fd5b60405180608001604052806000151581526020018581526020013373ffffffffffffffffffffffffffffffffffffffff16815260200160008152506003600086815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050506112bd81338661181e565b600061271060015484606001516112d4919061215e565b6112de919061212d565b905060008184606001516112f291906123d1565b9050816002600082825461130691906122c5565b925050819055508273ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611353573d6000803e3d6000fd5b503373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16877ff85d0c07d27fabeb455264c591cac3a67f6958aaa9f46fba618eed45c283b49987606001516040516113b691906119b1565b60405180910390a4505050505050565b60016113d06117f1565b60000181905550565b6113e1611894565b73ffffffffffffffffffffffffffffffffffffffff166113ff610bd2565b73ffffffffffffffffffffffffffffffffffffffff161461145e57611422611894565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016114559190611fac565b60405180910390fd5b565b61146a3383610bfb565b156114aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114a1906123b1565b60405180910390fd5b60405180608001604052806001151581526020018381526020013373ffffffffffffffffffffffffffffffffffffffff168152602001828152506003600084815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050503373ffffffffffffffffffffffffffffffffffffffff16827fe3f89e533982f732fc486dee2bc0e466acc85c387ae7f40a9e3233a2948c9aa7836040516115bc91906119b1565b60405180910390a35050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b61169733338361181e565b803373ffffffffffffffffffffffffffffffffffffffff167f745e9ff25e7b8746bcb27c63375e46ce8ad40fd3a91c1349613f7edba7c411fe60405160405180910390a350565b60405180608001604052806000151581526020018281526020013373ffffffffffffffffffffffffffffffffffffffff16815260200160008152506003600083815260200190815260200160002060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606082015181600301559050503373ffffffffffffffffffffffffffffffffffffffff16817ffbe304b5920fbd69012a7c05a0ebc9a10c224363ac30d77cc2f0fd7c87c329ef60405160405180910390a350565b6000807f09acf4e54214992e70883cf7dcd6957ff2c71cd9e14df4bec4383bc0d11607dc90508091505090565b61182983838361189c565b808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff1d95ed4d1680e6f665104f19c296ae52c1f64cd8114e84d55dc6349dbdafea360405160405180910390a461188f838383611936565b505050565b600033905090565b6118a68382610bfb565b156118dd576040517f62ef5a1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006118e98483610daa565b90506000811461193057806040517fc91eebe400000000000000000000000000000000000000000000000000000000815260040161192791906119b1565b60405180910390fd5b50505050565b61193e610fe8565b60000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082815260200190815260200160002060009055505050565b6000819050919050565b6119ab81611998565b82525050565b60006020820190506119c660008301846119a2565b92915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f840112611a0557611a046119e0565b5b8235905067ffffffffffffffff811115611a2257611a216119e5565b5b602083019150836020820283011115611a3e57611a3d6119ea565b5b9250929050565b60008083601f840112611a5b57611a5a6119e0565b5b8235905067ffffffffffffffff811115611a7857611a776119e5565b5b602083019150836020820283011115611a9457611a936119ea565b5b9250929050565b60008060008060408587031215611ab557611ab46119d6565b5b600085013567ffffffffffffffff811115611ad357611ad26119db565b5b611adf878288016119ef565b9450945050602085013567ffffffffffffffff811115611b0257611b016119db565b5b611b0e87828801611a45565b925092505092959194509250565b6000819050919050565b611b2f81611b1c565b8114611b3a57600080fd5b50565b600081359050611b4c81611b26565b92915050565b611b5b81611998565b8114611b6657600080fd5b50565b600081359050611b7881611b52565b92915050565b60008060408385031215611b9557611b946119d6565b5b6000611ba385828601611b3d565b9250506020611bb485828601611b69565b9150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611be982611bbe565b9050919050565b611bf981611bde565b8114611c0457600080fd5b50565b600081359050611c1681611bf0565b92915050565b60008060408385031215611c3357611c326119d6565b5b6000611c4185828601611c07565b9250506020611c5285828601611b3d565b9150509250929050565b60008115159050919050565b611c7181611c5c565b82525050565b6000602082019050611c8c6000830184611c68565b92915050565b600060208284031215611ca857611ca76119d6565b5b6000611cb684828501611b3d565b91505092915050565b611cc881611b1c565b82525050565b611cd781611bde565b82525050565b6000608082019050611cf26000830187611c68565b611cff6020830186611cbf565b611d0c6040830185611cce565b611d1960608301846119a2565b95945050505050565b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b611d6b82611d22565b810181811067ffffffffffffffff82111715611d8a57611d89611d33565b5b80604052505050565b6000611d9d6119cc565b9050611da98282611d62565b919050565b600067ffffffffffffffff821115611dc957611dc8611d33565b5b602082029050602081019050919050565b6000611ded611de884611dae565b611d93565b90508083825260208201905060208402830185811115611e1057611e0f6119ea565b5b835b81811015611e395780611e258882611b3d565b845260208401935050602081019050611e12565b5050509392505050565b600082601f830112611e5857611e576119e0565b5b8135611e68848260208601611dda565b91505092915050565b600067ffffffffffffffff821115611e8c57611e8b611d33565b5b602082029050602081019050919050565b6000611eb0611eab84611e71565b611d93565b90508083825260208201905060208402830185811115611ed357611ed26119ea565b5b835b81811015611efc5780611ee88882611b69565b845260208401935050602081019050611ed5565b5050509392505050565b600082601f830112611f1b57611f1a6119e0565b5b8135611f2b848260208601611e9d565b91505092915050565b60008060408385031215611f4b57611f4a6119d6565b5b600083013567ffffffffffffffff811115611f6957611f686119db565b5b611f7585828601611e43565b925050602083013567ffffffffffffffff811115611f9657611f956119db565b5b611fa285828601611f06565b9150509250929050565b6000602082019050611fc16000830184611cce565b92915050565b600060208284031215611fdd57611fdc6119d6565b5b6000611feb84828501611b69565b91505092915050565b60006020828403121561200a576120096119d6565b5b600061201884828501611c07565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061205b82611998565b915061206683611998565b92508261207657612075612021565b5b828206905092915050565b600082825260208201905092915050565b7f496e76616c6964457468736372697074696f6e4c656e67746800000000000000600082015250565b60006120c8601983612081565b91506120d382612092565b602082019050919050565b600060208201905081810360008301526120f7816120bb565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061213882611998565b915061214383611998565b92508261215357612152612021565b5b828204905092915050565b600061216982611998565b915061217483611998565b925082820261218281611998565b91508282048414831517612199576121986120fe565b5b5092915050565b6000815190506121af81611b26565b92915050565b6000602082840312156121cb576121ca6119d6565b5b60006121d9848285016121a0565b91505092915050565b60006121ed82611998565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361221f5761221e6120fe565b5b600182019050919050565b7f4172726179206c656e6774687320646f206e6f74206d61746368000000000000600082015250565b6000612260601a83612081565b915061226b8261222a565b602082019050919050565b6000602082019050818103600083015261228f81612253565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006122d082611998565b91506122db83611998565b92508282019050808211156122f3576122f26120fe565b5b92915050565b7f496e636f727265637420746f74616c2045746865722073656e74000000000000600082015250565b600061232f601a83612081565b915061233a826122f9565b602082019050919050565b6000602082019050818103600083015261235e81612322565b9050919050565b7f53656e646572206973206e6f74206465706f7369746f72000000000000000000600082015250565b600061239b601783612081565b91506123a682612365565b602082019050919050565b600060208201905081810360008301526123ca8161238e565b9050919050565b60006123dc82611998565b91506123e783611998565b92508282039050818111156123ff576123fe6120fe565b5b92915050565b7f457468736372697074696f6e206973206e6f7420666f722073616c6500000000600082015250565b600061243b601c83612081565b915061244682612405565b602082019050919050565b6000602082019050818103600083015261246a8161242e565b9050919050565b7f4e6f7420656e6f75676820657468657200000000000000000000000000000000600082015250565b60006124a7601083612081565b91506124b282612471565b602082019050919050565b600060208201905081810360008301526124d68161249a565b9050919050565b7f53656c6c65722069732062757965720000000000000000000000000000000000600082015250565b6000612513600f83612081565b915061251e826124dd565b602082019050919050565b6000602082019050818103600083015261254281612506565b905091905056fea2646970667358221220a7403deeaae6becd3b997b8e51fbc26a9444721b1ddc81d76441f389126791ce64736f6c63430008140033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | Ether (ETH) | 100.00% | $3,697.12 | 0.0455 | $168.39 |
Loading...
Loading
[ Download: CSV Export ]
[ 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.