Contract 0x16783272aA1fa186AE626182fc698D4BcABa5470

Txn Hash Method
Block
From
To
Value [Txn Fee]
0x59c0378934590d4045a41ee24394257a81394a272c2daa43ed974095455f0b190x6080604027116832023-01-24 12:47:1212 days 14 hrs ago0xd134a7d9485c1aac0cbf82718cf6d6e3fd130945 IN  Create: ERC1155StakingModuleFactory0 CLV0.01716805
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ERC1155StakingModuleFactory

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 1000 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 14 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

File 2 of 14 : IERC1155.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[EIP].
 *
 * _Available since v3.1._
 */
interface IERC1155 is IERC165 {
    /**
     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] values
    );

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

    /**
     * @dev Returns the amount of tokens of token type `id` owned by `account`.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) external view returns (uint256);

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
        external
        view
        returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the caller.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `amount`.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) external;
}

File 3 of 14 : IERC1155Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev _Available since v3.1._
 */
interface IERC1155Receiver is IERC165 {
    /**
     * @dev Handles the receipt of a single ERC1155 token type. This function is
     * called at the end of a `safeTransferFrom` after the balance has been updated.
     *
     * NOTE: To accept the transfer, this must return
     * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     * (i.e. 0xf23a6e61, or its own function selector).
     *
     * @param operator The address which initiated the transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param id The ID of the token being transferred
     * @param value The amount of tokens being transferred
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
     */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
     * @dev Handles the receipt of a multiple ERC1155 token types. This function
     * is called at the end of a `safeBatchTransferFrom` after the balances have
     * been updated.
     *
     * NOTE: To accept the transfer(s), this must return
     * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     * (i.e. 0xbc197c81, or its own function selector).
     *
     * @param operator The address which initiated the batch transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param ids An array containing ids of each token being transferred (order and length must match values array)
     * @param values An array containing amounts of each token being transferred (order and length must match ids array)
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
     */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}

File 4 of 14 : ERC1155Holder.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/utils/ERC1155Holder.sol)

pragma solidity ^0.8.0;

import "./ERC1155Receiver.sol";

/**
 * Simple implementation of `ERC1155Receiver` that will allow a contract to hold ERC1155 tokens.
 *
 * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be
 * stuck.
 *
 * @dev _Available since v3.1._
 */
contract ERC1155Holder is ERC1155Receiver {
    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(
        address,
        address,
        uint256[] memory,
        uint256[] memory,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155BatchReceived.selector;
    }
}

File 5 of 14 : ERC1155Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC1155/utils/ERC1155Receiver.sol)

pragma solidity ^0.8.0;

import "../IERC1155Receiver.sol";
import "../../../utils/introspection/ERC165.sol";

/**
 * @dev _Available since v3.1._
 */
abstract contract ERC1155Receiver is ERC165, IERC1155Receiver {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
    }
}

File 6 of 14 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 7 of 14 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 8 of 14 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 9 of 14 : ERC1155StakingModule.sol
/*
ERC1155StakingModule

https://github.com/FanbaseEU/Staking_Ethereum_SmartContracts

SPDX-License-Identifier: MIT
*/

pragma solidity ^0.8.4;

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
import "./interfaces/IStakingModule.sol";

/**
 * @title ERC721 staking module
 *
 * @notice this staking module allows users to deposit one or more ERC721
 * tokens in exchange for shares credited to their address. When the user
 * unstakes, these shares will be burned and a reward will be distributed.
 */
contract ERC1155StakingModule is IStakingModule {
	// constant
	uint256 public constant SHARES_PER_TOKEN = 10**18;
	mapping(uint256 => uint256) public sharePerTokenId;

	// members
	IERC1155 private immutable _token;
	address public immutable _factory;

	mapping(address => uint256) public userTotalBalance;
	mapping(address => mapping(uint256 => uint256)) public counts;
	mapping(uint256 => address) public owners;
	mapping(address => mapping(uint256 => uint256)) public tokenByOwner;
	mapping(uint256 => uint256) public tokenIndex;

	// newly defined
	uint256 private totalBalance;

	uint256[] public stakedTokenIds;

	event StakedERC1155(address user, address token, uint256[] tokenIds, uint256[] amounts, uint256 shares);

	// checksum
	bytes4 constant internal ERC1155_RECEIVED_VALUE = 0xf23a6e61;
    bytes4 constant internal ERC1155_BATCH_RECEIVED_VALUE = 0xbc197c81;

	/**
	 * @param token_ the token that will be rewarded
	 */
	constructor(address token_, address factory_) {
		require(
			IERC165(token_).supportsInterface(0xd9b67a26),
			"Interface ID not matched"
		);
		_token = IERC1155(token_);
		_factory = factory_;
	}

	/**
	 * @inheritdoc IStakingModule
	 */
	function tokens()
		external
		view
		override
		returns (address[] memory tokens_)
	{
		tokens_ = new address[](1);
		tokens_[0] = address(_token);
	}

	/**
	 * @inheritdoc IStakingModule
	 */
	function balances(address user)
		external
		view
		override
		returns (uint256[] memory balances_)
	{

		balances_ = new uint256[](1);
		balances_[0] = userTotalBalance[user];
	}

	/**
	 * @inheritdoc IStakingModule
	 */
	function factory() external view override returns (address) {
		return _factory;
	}

	/**
	 * @inheritdoc IStakingModule
	 */
	function totals()
		external
		view
		override
		returns (uint256[] memory totals_)
	{
		totals_ = new uint256[](1);
		totals_[0] = totalBalance;
	}

	/**
	 * @inheritdoc IStakingModule
	 */
	// function stake(
	// 	address user,
	// 	uint256 amount,
	// 	bytes calldata data
	// ) external override onlyOwner returns (address, uint256) {
	// 	// validate
	// 	require(amount > 0, "Staking amount must be greater than 0");
	// 	require(amount <= _token.balanceOf(user), "Insufficient balance");
	// 	require(data.length == 32 * amount, "Invalid calldata");

	// 	uint256 count = counts[user];

	// 	// stake
	// 	for (uint256 i = 0; i < amount; i++) {
	// 		// get token id
	// 		uint256 id;
	// 		uint256 pos = 132 + 32 * i;
	// 		assembly {
	// 			id := calldataload(pos)
	// 		}

	// 		// ownership mappings
	// 		owners[id] = user;
	// 		uint256 len = count + i;
	// 		tokenByOwner[user][len] = id;
	// 		tokenIndex[id] = len;

	// 		// transfer to module
	// 		_token.transferFrom(user, address(this), id);
	// 	}

	// 	// update position
	// 	counts[user] = count + amount;

	// 	// emit
	// 	uint256 shares = amount * SHARES_PER_TOKEN;
	// 	emit Staked(user, address(_token), amount, shares);

	// 	return (user, shares);
	// }

	function stake(
		address user,
		uint256 amount,
		bytes calldata data
	) external override onlyOwner returns (address, uint256) {
		require(data.length == 32, "Invalid calldata");

		uint256 tokenId;

		assembly {
			tokenId := calldataload(68)
		}

		uint256 shares = amount * sharePerTokenId[tokenId];

		emit Staked(user, address(_token), amount, shares);
		return (user, shares);
	}

	function _stake(
		address user, 
		uint256[] memory tokenIds, 
		uint256[] memory amounts
	) 
		internal returns (address, uint256) {

		uint256 shares;

		for (uint256 i = 0; i < tokenIds.length; i++) {
			require(amounts[i] > 0, "Staking amount must be greater than 0");
			counts[user][tokenIds[i]] = counts[user][tokenIds[i]] + amounts[i];
			userTotalBalance[user] = userTotalBalance[user] + amounts[i];
			
			shares = shares + amounts[i] * sharePerTokenId[tokenIds[i]];

			totalBalance = totalBalance + amounts[i];

			stakedTokenIds.push(tokenIds[i]);
		}

		emit StakedERC1155(user, address(_token), tokenIds, amounts, shares);

		return (user, shares);
	}

	/**
	 * @inheritdoc IStakingModule
	 */
	// function unstake(
	// 	address user,
	// 	uint256 amount,
	// 	bytes calldata data
	// ) external override onlyOwner returns (address, uint256) {
	// 	// validate
	// 	require(amount > 0, "Unstaking amount must be greater than 0");
	// 	uint256 count = counts[user];
	// 	require(amount <= count, "Insufficient staked balance");
	// 	require(data.length == 32 * amount, "Invalid calldata");

	// 	// unstake
	// 	for (uint256 i = 0; i < amount; i++) {
	// 		// get token id
	// 		uint256 id;
	// 		uint256 pos = 132 + 32 * i;
	// 		assembly {
	// 			id := calldataload(pos)
	// 		}

	// 		// ownership
	// 		require(owners[id] == user, "Only owner can unstake");
	// 		delete owners[id];

	// 		// clean up ownership mappings
	// 		uint256 lastIndex = count - 1 - i;
	// 		if (amount != count) {
	// 			// reindex on partial unstake
	// 			uint256 index = tokenIndex[id];
	// 			if (index != lastIndex) {
	// 				uint256 lastId = tokenByOwner[user][lastIndex];
	// 				tokenByOwner[user][index] = lastId;
	// 				tokenIndex[lastId] = index;
	// 			}
	// 		}
	// 		delete tokenByOwner[user][lastIndex];
	// 		delete tokenIndex[id];

	// 		// transfer to user
	// 		_token.safeTransferFrom(address(this), user, id);
	// 	}

	// 	// update position
	// 	counts[user] = count - amount;

	// 	// emit
	// 	uint256 shares = amount * SHARES_PER_TOKEN;
	// 	emit Unstaked(user, address(_token), amount, shares);

	// 	return (user, shares);
	// }

	function unstake(
		address user,
		uint256 amount,
		bytes calldata data
	) external override onlyOwner returns (address, uint256) {

		require(data.length == 32, "Invalid calldata");

		uint256 tokenId;

		assembly {
			tokenId := calldataload(68)
		}

		require(amount > 0, "Unstaking amount must be greater than 0");
		require(counts[user][tokenId] >= amount, "Insufficient staked balance");

		counts[user][tokenId] = counts[user][tokenId] - amount;
		userTotalBalance[user] = userTotalBalance[user] - amount;

		// decrease total balance
		totalBalance = totalBalance - amount;

		_token.safeTransferFrom(address(this), user, tokenId, amount, "");

		uint256 shares = amount * sharePerTokenId[tokenId];

		emit Unstaked(user, address(_token), amount, shares);
		return (user, shares);
	}

	/**
	 * @inheritdoc IStakingModule
	 */
	// function claim(
	// 	address user,
	// 	uint256 amount,
	// 	bytes calldata
	// ) external override onlyOwner returns (address, uint256) {
	// 	// validate
	// 	require(amount > 0, "Claiming amount must be greater than 0");
	// 	require(amount <= counts[user], "Insufficient balance");

	// 	uint256 shares = amount * SHARES_PER_TOKEN;
	// 	emit Claimed(user, address(_token), amount, shares);
	// 	return (user, shares);
	// }

	function claim(
		address user, 
		uint256 amount, 
		bytes calldata data
	) external override onlyOwner returns (address, uint256) {
		require(data.length == 32, "Invalid calldata");
		
		require(amount > 0, "Claiming amount must be greater than 0");
		uint256 tokenId;

		assembly {
			tokenId := calldataload(68)
		}

		require(amount <= counts[user][tokenId], "Insufficient balance");

		uint256 shares = amount * sharePerTokenId[tokenId];
		emit Claimed(user, address(_token), amount, shares);
		return (user, shares);
	}

	function getStakedTokenIds() public view returns (uint256[] memory) {
		return stakedTokenIds;
	}

	/**
	 * @inheritdoc IStakingModule
	 */
	function update(address) external override {}

	/**
	 * @inheritdoc IStakingModule
	 */
	function clean() external override {}

	 /**
        ERC1155 receiver
     */
    function onERC1155Received(
		address _operator,
		address _from, 
		uint256 _id, 
		uint256 _amount, 
		bytes memory _data
	)
    public returns(bytes4)
    {
        uint256[] memory ids = new uint256[](1);
        uint256[] memory amounts = new uint256[](1);

        ids[0] = _id;
        amounts[0] = _amount;

        require(
        ERC1155_BATCH_RECEIVED_VALUE == onERC1155BatchReceived(_operator, _from, ids, amounts, _data),
        "NE20#28"
        );

        return ERC1155_RECEIVED_VALUE;
    }

    function onERC1155BatchReceived(
        address, // _operator,
        address _from,
        uint256[] memory _ids,
        uint256[] memory _amounts,
        bytes memory)
    public returns(bytes4)
    {
        _stake(_from, _ids, _amounts);
        return ERC1155_BATCH_RECEIVED_VALUE;
    }
}

File 10 of 14 : ERC1155StakingModuleFactory.sol
/*
ERC721StakingModuleFactory

https://github.com/FanbaseEU/Staking_Ethereum_SmartContracts

SPDX-License-Identifier: MIT
*/

pragma solidity ^0.8.4;

import "./interfaces/IModuleFactory.sol";
import "./ERC1155StakingModule.sol";

/**
 * @title ERC721 staking module factory
 *
 * @notice this factory contract handles deployment for the
 * ERC721StakingModule contract
 *
 * @dev it is called by the parent PoolFactory and is responsible
 * for parsing constructor arguments before creating a new contract
 */
contract ERC1155StakingModuleFactory is IModuleFactory {
    /**
     * @inheritdoc IModuleFactory
     */
    function createModule(bytes calldata data)
        external
        override
        returns (address)
    {
        // validate
        require(data.length == 32, "Invalid calldata");

        // parse staking token
        address token;
        assembly {
            token := calldataload(68)
        }

        // create module
        ERC1155StakingModule module =
            new ERC1155StakingModule(token, address(this));
        module.transferOwnership(msg.sender);

        // output
        emit ModuleCreated(msg.sender, address(module));
        return address(module);
    }
}

File 11 of 14 : IEvents.sol
/*
IEvents

https://github.com/FanbaseEU/Staking_Ethereum_SmartContracts

SPDX-License-Identifier: MIT
 */

pragma solidity 0.8.4;

/**
 * @title GYSR event system
 *
 * @notice common interface to define GYSR event system
 */
interface IEvents {
    // staking
    event Staked(
        address indexed user,
        address indexed token,
        uint256 amount,
        uint256 shares
    );
    event Unstaked(
        address indexed user,
        address indexed token,
        uint256 amount,
        uint256 shares
    );
    event Claimed(
        address indexed user,
        address indexed token,
        uint256 amount,
        uint256 shares
    );

    // rewards
    event RewardsDistributed(
        address indexed user,
        address indexed token,
        uint256 amount,
        uint256 shares
    );
    event RewardsFunded(
        address indexed token,
        uint256 amount,
        uint256 shares,
        uint256 timestamp
    );
    event RewardsUnlocked(address indexed token, uint256 shares);
    event RewardsExpired(
        address indexed token,
        uint256 amount,
        uint256 shares,
        uint256 timestamp
    );

    // gysr
    event GysrSpent(address indexed user, uint256 amount);
    event GysrVested(address indexed user, uint256 amount);
    event GysrWithdrawn(uint256 amount);
}

File 12 of 14 : IModuleFactory.sol
/*
IModuleFactory

https://github.com/FanbaseEU/Staking_Ethereum_SmartContracts

SPDX-License-Identifier: MIT
*/

pragma solidity 0.8.4;

/**
 * @title Module factory interface
 *
 * @notice this defines the common module factory interface used by the
 * main factory to create the staking and reward modules for a new Pool.
 */
interface IModuleFactory {
    // events
    event ModuleCreated(address indexed user, address module);

    /**
     * @notice create a new Pool module
     * @param data binary encoded construction parameters
     * @return address of newly created module
     */
    function createModule(bytes calldata data) external returns (address);
}

File 13 of 14 : IStakingModule.sol
/*
IStakingModule

https://github.com/FanbaseEU/Staking_Ethereum_SmartContracts

SPDX-License-Identifier: MIT
*/

pragma solidity 0.8.4;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import "./IEvents.sol";

import "../OwnerController.sol";

/**
 * @title Staking module interface
 *
 * @notice this contract defines the common interface that any staking module
 * must implement to be compatible with the modular Pool architecture.
 */
abstract contract IStakingModule is OwnerController, IEvents {
    // constants
    uint256 public constant DECIMALS = 18;

    /**
     * @return array of staking tokens
     */
    function tokens() external view virtual returns (address[] memory);

    /**
     * @notice get balance of user
     * @param user address of user
     * @return balances of each staking token
     */
    function balances(address user)
        external
        view
        virtual
        returns (uint256[] memory);

    /**
     * @return address of module factory
     */
    function factory() external view virtual returns (address);

    /**
     * @notice get total staked amount
     * @return totals for each staking token
     */
    function totals() external view virtual returns (uint256[] memory);

    /**
     * @notice stake an amount of tokens for user
     * @param user address of user
     * @param amount number of tokens to stake
     * @param data additional data
     * @return address of staking account
     * @return number of shares minted for stake
     */
    function stake(
        address user,
        uint256 amount,
        bytes calldata data
    ) external virtual returns (address, uint256);

    /**
     * @notice unstake an amount of tokens for user
     * @param user address of user
     * @param amount number of tokens to unstake
     * @param data additional data
     * @return address of staking account
     * @return number of shares burned for unstake
     */
    function unstake(
        address user,
        uint256 amount,
        bytes calldata data
    ) external virtual returns (address, uint256);

    /**
     * @notice quote the share value for an amount of tokens without unstaking
     * @param user address of user
     * @param amount number of tokens to claim with
     * @param data additional data
     * @return address of staking account
     * @return number of shares that the claim amount is worth
     */
    function claim(
        address user,
        uint256 amount,
        bytes calldata data
    ) external virtual returns (address, uint256);

    /**
     * @notice method called by anyone to update accounting
     * @param user address of user for update
     * @dev will only be called ad hoc and should not contain essential logic
     */
    function update(address user) external virtual;

    /**
     * @notice method called by owner to clean up and perform additional accounting
     * @dev will only be called ad hoc and should not contain any essential logic
     */
    function clean() external virtual;
}

File 14 of 14 : OwnerController.sol
/*
OwnerController

https://github.com/FanbaseEU/Staking_Ethereum_SmartContracts

SPDX-License-Identifier: MIT
*/

pragma solidity 0.8.4;

/**
 * @title Owner controller
 *
 * @notice this base contract implements an owner-controller access model.
 *
 * @dev the contract is an adapted version of the OpenZeppelin Ownable contract.
 * It allows the owner to designate an additional account as the controller to
 * perform restricted operations.
 *
 * Other changes include supporting role verification with a require method
 * in addition to the modifier option, and removing some unneeded functionality.
 *
 * Original contract here:
 * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol
 */
contract OwnerController {
    address private _owner;
    address private _controller;

    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );

    event ControlTransferred(
        address indexed previousController,
        address indexed newController
    );

    constructor() {
        _owner = msg.sender;
        _controller = msg.sender;
        emit OwnershipTransferred(address(0), _owner);
        emit ControlTransferred(address(0), _owner);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view returns (address) {
        return _owner;
    }

    /**
     * @dev Returns the address of the current controller.
     */
    function controller() public view returns (address) {
        return _controller;
    }

    /**
     * @dev Modifier that throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(_owner == msg.sender, "Only owner can perform this action");
        _;
    }

    /**
     * @dev Modifier that throws if called by any account other than the controller.
     */
    modifier onlyController() {
        require(_controller == msg.sender, "Only controller can perform this action");
        _;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    function requireOwner() internal view {
        require(_owner == msg.sender, "Only owner can perform this action");
    }

    /**
     * @dev Throws if called by any account other than the controller.
     */
    function requireController() internal view {
        require(_controller == msg.sender, "Only controller can perform this action");
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`). This can
     * include renouncing ownership by transferring to the zero address.
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual {
        requireOwner();
        require(newOwner != address(0), "New owner address can't be zero");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }

    /**
     * @dev Transfers control of the contract to a new account (`newController`).
     * Can only be called by the owner.
     */
    function transferControl(address newController) public virtual {
        requireOwner();
        require(newController != address(0), "New controller address can't be zero");
        emit ControlTransferred(_controller, newController);
        _controller = newController;
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 1000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"module","type":"address"}],"name":"ModuleCreated","type":"event"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"createModule","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b50611e39806100206000396000f3fe608060405234801561001057600080fd5b506004361061002a5760003560e01c8062ee8fe51461002f575b600080fd5b61004261003d366004610215565b61006b565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6000602082146100db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f496e76616c69642063616c6c6461746100000000000000000000000000000000604482015260640160405180910390fd5b60006044359050600081306040516100f290610208565b73ffffffffffffffffffffffffffffffffffffffff928316815291166020820152604001604051809103906000f080158015610132573d6000803e3d6000fd5b506040517ff2fde38b00000000000000000000000000000000000000000000000000000000815233600482015290915073ffffffffffffffffffffffffffffffffffffffff82169063f2fde38b90602401600060405180830381600087803b15801561019d57600080fd5b505af11580156101b1573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681523392507ff708942ec477396a151a5285651961dcab8e8a82ea4f5b31a5236f92f6c92710915060200160405180910390a2949350505050565b611b818061028383390190565b60008060208385031215610227578182fd5b823567ffffffffffffffff8082111561023e578384fd5b818501915085601f830112610251578384fd5b81358181111561025f578485fd5b866020828501011115610270578485fd5b6020929092019691955090935050505056fe60c06040523480156200001157600080fd5b5060405162001b8138038062001b818339810160408190526200003491620001c8565b60008054336001600160a01b0319918216811783556001805490921681179091556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600080546040516001600160a01b0390911691907fa06677f7b64342b4bcbde423684dbdb5356acfe41ad0285b6ecbe6dc4bf427f2908290a36040516301ffc9a760e01b8152636cdb3d1360e11b60048201526001600160a01b038316906301ffc9a79060240160206040518083038186803b1580156200010057600080fd5b505afa15801562000115573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200013b9190620001ff565b6200018c5760405162461bcd60e51b815260206004820152601860248201527f496e74657266616365204944206e6f74206d6174636865640000000000000000604482015260640160405180910390fd5b6001600160601b0319606092831b8116608052911b1660a05262000228565b80516001600160a01b0381168114620001c357600080fd5b919050565b60008060408385031215620001db578182fd5b620001e683620001ab565b9150620001f660208401620001ab565b90509250929050565b60006020828403121562000211578081fd5b8151801515811462000221578182fd5b9392505050565b60805160601c60a05160601c6119036200027e600039600081816103f901526104220152600081816105bf015281816108de0152818161098f01528181610ceb01528181610d6601526113e101526119036000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80639d63848a116100ee578063c45a015511610097578063f23a6e6111610071578063f23a6e611461044c578063f2fde38b1461045f578063f77c479114610472578063fc4333cd1461023857600080fd5b8063c45a0155146103f7578063c5cc6b6a1461041d578063edf394df1461044457600080fd5b8063bc197c81116100c8578063bc197c8114610398578063c038a38e146103dc578063c4113b88146103e457600080fd5b80639d63848a146103385780639d8818f01461034d578063af7e2c661461036d57600080fd5b80633e12170f1161015b5780638c7a4638116101355780638c7a4638146102f25780638da5cb5b146103015780638f0bc152146103125780638f7398241461032557600080fd5b80633e12170f1461028d5780636d16fa41146102bf578063821a3e67146102d257600080fd5b8063259fd2211161018c578063259fd2211461023a57806327e235e3146102655780632e0f26251461028557600080fd5b8063025e7c27146101b35780630583e9f8146101f95780631c1b877214610227575b600080fd5b6101dc6101c1366004611704565b6005602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b610219610207366004611704565b60076020526000908152604090205481565b6040519081526020016101f0565b61023861023536600461152f565b50565b005b610219610248366004611659565b600660209081526000928352604080842090915290825290205481565b61027861027336600461152f565b610483565b6040516101f091906117f4565b610219601281565b6102a061029b366004611682565b6104ef565b604080516001600160a01b0390931683526020830191909152016101f0565b6102386102cd36600461152f565b61063e565b6102196102e036600461152f565b60036020526000908152604090205481565b610219670de0b6b3a764000081565b6000546001600160a01b03166101dc565b6102a0610320366004611682565b61072a565b610219610333366004611704565b61094a565b61034061096b565b6040516101f091906117a7565b61021961035b366004611704565b60026020526000908152604090205481565b61021961037b366004611659565b600460209081526000928352604080842090915290825290205481565b6103ab6103a6366004611550565b6109f2565b6040517fffffffff0000000000000000000000000000000000000000000000000000000090911681526020016101f0565b610278610a13565b6102a06103f2366004611682565b610a68565b7f00000000000000000000000000000000000000000000000000000000000000006101dc565b6101dc7f000000000000000000000000000000000000000000000000000000000000000081565b610278610dd2565b6103ab61045a3660046115f6565b610e2a565b61023861046d36600461152f565b610f7f565b6001546001600160a01b03166101dc565b604080516001808252818301909252606091602080830190803683375050506001600160a01b0383166000908152600360205260408120548251929350918391906104de57634e487b7160e01b600052603260045260246000fd5b602002602001018181525050919050565b6000805481906001600160a01b0316331461055c5760405162461bcd60e51b815260206004820152602260248201527f4f6e6c79206f776e65722063616e20706572666f726d2074686973206163746960448201526137b760f11b60648201526084015b60405180910390fd5b6020831461059f5760405162461bcd60e51b815260206004820152601060248201526f496e76616c69642063616c6c6461746160801b6044820152606401610553565b6044356000818152600260205260408120546105bb9088611850565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316886001600160a01b03167f6c86f3fd5118b3aa8bb4f389a617046de0a3d3d477de1a1673d227f802f616dc898460405161062b929190918252602082015260400190565b60405180910390a3969795505050505050565b610646611047565b6001600160a01b0381166106c15760405162461bcd60e51b8152602060048201526024808201527f4e657720636f6e74726f6c6c657220616464726573732063616e27742062652060448201527f7a65726f000000000000000000000000000000000000000000000000000000006064820152608401610553565b6001546040516001600160a01b038084169216907fa06677f7b64342b4bcbde423684dbdb5356acfe41ad0285b6ecbe6dc4bf427f290600090a36001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000805481906001600160a01b031633146107925760405162461bcd60e51b815260206004820152602260248201527f4f6e6c79206f776e65722063616e20706572666f726d2074686973206163746960448201526137b760f11b6064820152608401610553565b602083146107d55760405162461bcd60e51b815260206004820152601060248201526f496e76616c69642063616c6c6461746160801b6044820152606401610553565b6000851161084b5760405162461bcd60e51b815260206004820152602660248201527f436c61696d696e6720616d6f756e74206d75737420626520677265617465722060448201527f7468616e203000000000000000000000000000000000000000000000000000006064820152608401610553565b6001600160a01b03861660009081526004602090815260408083206044358085529252909120548611156108c15760405162461bcd60e51b815260206004820152601460248201527f496e73756666696369656e742062616c616e63650000000000000000000000006044820152606401610553565b6000818152600260205260408120546108da9088611850565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316886001600160a01b03167f2f6639d24651730c7bf57c95ddbf96d66d11477e4ec626876f92c22e5f365e68898460405161062b929190918252602082015260400190565b6009818154811061095a57600080fd5b600091825260209091200154905081565b604080516001808252818301909252606091602080830190803683370190505090507f0000000000000000000000000000000000000000000000000000000000000000816000815181106109cf57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b03168152505090565b60006109ff8585856110ac565b5063bc197c8160e01b979650505050505050565b6040805160018082528183019092526060916020808301908036833701905050905060085481600081518110610a5957634e487b7160e01b600052603260045260246000fd5b60200260200101818152505090565b6000805481906001600160a01b03163314610ad05760405162461bcd60e51b815260206004820152602260248201527f4f6e6c79206f776e65722063616e20706572666f726d2074686973206163746960448201526137b760f11b6064820152608401610553565b60208314610b135760405162461bcd60e51b815260206004820152601060248201526f496e76616c69642063616c6c6461746160801b6044820152606401610553565b60443585610b895760405162461bcd60e51b815260206004820152602760248201527f556e7374616b696e6720616d6f756e74206d757374206265206772656174657260448201527f207468616e2030000000000000000000000000000000000000000000000000006064820152608401610553565b6001600160a01b0387166000908152600460209081526040808320848452909152902054861115610bfc5760405162461bcd60e51b815260206004820152601b60248201527f496e73756666696369656e74207374616b65642062616c616e636500000000006044820152606401610553565b6001600160a01b0387166000908152600460209081526040808320848452909152902054610c2b90879061186f565b6001600160a01b038816600081815260046020908152604080832086845282528083209490945591815260039091522054610c6790879061186f565b6001600160a01b038816600090815260036020526040902055600854610c8e90879061186f565b6008556040517ff242432a0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038881166024830152604482018390526064820188905260a06084830152600060a48301527f0000000000000000000000000000000000000000000000000000000000000000169063f242432a9060c401600060405180830381600087803b158015610d2f57600080fd5b505af1158015610d43573d6000803e3d6000fd5b505050600082815260026020526040812054909150610d629088611850565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316886001600160a01b03167f06cc7e90b4f2b554a9614b0caa84f909f3498c820ae47c731f490c28c07f7d3b898460405161062b929190918252602082015260400190565b60606009805480602002602001604051908101604052809291908181526020018280548015610e2057602002820191906000526020600020905b815481526020019060010190808311610e0c575b5050505050905090565b6040805160018082528183019092526000918291906020808301908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090508582600081518110610e9457634e487b7160e01b600052603260045260246000fd5b6020026020010181815250508481600081518110610ec257634e487b7160e01b600052603260045260246000fd5b602002602001018181525050610edb88888484886109f2565b7fffffffff000000000000000000000000000000000000000000000000000000001663bc197c8160e01b14610f525760405162461bcd60e51b815260206004820152600760248201527f4e453230233238000000000000000000000000000000000000000000000000006044820152606401610553565b507ff23a6e6100000000000000000000000000000000000000000000000000000000979650505050505050565b610f87611047565b6001600160a01b038116610fdd5760405162461bcd60e51b815260206004820152601f60248201527f4e6577206f776e657220616464726573732063616e2774206265207a65726f006044820152606401610553565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b565b6000546001600160a01b031633146110455760405162461bcd60e51b815260206004820152602260248201527f4f6e6c79206f776e65722063616e20706572666f726d2074686973206163746960448201526137b760f11b6064820152608401610553565b60008080805b85518110156113bc5760008582815181106110dd57634e487b7160e01b600052603260045260246000fd5b6020026020010151116111585760405162461bcd60e51b815260206004820152602560248201527f5374616b696e6720616d6f756e74206d7573742062652067726561746572207460448201527f68616e20300000000000000000000000000000000000000000000000000000006064820152608401610553565b84818151811061117857634e487b7160e01b600052603260045260246000fd5b602002602001015160046000896001600160a01b03166001600160a01b0316815260200190815260200160002060008884815181106111c757634e487b7160e01b600052603260045260246000fd5b60200260200101518152602001908152602001600020546111e89190611838565b6001600160a01b0388166000908152600460205260408120885190919089908590811061122557634e487b7160e01b600052603260045260246000fd5b602002602001015181526020019081526020016000208190555084818151811061125f57634e487b7160e01b600052603260045260246000fd5b602002602001015160036000896001600160a01b03166001600160a01b03168152602001908152602001600020546112979190611838565b6001600160a01b0388166000908152600360205260408120919091558651600291908890849081106112d957634e487b7160e01b600052603260045260246000fd5b602002602001015181526020019081526020016000205485828151811061131057634e487b7160e01b600052603260045260246000fd5b60200260200101516113229190611850565b61132c9083611838565b915084818151811061134e57634e487b7160e01b600052603260045260246000fd5b60200260200101516008546113639190611838565b600881905550600986828151811061138b57634e487b7160e01b600052603260045260246000fd5b60209081029190910181015182546001810184556000938452919092200155806113b481611886565b9150506110b2565b507fa8d4e65faa707d7d23651270f14c684fc78adea5eb6143954e8ac787939a8ba9867f0000000000000000000000000000000000000000000000000000000000000000878785604051611414959493929190611756565b60405180910390a194959350505050565b80356001600160a01b038116811461143c57600080fd5b919050565b600082601f830112611451578081fd5b8135602067ffffffffffffffff82111561146d5761146d6118b7565b8160051b61147c828201611807565b838152828101908684018388018501891015611496578687fd5b8693505b858410156114b857803583526001939093019291840191840161149a565b50979650505050505050565b600082601f8301126114d4578081fd5b813567ffffffffffffffff8111156114ee576114ee6118b7565b611501601f8201601f1916602001611807565b818152846020838601011115611515578283fd5b816020850160208301379081016020019190915292915050565b600060208284031215611540578081fd5b61154982611425565b9392505050565b600080600080600060a08688031215611567578081fd5b61157086611425565b945061157e60208701611425565b9350604086013567ffffffffffffffff8082111561159a578283fd5b6115a689838a01611441565b945060608801359150808211156115bb578283fd5b6115c789838a01611441565b935060808801359150808211156115dc578283fd5b506115e9888289016114c4565b9150509295509295909350565b600080600080600060a0868803121561160d578081fd5b61161686611425565b945061162460208701611425565b93506040860135925060608601359150608086013567ffffffffffffffff81111561164d578182fd5b6115e9888289016114c4565b6000806040838503121561166b578182fd5b61167483611425565b946020939093013593505050565b60008060008060608587031215611697578384fd5b6116a085611425565b935060208501359250604085013567ffffffffffffffff808211156116c3578384fd5b818701915087601f8301126116d6578384fd5b8135818111156116e4578485fd5b8860208285010111156116f5578485fd5b95989497505060200194505050565b600060208284031215611715578081fd5b5035919050565b6000815180845260208085019450808401835b8381101561174b5781518752958201959082019060010161172f565b509495945050505050565b60006001600160a01b03808816835280871660208401525060a0604083015261178260a083018661171c565b8281036060840152611794818661171c565b9150508260808301529695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156117e85783516001600160a01b0316835292840192918401916001016117c3565b50909695505050505050565b602081526000611549602083018461171c565b604051601f8201601f1916810167ffffffffffffffff81118282101715611830576118306118b7565b604052919050565b6000821982111561184b5761184b6118a1565b500190565b600081600019048311821515161561186a5761186a6118a1565b500290565b600082821015611881576118816118a1565b500390565b600060001982141561189a5761189a6118a1565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220f8db2d67cf0444c299b7de6bebb4268a34d9a269c6294f6f15ae095d44cb232864736f6c63430008040033a264697066735822122092c4375c515c695d6f0f7e96b7635a65e1799e9d228a12932ddedc88a2bea41364736f6c63430008040033

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.