ETH Price: $2,991.09 (+0.54%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

View more zero value Internal Transactions in Advanced View mode

Advanced mode:

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
HoldersRewardsDistributorV1

Compiler Version
v0.8.15+commit.e14f2714

Optimization Enabled:
Yes with 200 runs

Other Settings:
london EvmVersion, MIT license
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "./HoldersRewardsDistributor.sol";
import "../utils/Transfers.sol";
import "../utils/InitializableAccessControl.sol";

/**
 * @title Bonding Curve Holder Reward Distributor
 *
 * @notice Holder reward distributor keeps track of every trade event happening in the curve,
 *      and based on the amount of shares the holder has, alters the holders' reward weight,
 *      which directly affects the amount of the distributed rewards between the holders
 *
 * @notice Holder reward distributor accepts the fees from the curve and distributes these fees
 *      across shares holders proportionally to their weights
 *
 * @dev Apart from the `accept(uint256,address)` function designed to accept the fees from the
 *      curve contract, the implementation must implement receive(), fallback(), and onTransferReceived()
 *      functions to accept direct payments in both ETH and/or ERC20 payment token
 *
 * @dev receive() and onTransferReceived() with an empty data field must accept the fee in the same way
 *      as an accept() function would do, but in a passive way (without ERC20 transfer)
 *
 * @dev The fallback() and onTransferReceived() with non-empty data field must accept the fee and the trading event;
 *      trading event encoded in the bytes data field contains the information
 *      on the trade which resulted in the fee being sent:
 *
 *      - address trader - shares holder/trader
 *      - bool isBuy - true if shares were bought, false if shares were sold
 *      - uint256 sharesAmount - amount of shares bought or sold
 *
 *      the values above are packed as data = abi.encode(trader, isBuy, sharesAmount)
 *      and can be unpacked as (trader, isBuy, sharesAmount) = abi.decode(data, (address, bool, uint256))
 *
 *      if specified, the data field must be parsed by the implementation and its containing data applied;
 *      standard logic applies, if the data is malformed implementation should throw
 *
 */
contract HoldersRewardsDistributorV1 is HoldersRewardsDistributor, InitializableAccessControl {
	// Info of each user.
	struct UserInfo {
		uint256 shares;
		uint256 rewardDebt;
		uint256 claimedAmount;
		uint256 unclaimedAmount;
	}

	// ERC20 payment token address
	address private /*immutable*/ paymentToken;
	/// bonding curve contract address
	address public sharesContractAddress;
	/// accumulated reward per share, times 1e18 (with 18 decimal precision)
	uint256 public accRewardPerShare;
	/// total number of share registered
	uint256 public totalShares;
	// Info of each user that stakes LP tokens.
	mapping(address => UserInfo) public userInfo;

	/**
	 * @dev Deploys the distributor contract
	 *
	 * @param _owner contract, optional (can be zero address), since there are no admin functions
	 * @param _sharesContractAddress TradeableShares contract to bind the distributor to,
	 *      optional (can be zero address), this can be set up later with the
	 *      `initializeSharesContractAddressIfRequired` function
	 * @param _paymentToken ERC1363 payment token to bind to, optional (can be zero address),
	 *      zero address means distributor works with the plain ETH
	 */
	constructor(address _owner, address _sharesContractAddress, address _paymentToken) initializer {
		// initialize the deployed instance
		postConstruct(_owner, _sharesContractAddress, _paymentToken);
	}

	/**
	 * @dev "Constructor replacement" for initializable, must be execute during or immediately after deployment
	 *      see https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#initializers
	 *
	 * @param _owner contract, optional (can be zero address), since there are no admin functions
	 * @param _sharesContractAddress TradeableShares contract to bind the distributor to,
	 *      optional (can be zero address), this can be set up later with the
	 *      `initializeSharesContractAddressIfRequired` function
	 * @param _paymentToken ERC1363 payment token to bind to, optional (can be zero address),
	 *      zero address means distributor works with the plain ETH
	 */
	function postConstruct(address _owner, address _sharesContractAddress, address _paymentToken) public initializer {
		// execute parent initializer(s)
		_postConstruct(_owner);

		sharesContractAddress = _sharesContractAddress;
		paymentToken = _paymentToken;
	}

	/**
	 * @notice Sets the TradeableShares contract to bind the distributor to
	 *
	 * @dev TradeableShares contract can be set only once; fails if it is already set
	 * @param _sharesContractAddress TradeableShares contract to bind the distributor to
	 */
	function initializeSharesContractAddressIfRequired(address _sharesContractAddress) public {
		// check the address is not yet set
		require(sharesContractAddress == address(0) && _sharesContractAddress != address(0), "already initialized");

		// set the TradeableShares contract address
		sharesContractAddress = _sharesContractAddress;
	}

	/**
	 * @inheritdoc HoldersRewardsDistributor
	 */
	function getPaymentToken() public view returns (address) {
		return paymentToken;
	}

	/**
	 * @dev Executed when TradeableShares contract notifies about shares bought event
	 */
	function __sharesBought(address _buyer, uint256 _amountBought) private {
		UserInfo storage userDetail = userInfo[_buyer];
		if(userDetail.shares > 0) {
			// calculated pending reward if any
			uint256 pending = ((userDetail.shares * accRewardPerShare) / 1e18) - userDetail.rewardDebt;
			if(pending > 0) {
				// update unclaimed amount
				userDetail.unclaimedAmount += pending;
			}
		}

		// update state variables
		userDetail.shares += _amountBought;
		totalShares += _amountBought;
		userDetail.rewardDebt = (userDetail.shares * accRewardPerShare) / 1e18;
	}

	/**
	 * @dev Executed when TradeableShares contract notifies about shares sold event
	 */
	function __sharesSold(address _seller, uint256 _amountSold) private {
		require(_amountSold <= userInfo[_seller].shares, "amount must be <= registered amount");

		UserInfo storage userDetail = userInfo[_seller];
		// calculated pending reward if any
		uint256 pending = ((userDetail.shares * accRewardPerShare) / 1e18) - userDetail.rewardDebt;
		if(pending > 0) {
			// update unclaimed amount
			userDetail.unclaimedAmount += pending;
		}

		// update state variables
		userDetail.shares = userDetail.shares - _amountSold;
		totalShares = totalShares - _amountSold;
		userDetail.rewardDebt = (userDetail.shares * accRewardPerShare) / 1e18;
	}

	/**
	 * @dev Executed when TradeableShares contract send the fees;
	 * @dev The very first tranche of the fees might be ignored if it is done by the issuer
	 */
	function __accept(uint256 _feeAmount) private {
		// check the state can accept the changes
		if(_feeAmount == 0 || totalShares == 0) {
			return;
		}

		// update state variables
		accRewardPerShare += (_feeAmount * 1e18) / totalShares;

		// emit an event
		emit FeeReceived(_feeAmount);
	}


	/**
	 * @dev Processes the fee, and the sync message
	 *
	 * @dev Takes care about the encoded bytes data containing trader address, trade operation type,
	 *      and amount of the shares bought
	 *
	 * @dev Format: address | bool | uint256
	 */
	function __parseTrade(uint256 _feeAmount, bytes memory data) private {
		if(totalShares == 0) {
			__parseFirstTrade(_feeAmount, data);
		}
		else {
			__parseNextTrade(_feeAmount, data);
		}
	}

	/**
	 * @dev Processes the very first fee, and the sync message
	 */
	function __parseFirstTrade(uint256 _feeAmount, bytes memory data) private {
		// the very first sync message must not be empty
		require(data.length != 0, "sync message expected");

		// verify message length
		require(data.length == 96, "malformed sync message");

		// decode the sync message
		(address trader, bool isBuy, uint256 sharesAmount) = abi.decode(data, (address, bool, uint256));
		// the very first operation can be buy only, and cannot be zero
		require(isBuy && sharesAmount >= 1, "invalid state");

		// init: notify about the first share
		__sharesBought(trader, 1);
		// to save the gas execute the rest of the functions only if there is a need
		if(sharesAmount > 1) {
			// process the fee
			__accept(_feeAmount);
			// notify about the remaining shares
			__sharesBought(trader, sharesAmount - 1);
		}

		// emit an event
		emit SharesTraded(trader, true, sharesAmount);
	}

	/**
	 * @dev Processes not the very first fee, and the sync message
	 */
	function __parseNextTrade(uint256 _feeAmount, bytes memory data) private {
		// process the fee
		__accept(_feeAmount);

		// if the sync message is empty, we're done
		if(data.length == 0) {
			return;
		}

		// verify message length
		require(data.length == 96, "malformed sync message");

		// decode the sync message
		(address trader, bool isBuy, uint256 sharesAmount) = abi.decode(data, (address, bool, uint256));
		if(isBuy) {
			// notify buy
			__sharesBought(trader, sharesAmount);
		}
		else {
			// notify sell
			__sharesSold(trader, sharesAmount);
		}

		// emit an event
		emit SharesTraded(trader, isBuy, sharesAmount);
	}

	/**
	 * @inheritdoc HoldersRewardsDistributor
	 */
	function claimTheReward() public {
		uint256 claimableAmount = pendingReward(msg.sender);
		require(claimableAmount > 0, "Nothing to claim");

		UserInfo storage userDetail = userInfo[msg.sender];
		// update state variable
		userDetail.unclaimedAmount = 0;
		userDetail.claimedAmount += claimableAmount;
		userDetail.rewardDebt = (userDetail.shares * accRewardPerShare) / 1e18;

		// transfer reward
		if(paymentToken == address(0)) {
			Transfers.transfer(payable(msg.sender), claimableAmount);
		}
		else {
			require(ERC20(paymentToken).transfer(msg.sender, claimableAmount));
		}

		// emit an event
		emit RewardClaimed(msg.sender, claimableAmount);
	}

	/**
	 * @inheritdoc HoldersRewardsDistributor
	 */
	function pendingReward(address holder) public view returns (uint256) {
		// read user details and calculate how much we own
		UserInfo memory userDetail = userInfo[holder];
		uint256 pending = userDetail.unclaimedAmount + userDetail.shares * accRewardPerShare / 1e18 - userDetail.rewardDebt;

		// get an idea of how much we have on the balance
		uint256 available = paymentToken == address(0)? address(this).balance: ERC20(paymentToken).balanceOf(address(this));

		// we allow up to 1 gwei cumulative discrepancy due to rounding errors
		require(pending < 1_000_000_000 + available, "discrepancy error");

		// return the amount we're actually able to return in `claimTheReward`
		return pending > available? available: pending;
	}

	/**
	 * @inheritdoc ERC1363Receiver
	 *
	 * @notice Anyone can send some additional rewards – just use empty `data` for a callback
	 *
	 * @dev Non-empty `data` executes trade updates and therefore is restricted to be sent only
	 *      by `sharesContractAddress`
	 */
	function onTransferReceived(address operator, address, uint256 value, bytes memory data) public returns (bytes4) {
		require(msg.sender == paymentToken, "received event from wrong token");
		require(operator == sharesContractAddress, "not allowed");

		__parseTrade(value, data);
		return ERC1363Receiver(this).onTransferReceived.selector;
	}

	/**
	 * @notice Receive is public. Anyone can send some additional rewards ;)
	 */
	receive() external payable {
		require(paymentToken == address(0), "not allowed");
		__parseTrade(msg.value, bytes(""));
	}

	/**
	 * @dev Fallback executes trade updates and therefore is restricted to be executed only by `sharesContractAddress`
	 *
	 * @notice If you want do donate some rewards - use `receive()`
	 */
	fallback() external payable {
		require(paymentToken == address(0), "not an ETH reward distributor");

		require(msg.sender == sharesContractAddress, "not allowed");
		__parseTrade(msg.value, msg.data);
	}
}

File 2 of 9 : Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol)

pragma solidity ^0.8.0;

import "../../utils/AddressUpgradeable.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
 * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() initializer {}
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        // If the contract is initializing we ignore whether _initialized is set in order to support multiple
        // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
        // contract may have been reentered.
        require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} modifier, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    function _isConstructor() private view returns (bool) {
        return !AddressUpgradeable.isContract(address(this));
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "../interfaces/ERC1363Spec.sol";

/**
 * @title Bonding Curve Holder Reward Distributor
 *
 * @notice Holder reward distributor keeps track of every trade event happening in the curve,
 *      and based on the amount of shares the holder has, alters the holders' reward weight,
 *      which directly affects the amount of the distributed rewards between the holders
 *
 * @notice Holder reward distributor accepts the fees from the curve and distributes these fees
 *      across shares holders proportionally to their weights
 *
 * @dev Apart from the `accept(uint256,address)` function designed to accept the fees from the
 *      curve contract, the implementation must implement receive(), fallback(), and onTransferReceived()
 *      functions to accept direct payments in both ETH and/or ERC20 payment token
 *
 * @dev receive() and onTransferReceived() with an empty data field must accept the fee in the same way
 *      as an accept() function would do, but in a passive way (without ERC20 transfer)
 *
 * @dev The fallback() and onTransferReceived() with non-empty data field must accept the fee and the trading event;
 *      trading event encoded in the bytes data field contains the information
 *      on the trade which resulted in the fee being sent:
 *
 *      - address trader - shares holder/trader
 *      - bool isBuy - true if shares were bought, false if shares were sold
 *      - uint256 sharesAmount - amount of shares bought or sold
 *
 *      the values above are packed as data = abi.encode(trader, isBuy, sharesAmount)
 *      and can be unpacked as (trader, isBuy, sharesAmount) = abi.decode(data, (address, bool, uint256))
 *
 *      if specified, the data field must be parsed by the implementation and its containing data applied;
 *      standard logic applies, if the data is malformed implementation should throw
 *
 */
interface HoldersRewardsDistributor is ERC1363Receiver {
	/**
	 * @dev Fired in `sharesBought` and `sharesSold`
	 *
	 * @param trader is a buyer or a seller, depending on the operation type
	 * @param isBuy true if the event comes from the `sharesBought` and represents the buy operation,
	 *      false if the event comes from the `sharesSold` and represents the sell operation
	 * @param sharesAmount amount of the shares bought or sold (see `isBuy`)
	 */
	event SharesTraded(address indexed trader, bool indexed isBuy, uint256 sharesAmount);

	/**
	 * @dev Fired when the fee for the distribution is received
	 *
	 * @param feeAmount amount of the fee to distribute between the holders
	 */
	event FeeReceived(uint256 feeAmount);

	/**
	 * @dev Fired in `claimReward`
	 *
	 * @param holder address of the trader (and shares holder) who received the reward
	 * @param rewardAmount amount of the reward sent
	 */
	event RewardClaimed(address indexed holder, uint256 rewardAmount);

	/**
	 * @notice ERC20 payment token distributor is bound to
	 *
	 * @return paymentToken ERC20 payment token address the contract is bound to,
	 *      or zero zero address if it operates with the plain ETH
	 */
	function getPaymentToken() external view returns(address paymentToken);

/*
	*/
/**
	 * @notice Notifies the distributor about the trade event
	 *
	 * @dev Trade amount specified affects holder's (buyer's) weight when calculating the reward
	 *
	 * @param buyer shares buyer (becomes shares holder if not yet), a.k.a trader
	 * @param amountBought amount of the shares bought
	 *//*

	function sharesBought(address buyer, uint256 amountBought) external;

	*/
/**
	 * @notice Notifies the distributor about the trade event
	 *
	 * @dev Trade amount specified affects holder's (seller's) weight when calculating the reward
	 *
	 * @param seller shares seller (shares holder), a.k.a trader
	 * @param amountSold amount of the shares sold
	 *//*

	function sharesSold(address seller, uint256 amountSold) external;

	*/
/**
	 * @notice Executed by the fee sender to send the fee; in case of the ERC20 payment,
	 *      this is the ask to take the specified amount of the ERC20 token of the specified type;
	 *      in case of the ETH payment, the amount must be supplied with the transaction itself
	 *
	 * @dev When paying with an ERC20 payment token, sender must approve the contract for
	 *      at least the amount specified before executing this function
	 *
	 * @dev Updates the accumulated reward per share
	 *
	 * @param feeAmount amount of the fee sent,
	 *      in the case of ETH payment must be equal to msg.value
	 *//*

	function accept(uint256 feeAmount) external payable;
*/

	/**
	 * @notice Executed by the holder to claim entire pending reward
	 *
	 * @dev Holder can verify pending reward amount with the `pendingReward` function
	 */
	function claimTheReward() external;

	/**
	 * @notice Pending (claimable) reward. This is the amount which can be claimed using `claimTheReward`
	 *
	 * @param holder the holder address to query the reward for
	 * @return rewardAmount pending reward amount\
	 */
	function pendingReward(address holder) external view returns(uint256 rewardAmount);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "./ERC20Spec.sol";
import "./ERC165Spec.sol";

/**
 * @title ERC1363 Interface
 *
 * @dev Interface defining a ERC1363 Payable Token contract.
 *      Implementing contracts MUST implement the ERC1363 interface as well as the ERC20 and ERC165 interfaces.
 */
interface ERC1363 is ERC20, ERC165  {
	/*
	 * Note: the ERC-165 identifier for this interface is 0xb0202a11.
	 * 0xb0202a11 ===
	 *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
	 *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
	 *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
	 *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
	 *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
	 *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
	 */

	/**
	 * @notice Transfer tokens from `msg.sender` to another address and then call `onTransferReceived` on receiver
	 * @param to address The address which you want to transfer to
	 * @param value uint256 The amount of tokens to be transferred
	 * @return true unless throwing
	 */
	function transferAndCall(address to, uint256 value) external returns (bool);

	/**
	 * @notice Transfer tokens from `msg.sender` to another address and then call `onTransferReceived` on receiver
	 * @param to address The address which you want to transfer to
	 * @param value uint256 The amount of tokens to be transferred
	 * @param data bytes Additional data with no specified format, sent in call to `to`
	 * @return true unless throwing
	 */
	function transferAndCall(address to, uint256 value, bytes memory data) external returns (bool);

	/**
	 * @notice Transfer tokens from one address to another and then call `onTransferReceived` on receiver
	 * @param from address The address which you want to send tokens from
	 * @param to address The address which you want to transfer to
	 * @param value uint256 The amount of tokens to be transferred
	 * @return true unless throwing
	 */
	function transferFromAndCall(address from, address to, uint256 value) external returns (bool);


	/**
	 * @notice Transfer tokens from one address to another and then call `onTransferReceived` on receiver
	 * @param from address The address which you want to send tokens from
	 * @param to address The address which you want to transfer to
	 * @param value uint256 The amount of tokens to be transferred
	 * @param data bytes Additional data with no specified format, sent in call to `to`
	 * @return true unless throwing
	 */
	function transferFromAndCall(address from, address to, uint256 value, bytes memory data) external returns (bool);

	/**
	 * @notice Approve the passed address to spend the specified amount of tokens on behalf of msg.sender
	 * and then call `onApprovalReceived` on spender.
	 * @param spender address The address which will spend the funds
	 * @param value uint256 The amount of tokens to be spent
	 */
	function approveAndCall(address spender, uint256 value) external returns (bool);

	/**
	 * @notice Approve the passed address to spend the specified amount of tokens on behalf of msg.sender
	 * and then call `onApprovalReceived` on spender.
	 * @param spender address The address which will spend the funds
	 * @param value uint256 The amount of tokens to be spent
	 * @param data bytes Additional data with no specified format, sent in call to `spender`
	 */
	function approveAndCall(address spender, uint256 value, bytes memory data) external returns (bool);
}

/**
 * @title ERC1363Receiver Interface
 *
 * @dev Interface for any contract that wants to support `transferAndCall` or `transferFromAndCall`
 *      from ERC1363 token contracts.
 */
interface ERC1363Receiver {
	/*
	 * Note: the ERC-165 identifier for this interface is 0x88a7ca5c.
	 * 0x88a7ca5c === bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))
	 */

	/**
	 * @notice Handle the receipt of ERC1363 tokens
	 *
	 * @dev Any ERC1363 smart contract calls this function on the recipient
	 *      after a `transfer` or a `transferFrom`. This function MAY throw to revert and reject the
	 *      transfer. Return of other than the magic value MUST result in the
	 *      transaction being reverted.
	 *      Note: the token contract address is always the message sender.
	 *
	 * @param operator address The address which called `transferAndCall` or `transferFromAndCall` function
	 * @param from address The address which are token transferred from
	 * @param value uint256 The amount of tokens transferred
	 * @param data bytes Additional data with no specified format
	 * @return `bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))`
	 *      unless throwing
	 */
	function onTransferReceived(address operator, address from, uint256 value, bytes memory data) external returns (bytes4);
}

/**
 * @title ERC1363Spender Interface
 *
 * @dev Interface for any contract that wants to support `approveAndCall`
 *      from ERC1363 token contracts.
 */
interface ERC1363Spender {
	/*
	 * Note: the ERC-165 identifier for this interface is 0x7b04a2d0.
	 * 0x7b04a2d0 === bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))
	 */

	/**
	 * @notice Handle the approval of ERC1363 tokens
	 *
	 * @dev Any ERC1363 smart contract calls this function on the recipient
	 *      after an `approve`. This function MAY throw to revert and reject the
	 *      approval. Return of other than the magic value MUST result in the
	 *      transaction being reverted.
	 *      Note: the token contract address is always the message sender.
	 *
	 * @param owner address The address which called `approveAndCall` function
	 * @param value uint256 The amount of tokens to be spent
	 * @param data bytes Additional data with no specified format
	 * @return `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))`
	 *      unless throwing
	 */
	function onApprovalReceived(address owner, uint256 value, bytes memory data) external returns (bytes4);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/**
 * @title ERC-165 Standard Interface Detection
 *
 * @dev Interface of the ERC165 standard, as defined in the
 *       https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * @dev Implementers can declare support of contract interfaces,
 *      which can then be queried by others.
 *
 * @author Christian Reitwießner, Nick Johnson, Fabian Vogelsteller, Jordi Baylina, Konrad Feldmeier, William Entriken
 */
interface ERC165 {
	/**
	 * @notice Query if a contract implements an interface
	 *
	 * @dev Interface identification is specified in ERC-165.
	 *      This function uses less than 30,000 gas.
	 *
	 * @param interfaceID The interface identifier, as specified in ERC-165
	 * @return `true` if the contract implements `interfaceID` and
	 *      `interfaceID` is not 0xffffffff, `false` otherwise
	 */
	function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/**
 * @title EIP-20: ERC-20 Token Standard
 *
 * @notice The ERC-20 (Ethereum Request for Comments 20), proposed by Fabian Vogelsteller in November 2015,
 *      is a Token Standard that implements an API for tokens within Smart Contracts.
 *
 * @notice It provides functionalities like to transfer tokens from one account to another,
 *      to get the current token balance of an account and also the total supply of the token available on the network.
 *      Besides these it also has some other functionalities like to approve that an amount of
 *      token from an account can be spent by a third party account.
 *
 * @notice If a Smart Contract implements the following methods and events it can be called an ERC-20 Token
 *      Contract and, once deployed, it will be responsible to keep track of the created tokens on Ethereum.
 *
 * @notice See https://ethereum.org/en/developers/docs/standards/tokens/erc-20/
 * @notice See https://eips.ethereum.org/EIPS/eip-20
 */
interface ERC20 {
	/**
	 * @dev Fired in transfer(), transferFrom() to indicate that token transfer happened
	 *
	 * @param from an address tokens were consumed from
	 * @param to an address tokens were sent to
	 * @param value number of tokens transferred
	 */
	event Transfer(address indexed from, address indexed to, uint256 value);

	/**
	 * @dev Fired in approve() to indicate an approval event happened
	 *
	 * @param owner an address which granted a permission to transfer
	 *      tokens on its behalf
	 * @param spender an address which received a permission to transfer
	 *      tokens on behalf of the owner `_owner`
	 * @param value amount of tokens granted to transfer on behalf
	 */
	event Approval(address indexed owner, address indexed spender, uint256 value);

	/**
	 * @return name of the token (ex.: USD Coin)
	 */
	// OPTIONAL - This method can be used to improve usability,
	// but interfaces and other contracts MUST NOT expect these values to be present.
	// function name() external view returns (string memory);

	/**
	 * @return symbol of the token (ex.: USDC)
	 */
	// OPTIONAL - This method can be used to improve usability,
	// but interfaces and other contracts MUST NOT expect these values to be present.
	// function symbol() external view returns (string memory);

	/**
	 * @dev Returns the number of decimals used to get its user representation.
	 *      For example, if `decimals` equals `2`, a balance of `505` tokens should
	 *      be displayed to a user as `5,05` (`505 / 10 ** 2`).
	 *
	 * @dev Tokens usually opt for a value of 18, imitating the relationship between
	 *      Ether and Wei. This is the value {ERC20} uses, unless this function is
	 *      overridden;
	 *
	 * @dev NOTE: This information is only used for _display_ purposes: it in
	 *      no way affects any of the arithmetic of the contract, including
	 *      {IERC20-balanceOf} and {IERC20-transfer}.
	 *
	 * @return token decimals
	 */
	// OPTIONAL - This method can be used to improve usability,
	// but interfaces and other contracts MUST NOT expect these values to be present.
	// function decimals() external view returns (uint8);

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

	/**
	 * @notice Gets the balance of a particular address
	 *
	 * @param _owner the address to query the the balance for
	 * @return balance an amount of tokens owned by the address specified
	 */
	function balanceOf(address _owner) external view returns (uint256 balance);

	/**
	 * @notice Transfers some tokens to an external address or a smart contract
	 *
	 * @dev Called by token owner (an address which has a
	 *      positive token balance tracked by this smart contract)
	 * @dev Throws on any error like
	 *      * insufficient token balance or
	 *      * incorrect `_to` address:
	 *          * zero address or
	 *          * self address or
	 *          * smart contract which doesn't support ERC20
	 *
	 * @param _to an address to transfer tokens to,
	 *      must be either an external address or a smart contract,
	 *      compliant with the ERC20 standard
	 * @param _value amount of tokens to be transferred,, zero
	 *      value is allowed
	 * @return success true on success, throws otherwise
	 */
	function transfer(address _to, uint256 _value) external returns (bool success);

	/**
	 * @notice Transfers some tokens on behalf of address `_from' (token owner)
	 *      to some other address `_to`
	 *
	 * @dev Called by token owner on his own or approved address,
	 *      an address approved earlier by token owner to
	 *      transfer some amount of tokens on its behalf
	 * @dev Throws on any error like
	 *      * insufficient token balance or
	 *      * incorrect `_to` address:
	 *          * zero address or
	 *          * same as `_from` address (self transfer)
	 *          * smart contract which doesn't support ERC20
	 *
	 * @param _from token owner which approved caller (transaction sender)
	 *      to transfer `_value` of tokens on its behalf
	 * @param _to an address to transfer tokens to,
	 *      must be either an external address or a smart contract,
	 *      compliant with the ERC20 standard
	 * @param _value amount of tokens to be transferred,, zero
	 *      value is allowed
	 * @return success true on success, throws otherwise
	 */
	function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);

	/**
	 * @notice Approves address called `_spender` to transfer some amount
	 *      of tokens on behalf of the owner (transaction sender)
	 *
	 * @dev Transaction sender must not necessarily own any tokens to grant the permission
	 *
	 * @param _spender an address approved by the caller (token owner)
	 *      to spend some tokens on its behalf
	 * @param _value an amount of tokens spender `_spender` is allowed to
	 *      transfer on behalf of the token owner
	 * @return success true on success, throws otherwise
	 */
	function approve(address _spender, uint256 _value) external returns (bool success);

	/**
	 * @notice Returns the amount which _spender is still allowed to withdraw from _owner.
	 *
	 * @dev A function to check an amount of tokens owner approved
	 *      to transfer on its behalf by some other address called "spender"
	 *
	 * @param _owner an address which approves transferring some tokens on its behalf
	 * @param _spender an address approved to transfer some tokens on behalf
	 * @return remaining an amount of tokens approved address `_spender` can transfer on behalf
	 *      of token owner `_owner`
	 */
	function allowance(address _owner, address _spender) external view returns (uint256 remaining);
}

/**
 * @title Mintable/burnable ERC20 Extension
 *
 * @notice Adds mint/burn functions to ERC20 interface, these functions
 *      are usually present in ERC20 implementations, but these become
 *      a must for the bridged tokens in L2 since the bridge on L2
 *      needs to have a way to mint tokens deposited from L1 to L2
 *      and to burn tokens to be withdrawn from L2 to L1
 */
interface MintableBurnableERC20 is ERC20 {
	/**
	 * @dev Mints (creates) some tokens to address specified
	 * @dev The value specified is treated as is without taking
	 *      into account what `decimals` value is
	 *
	 * @param _to an address to mint tokens to
	 * @param _value an amount of tokens to mint (create)
	 */
	function mint(address _to, uint256 _value) external;

	/**
	 * @dev Burns (destroys) some tokens from the address specified
	 *
	 * @dev The value specified is treated as is without taking
	 *      into account what `decimals` value is
	 *
	 * @param _from an address to burn some tokens from
	 * @param _value an amount of tokens to burn (destroy)
	 */
	function burn(address _from, uint256 _value) external;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

/**
 * @title Initializable Role-based Access Control (RBAC) // ERC1967Proxy
 *
 * @notice Access control smart contract provides an API to check
 *      if a specific operation is permitted globally and/or
 *      if a particular user has a permission to execute it.
 *
 * @notice This contract is inherited by other contracts requiring the role-based access control (RBAC)
 *      protection for the restricted access functions
 *
 * @notice It deals with two main entities: features and roles.
 *
 * @notice Features are designed to be used to enable/disable public functions
 *      of the smart contract (used by a wide audience).
 * @notice User roles are designed to control the access to restricted functions
 *      of the smart contract (used by a limited set of maintainers).
 *
 * @notice Terms "role", "permissions" and "set of permissions" have equal meaning
 *      in the documentation text and may be used interchangeably.
 * @notice Terms "permission", "single permission" implies only one permission bit set.
 *
 * @notice Access manager is a special role which allows to grant/revoke other roles.
 *      Access managers can only grant/revoke permissions which they have themselves.
 *      As an example, access manager with no other roles set can only grant/revoke its own
 *      access manager permission and nothing else.
 *
 * @notice Access manager permission should be treated carefully, as a super admin permission:
 *      Access manager with even no other permission can interfere with another account by
 *      granting own access manager permission to it and effectively creating more powerful
 *      permission set than its own.
 *
 * @dev Both current and OpenZeppelin AccessControl implementations feature a similar API
 *      to check/know "who is allowed to do this thing".
 * @dev Zeppelin implementation is more flexible:
 *      - it allows setting unlimited number of roles, while current is limited to 256 different roles
 *      - it allows setting an admin for each role, while current allows having only one global admin
 * @dev Current implementation is more lightweight:
 *      - it uses only 1 bit per role, while Zeppelin uses 256 bits
 *      - it allows setting up to 256 roles at once, in a single transaction, while Zeppelin allows
 *        setting only one role in a single transaction
 *
 * @dev This smart contract is designed to be inherited by other
 *      smart contracts which require access control management capabilities.
 *
 * @dev Access manager permission has a bit 255 set.
 *      This bit must not be used by inheriting contracts for any other permissions/features.
 *
 * @dev This is an initializable version of the RBAC, based on Zeppelin implementation,
 *      it can be used for ERC1967 proxies, as well as for EIP-1167 minimal proxies
 *      see https://docs.openzeppelin.com/contracts/4.x/upgradeable
 *      see https://docs.openzeppelin.com/contracts/4.x/api/proxy#UUPSUpgradeable
 *      see https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786
 *      see https://eips.ethereum.org/EIPS/eip-1167
 *      see https://docs.openzeppelin.com/contracts/4.x/api/proxy#Clones
 *
 * @author Basil Gorin
 */
abstract contract InitializableAccessControl is Initializable {
	/**
	 * @dev Privileged addresses with defined roles/permissions
	 * @dev In the context of ERC20/ERC721 tokens these can be permissions to
	 *      allow minting or burning tokens, transferring on behalf and so on
	 *
	 * @dev Maps user address to the permissions bitmask (role), where each bit
	 *      represents a permission
	 * @dev Bitmask 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
	 *      represents all possible permissions
	 * @dev 'This' address mapping represents global features of the smart contract
	 *
	 * @dev We keep the mapping private to prevent direct writes to it from the inheriting
	 *      contracts, `getRole()` and `updateRole()` functions should be used instead
	 */
	mapping(address => uint256) private userRoles;

	/**
	 * @dev Empty reserved space in storage. The size of the __gap array is calculated so that
	 *      the amount of storage used by a contract always adds up to the 50.
	 *      See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
	 */
	uint256[49] private __gap;

	/**
	 * @notice Access manager is responsible for assigning the roles to users,
	 *      enabling/disabling global features of the smart contract
	 * @notice Access manager can add, remove and update user roles,
	 *      remove and update global features
	 *
	 * @dev Role ROLE_ACCESS_MANAGER allows modifying user roles and global features
	 * @dev Role ROLE_ACCESS_MANAGER has single bit at position 255 enabled
	 */
	uint256 public constant ROLE_ACCESS_MANAGER = 0x8000000000000000000000000000000000000000000000000000000000000000;

	/**
	 * @notice Upgrade manager is responsible for smart contract upgrades,
	 *      see https://docs.openzeppelin.com/contracts/4.x/api/proxy#UUPSUpgradeable
	 *      see https://docs.openzeppelin.com/contracts/4.x/upgradeable
	 *
	 * @dev Role ROLE_UPGRADE_MANAGER allows passing the _authorizeUpgrade() check
	 * @dev Role ROLE_UPGRADE_MANAGER has single bit at position 254 enabled
	 */
	uint256 public constant ROLE_UPGRADE_MANAGER = 0x4000000000000000000000000000000000000000000000000000000000000000;

	/**
	 * @dev Bitmask representing all the possible permissions (super admin role)
	 * @dev Has all the bits are enabled (2^256 - 1 value)
	 */
	uint256 private constant FULL_PRIVILEGES_MASK = type(uint256).max; // before 0.8.0: uint256(-1) overflows to 0xFFFF...

	/**
	 * @dev Fired in updateRole() and updateFeatures()
	 *
	 * @param operator address which was granted/revoked permissions
	 * @param requested permissions requested
	 * @param assigned permissions effectively set
	 */
	event RoleUpdated(address indexed operator, uint256 requested, uint256 assigned);

	/**
	 * @notice Function modifier making a function defined as public behave as restricted
	 *      (so that only a pre-configured set of accounts can execute it)
	 *
	 * @param role the role transaction executor is required to have;
	 *      the function throws an "access denied" exception if this condition is not met
	 */
	modifier restrictedTo(uint256 role) {
		// verify the access permission
		require(isSenderInRole(role), "access denied");

		// execute the rest of the function
		_;
	}

	/**
	 * @dev Creates/deploys the ACL implementation to be used in a proxy
	 *
	 * @dev Note:
	 *      the implementation is already initialized and
	 *      `_postConstruct` is not executable on the implementation
	 *      `_postConstruct` is still available in the context of a proxy
	 *      and should be executed on the proxy deployment (in the same tx)
	 */
	 // constructor() initializer {}

	/**
	 * @dev Contract initializer, sets the contract owner to have full privileges
	 *
	 * @dev Can be executed only once, reverts when executed second time
	 *
	 * @dev IMPORTANT:
	 *      this function SHOULD be executed during proxy deployment (in the same transaction)
	 *
	 * @param _owner smart contract owner having full privileges
	 */
	function _postConstruct(address _owner) internal virtual onlyInitializing {
		// grant owner full privileges
		__setRole(_owner, FULL_PRIVILEGES_MASK, FULL_PRIVILEGES_MASK);
	}

	/**
	 * @dev Highest version that has been initialized.
	 *      Non-zero value means contract was already initialized.
	 * @dev see {Initializable}, {reinitializer}.
	 *
	 * @return highest version that has been initialized
	 */
/*
	function getInitializedVersion() public view returns(uint64) {
		// delegate to `_getInitializedVersion`
		return _getInitializedVersion();
	}
*/

	/**
	 * @notice Retrieves globally set of features enabled
	 *
	 * @dev Effectively reads userRoles role for the contract itself
	 *
	 * @return 256-bit bitmask of the features enabled
	 */
	function features() public view returns (uint256) {
		// features are stored in 'this' address mapping of `userRoles`
		return getRole(address(this));
	}

	/**
	 * @notice Updates set of the globally enabled features (`features`),
	 *      taking into account sender's permissions
	 *
	 * @dev Requires transaction sender to have `ROLE_ACCESS_MANAGER` permission
	 * @dev Function is left for backward compatibility with older versions
	 *
	 * @param _mask bitmask representing a set of features to enable/disable
	 */
	function updateFeatures(uint256 _mask) public {
		// delegate call to `updateRole`
		updateRole(address(this), _mask);
	}

	/**
	 * @notice Reads the permissions (role) for a given user from the `userRoles` mapping
	 *      (privileged addresses with defined roles/permissions)
	 * @notice In the context of ERC20/ERC721 tokens these can be permissions to
	 *      allow minting or burning tokens, transferring on behalf and so on
	 *
	 * @dev Having a simple getter instead of making the mapping public
	 *      allows enforcing the encapsulation of the mapping and protects from
	 *      writing to it directly in the inheriting smart contracts
	 *
	 * @param operator address of a user to read permissions for,
	 *      or self address to read global features of the smart contract
	 */
	function getRole(address operator) public view returns(uint256) {
		// read the value from `userRoles` and return
		return userRoles[operator];
	}

	/**
	 * @notice Updates set of permissions (role) for a given user,
	 *      taking into account sender's permissions.
	 *
	 * @dev Setting role to zero is equivalent to removing an all permissions
	 * @dev Setting role to `FULL_PRIVILEGES_MASK` is equivalent to
	 *      copying senders' permissions (role) to the user
	 * @dev Requires transaction sender to have `ROLE_ACCESS_MANAGER` permission
	 *
	 * @param operator address of a user to alter permissions for,
	 *       or self address to alter global features of the smart contract
	 * @param role bitmask representing a set of permissions to
	 *      enable/disable for a user specified
	 */
	function updateRole(address operator, uint256 role) public {
		// caller must have a permission to update user roles
		require(isSenderInRole(ROLE_ACCESS_MANAGER), "access denied");

		// evaluate the role and reassign it
		__setRole(operator, role, _evaluateBy(msg.sender, getRole(operator), role));
	}

	/**
	 * @notice Determines the permission bitmask an operator can set on the
	 *      target permission set
	 * @notice Used to calculate the permission bitmask to be set when requested
	 *     in `updateRole` and `updateFeatures` functions
	 *
	 * @dev Calculated based on:
	 *      1) operator's own permission set read from userRoles[operator]
	 *      2) target permission set - what is already set on the target
	 *      3) desired permission set - what do we want set target to
	 *
	 * @dev Corner cases:
	 *      1) Operator is super admin and its permission set is `FULL_PRIVILEGES_MASK`:
	 *        `desired` bitset is returned regardless of the `target` permission set value
	 *        (what operator sets is what they get)
	 *      2) Operator with no permissions (zero bitset):
	 *        `target` bitset is returned regardless of the `desired` value
	 *        (operator has no authority and cannot modify anything)
	 *
	 * @dev Example:
	 *      Consider an operator with the permissions bitmask     00001111
	 *      is about to modify the target permission set          01010101
	 *      Operator wants to set that permission set to          00110011
	 *      Based on their role, an operator has the permissions
	 *      to update only lowest 4 bits on the target, meaning that
	 *      high 4 bits of the target set in this example is left
	 *      unchanged and low 4 bits get changed as desired:      01010011
	 *
	 * @param operator address of the contract operator which is about to set the permissions
	 * @param target input set of permissions to operator is going to modify
	 * @param desired desired set of permissions operator would like to set
	 * @return resulting set of permissions given operator will set
	 */
	function _evaluateBy(address operator, uint256 target, uint256 desired) internal view returns (uint256) {
		// read operator's permissions
		uint256 p = getRole(operator);

		// taking into account operator's permissions,
		// 1) enable the permissions desired on the `target`
		target |= p & desired;
		// 2) disable the permissions desired on the `target`
		target &= FULL_PRIVILEGES_MASK ^ (p & (FULL_PRIVILEGES_MASK ^ desired));

		// return calculated result
		return target;
	}

	/**
	 * @notice Checks if requested set of features is enabled globally on the contract
	 *
	 * @param required set of features to check against
	 * @return true if all the features requested are enabled, false otherwise
	 */
	function isFeatureEnabled(uint256 required) public view returns (bool) {
		// delegate call to `__hasRole`, passing `features` property
		return __hasRole(features(), required);
	}

	/**
	 * @notice Checks if transaction sender `msg.sender` has all the permissions required
	 *
	 * @dev Used in smart contracts only. Off-chain clients should use `isOperatorInRole`.
	 *
	 * @param required set of permissions (role) to check against
	 * @return true if all the permissions requested are enabled, false otherwise
	 */
	function isSenderInRole(uint256 required) public view returns (bool) {
		// delegate call to `isOperatorInRole`, passing transaction sender
		return isOperatorInRole(msg.sender, required);
	}

	/**
	 * @notice Checks if operator has all the permissions (role) required
	 *
	 * @param operator address of the user to check role for
	 * @param required set of permissions (role) to check
	 * @return true if all the permissions requested are enabled, false otherwise
	 */
	function isOperatorInRole(address operator, uint256 required) public view returns (bool) {
		// delegate call to `__hasRole`, passing operator's permissions (role)
		return __hasRole(getRole(operator), required);
	}

	/**
	 * @dev Sets the `assignedRole` role to the operator, logs both `requestedRole` and `actualRole`
	 *
	 * @dev Unsafe:
	 *      provides direct write access to `userRoles` mapping without any security checks,
	 *      doesn't verify the executor (msg.sender) permissions,
	 *      must be kept private at all times
	 *
	 * @param operator address of a user to alter permissions for,
	 *       or self address to alter global features of the smart contract
	 * @param requestedRole bitmask representing a set of permissions requested
	 *      to be enabled/disabled for a user specified, used only to be logged into event
	 * @param assignedRole bitmask representing a set of permissions to
	 *      enable/disable for a user specified, used to update the mapping and to be logged into event
	 */
	function __setRole(address operator, uint256 requestedRole, uint256 assignedRole) private {
		// assign the role to the operator
		userRoles[operator] = assignedRole;

		// fire an event
		emit RoleUpdated(operator, requestedRole, assignedRole);
	}

	/**
	 * @dev Checks if role `actual` contains all the permissions required `required`
	 *
	 * @param actual existent role
	 * @param required required role
	 * @return true if actual has required role (all permissions), false otherwise
	 */
	function __hasRole(uint256 actual, uint256 required) private pure returns (bool) {
		// check the bitmask for the role required and return the result
		return actual & required == required;
	}
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/**
 * @notice Replaces built-in Solidity address.transfer and address.send functions
 *      with the address.call function
 */
library Transfers {
	/// @dev Mimics address.send forwarding 4,900 gas
	function send(address payable to, uint256 value) internal returns(bool) {
		(bool success, ) = to.call{gas: 4900, value: value}("");
		return success;
	}

	/// @dev Mimics address.transfer forwarding 4,900 gas
	function transfer(address payable to, uint256 value) internal {
		require(send(to, value), "failed to send ether");
	}

	/// @dev Alias for `send`
	function send1(address payable to, uint256 value) internal returns(bool) {
		return send(to, value);
	}

	/// @dev Alias for `transfer`
	function transfer1(address payable to, uint256 value) internal {
		transfer(to, value);
	}
}

Settings
{
  "evmVersion": "london",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_sharesContractAddress","type":"address"},{"internalType":"address","name":"_paymentToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"FeeReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"holder","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"name":"RewardClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"uint256","name":"requested","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assigned","type":"uint256"}],"name":"RoleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"trader","type":"address"},{"indexed":true,"internalType":"bool","name":"isBuy","type":"bool"},{"indexed":false,"internalType":"uint256","name":"sharesAmount","type":"uint256"}],"name":"SharesTraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"ROLE_ACCESS_MANAGER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_UPGRADE_MANAGER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accRewardPerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimTheReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"features","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPaymentToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"getRole","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_sharesContractAddress","type":"address"}],"name":"initializeSharesContractAddressIfRequired","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"required","type":"uint256"}],"name":"isFeatureEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"isOperatorInRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"required","type":"uint256"}],"name":"isSenderInRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTransferReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"holder","type":"address"}],"name":"pendingReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_sharesContractAddress","type":"address"},{"internalType":"address","name":"_paymentToken","type":"address"}],"name":"postConstruct","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sharesContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mask","type":"uint256"}],"name":"updateFeatures","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"role","type":"uint256"}],"name":"updateRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"},{"internalType":"uint256","name":"claimedAmount","type":"uint256"},{"internalType":"uint256","name":"unclaimedAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60806040523480156200001157600080fd5b50604051620018503803806200185083398101604081905262000034916200030c565b600054610100900460ff16620000515760005460ff16156200005b565b6200005b62000100565b620000b35760405162461bcd60e51b815260206004820152602e60248201526000805160206200183083398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b600054610100900460ff16158015620000d6576000805461ffff19166101011790555b620000e38484846200011e565b8015620000f6576000805461ff00191690555b5050505062000356565b600062000118306200021060201b62000b481760201c565b15905090565b600054610100900460ff166200013b5760005460ff161562000145565b6200014562000100565b620001995760405162461bcd60e51b815260206004820152602e60248201526000805160206200183083398151915260448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620000aa565b600054610100900460ff16158015620001bc576000805461ffff19166101011790555b620001c78462000216565b603480546001600160a01b038086166001600160a01b031992831617909255603380549285169290911691909117905580156200020a576000805461ff00191690555b50505050565b3b151590565b600054610100900460ff16620002835760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000aa565b62000292816000198062000295565b50565b6001600160a01b03831660008181526001602090815260409182902084905581518581529081018490527fe9be537308880e0f56b7d7cfd7abf85f14c4934486d138f848b92a0cbaf659b4910160405180910390a2505050565b80516001600160a01b03811681146200030757600080fd5b919050565b6000806000606084860312156200032257600080fd5b6200032d84620002ef565b92506200033d60208501620002ef565b91506200034d60408501620002ef565b90509250925092565b6114ca80620003666000396000f3fe6080604052600436106101185760003560e01c8063ae60bda4116100a0578063d7380ea611610064578063d7380ea61461046e578063e023fd4214610483578063e7db4d81146104a3578063f40f0f52146104c3578063fcc2c078146104e35761016a565b8063ae60bda4146103cc578063ae682e2e146103e4578063c688d693146103fc578063d41c3a651461041c578063d5bb7f671461044e5761016a565b8063725f3626116100e7578063725f36261461030d57806388a7ca5c1461033d578063939d6237146103765780639ba81bed1461038c578063ae5b102e146103ac5761016a565b80631959a0021461022e5780632b521416146102955780633a98ef39146102c157806344276733146102d75761016a565b3661016a576033546001600160a01b03161561014f5760405162461bcd60e51b8152600401610146906111aa565b60405180910390fd5b6101683460405180602001604052806000815250610503565b005b6033546001600160a01b0316156101c35760405162461bcd60e51b815260206004820152601d60248201527f6e6f7420616e2045544820726577617264206469737472696275746f720000006044820152606401610146565b6034546001600160a01b031633146101ed5760405162461bcd60e51b8152600401610146906111aa565b610168346000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061050392505050565b34801561023a57600080fd5b506102706102493660046111e4565b60376020526000908152604090208054600182015460028301546003909301549192909184565b6040805194855260208501939093529183015260608201526080015b60405180910390f35b3480156102a157600080fd5b50306000908152600160205260409020545b60405190815260200161028c565b3480156102cd57600080fd5b506102b360365481565b3480156102e357600080fd5b506102b36102f23660046111e4565b6001600160a01b031660009081526001602052604090205490565b34801561031957600080fd5b5061032d610328366004611201565b610525565b604051901515815260200161028c565b34801561034957600080fd5b5061035d610358366004611230565b610547565b6040516001600160e01b0319909116815260200161028c565b34801561038257600080fd5b506102b360355481565b34801561039857600080fd5b506101686103a73660046111e4565b6105ec565b3480156103b857600080fd5b506101686103c7366004611310565b610671565b3480156103d857600080fd5b506102b3600160fe1b81565b3480156103f057600080fd5b506102b3600160ff1b81565b34801561040857600080fd5b5061032d610417366004611310565b610716565b34801561042857600080fd5b506033546001600160a01b03165b6040516001600160a01b03909116815260200161028c565b34801561045a57600080fd5b50610168610469366004611201565b61073f565b34801561047a57600080fd5b5061016861074c565b34801561048f57600080fd5b5061016861049e36600461133c565b6108c9565b3480156104af57600080fd5b50603454610436906001600160a01b031681565b3480156104cf57600080fd5b506102b36104de3660046111e4565b6109be565b3480156104ef57600080fd5b5061032d6104fe366004611201565b610b3c565b60365460000361051b576105178282610b4e565b5050565b6105178282610cc4565b30600090815260016020526040812054610541905b8316831490565b92915050565b6033546000906001600160a01b031633146105a45760405162461bcd60e51b815260206004820152601f60248201527f7265636569766564206576656e742066726f6d2077726f6e6720746f6b656e006044820152606401610146565b6034546001600160a01b038681169116146105d15760405162461bcd60e51b8152600401610146906111aa565b6105db8383610503565b50632229f29760e21b949350505050565b6034546001600160a01b031615801561060d57506001600160a01b03811615155b61064f5760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610146565b603480546001600160a01b0319166001600160a01b0392909216919091179055565b61067e600160ff1b610b3c565b6106ba5760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610146565b6105178282610711336106e2876001600160a01b031660009081526001602052604090205490565b6001600160a01b0391909116600090815260016020526040902054600019808818821618908716919091171690565b610da0565b6001600160a01b0382166000908152600160205260408120546107389061053a565b9392505050565b6107493082610671565b50565b6000610757336109be565b90506000811161079c5760405162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b6044820152606401610146565b33600090815260376020526040812060038101829055600281018054919284926107c790849061139d565b90915550506035548154670de0b6b3a7640000916107e4916113b5565b6107ee91906113d4565b60018201556033546001600160a01b03166108125761080d3383610dfa565b610890565b60335460405163a9059cbb60e01b8152336004820152602481018490526001600160a01b039091169063a9059cbb906044016020604051808303816000875af1158015610863573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610887919061140b565b61089057600080fd5b60405182815233907f106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f72419060200160405180910390a25050565b600054610100900460ff166108e45760005460ff16156108e8565b303b155b61094b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610146565b600054610100900460ff1615801561096d576000805461ffff19166101011790555b61097684610e47565b603480546001600160a01b038086166001600160a01b031992831617909255603380549285169290911691909117905580156109b8576000805461ff00191690555b50505050565b6001600160a01b03811660009081526037602090815260408083208151608081018352815480825260018301549482018590526002830154938201939093526003909101546060820152603554909284929091670de0b6b3a764000091610a2591906113b5565b610a2f91906113d4565b8360600151610a3e919061139d565b610a489190611426565b6033549091506000906001600160a01b031615610ad0576033546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610aa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610acb919061143d565b610ad2565b475b9050610ae281633b9aca0061139d565b8210610b245760405162461bcd60e51b81526020600482015260116024820152703234b9b1b932b830b731bc9032b93937b960791b6044820152606401610146565b808211610b315781610b33565b805b95945050505050565b60006105413383610716565b3b151590565b8051600003610b975760405162461bcd60e51b81526020600482015260156024820152741cde5b98c81b595cdcd859d948195e1c1958dd1959605a1b6044820152606401610146565b8051606014610be15760405162461bcd60e51b81526020600482015260166024820152756d616c666f726d65642073796e63206d65737361676560501b6044820152606401610146565b600080600083806020019051810190610bfa9190611456565b925092509250818015610c0e575060018110155b610c4a5760405162461bcd60e51b815260206004820152600d60248201526c696e76616c696420737461746560981b6044820152606401610146565b610c55836001610ebf565b6001811115610c7b57610c6785610f96565b610c7b83610c76600184611426565b610ebf565b6040518181526001906001600160a01b038516907fbd737de9fda35bf54b4f4a52ea425f0d646b85bafdc736be7fd40cc50dd9ed92906020015b60405180910390a35050505050565b610ccd82610f96565b8051600003610cda575050565b8051606014610d245760405162461bcd60e51b81526020600482015260166024820152756d616c666f726d65642073796e63206d65737361676560501b6044820152606401610146565b600080600083806020019051810190610d3d9190611456565b9250925092508115610d5857610d538382610ebf565b610d62565b610d628382611016565b811515836001600160a01b03167fbd737de9fda35bf54b4f4a52ea425f0d646b85bafdc736be7fd40cc50dd9ed9283604051610cb591815260200190565b6001600160a01b03831660008181526001602090815260409182902084905581518581529081018490527fe9be537308880e0f56b7d7cfd7abf85f14c4934486d138f848b92a0cbaf659b4910160405180910390a2505050565b610e048282611148565b6105175760405162461bcd60e51b81526020600482015260146024820152733330b4b632b2103a379039b2b7321032ba3432b960611b6044820152606401610146565b600054610100900460ff16610eb25760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610146565b6107498160001980610da0565b6001600160a01b0382166000908152603760205260409020805415610f385760008160010154670de0b6b3a76400006035548460000154610f0091906113b5565b610f0a91906113d4565b610f149190611426565b90508015610f365780826003016000828254610f30919061139d565b90915550505b505b81816000016000828254610f4c919061139d565b925050819055508160366000828254610f65919061139d565b90915550506035548154670de0b6b3a764000091610f82916113b5565b610f8c91906113d4565b6001909101555050565b801580610fa35750603654155b15610fab5750565b603654610fc082670de0b6b3a76400006113b5565b610fca91906113d4565b60356000828254610fdb919061139d565b90915550506040518181527f86c46efee0a638b418fa0952cd587c78b75b8bc989e7a7c13a86d448ec34a0849060200160405180910390a150565b6001600160a01b03821660009081526037602052604090205481111561108a5760405162461bcd60e51b815260206004820152602360248201527f616d6f756e74206d757374206265203c3d207265676973746572656420616d6f6044820152621d5b9d60ea1b6064820152608401610146565b6001600160a01b038216600090815260376020526040812060018101546035548254929392670de0b6b3a7640000916110c2916113b5565b6110cc91906113d4565b6110d69190611426565b905080156110f857808260030160008282546110f2919061139d565b90915550505b8154611105908490611426565b8255603654611115908490611426565b6036556035548254670de0b6b3a764000091611130916113b5565b61113a91906113d4565b826001018190555050505050565b600080836001600160a01b031661132484604051600060405180830381858888f193505050503d806000811461119a576040519150601f19603f3d011682016040523d82523d6000602084013e61119f565b606091505b509095945050505050565b6020808252600b908201526a1b9bdd08185b1b1bddd95960aa1b604082015260600190565b6001600160a01b038116811461074957600080fd5b6000602082840312156111f657600080fd5b8135610738816111cf565b60006020828403121561121357600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561124657600080fd5b8435611251816111cf565b93506020850135611261816111cf565b925060408501359150606085013567ffffffffffffffff8082111561128557600080fd5b818701915087601f83011261129957600080fd5b8135818111156112ab576112ab61121a565b604051601f8201601f19908116603f011681019083821181831017156112d3576112d361121a565b816040528281528a60208487010111156112ec57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561132357600080fd5b823561132e816111cf565b946020939093013593505050565b60008060006060848603121561135157600080fd5b833561135c816111cf565b9250602084013561136c816111cf565b9150604084013561137c816111cf565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b600082198211156113b0576113b0611387565b500190565b60008160001904831182151516156113cf576113cf611387565b500290565b6000826113f157634e487b7160e01b600052601260045260246000fd5b500490565b8051801515811461140657600080fd5b919050565b60006020828403121561141d57600080fd5b610738826113f6565b60008282101561143857611438611387565b500390565b60006020828403121561144f57600080fd5b5051919050565b60008060006060848603121561146b57600080fd5b8351611476816111cf565b9250611484602085016113f6565b915060408401519050925092509256fea264697066735822122036feda829a13929b76cc8895119347a0e3d1ac17b0ed9ee943ba44c0833e727364736f6c634300080f0033496e697469616c697a61626c653a20636f6e747261637420697320616c726561000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106101185760003560e01c8063ae60bda4116100a0578063d7380ea611610064578063d7380ea61461046e578063e023fd4214610483578063e7db4d81146104a3578063f40f0f52146104c3578063fcc2c078146104e35761016a565b8063ae60bda4146103cc578063ae682e2e146103e4578063c688d693146103fc578063d41c3a651461041c578063d5bb7f671461044e5761016a565b8063725f3626116100e7578063725f36261461030d57806388a7ca5c1461033d578063939d6237146103765780639ba81bed1461038c578063ae5b102e146103ac5761016a565b80631959a0021461022e5780632b521416146102955780633a98ef39146102c157806344276733146102d75761016a565b3661016a576033546001600160a01b03161561014f5760405162461bcd60e51b8152600401610146906111aa565b60405180910390fd5b6101683460405180602001604052806000815250610503565b005b6033546001600160a01b0316156101c35760405162461bcd60e51b815260206004820152601d60248201527f6e6f7420616e2045544820726577617264206469737472696275746f720000006044820152606401610146565b6034546001600160a01b031633146101ed5760405162461bcd60e51b8152600401610146906111aa565b610168346000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061050392505050565b34801561023a57600080fd5b506102706102493660046111e4565b60376020526000908152604090208054600182015460028301546003909301549192909184565b6040805194855260208501939093529183015260608201526080015b60405180910390f35b3480156102a157600080fd5b50306000908152600160205260409020545b60405190815260200161028c565b3480156102cd57600080fd5b506102b360365481565b3480156102e357600080fd5b506102b36102f23660046111e4565b6001600160a01b031660009081526001602052604090205490565b34801561031957600080fd5b5061032d610328366004611201565b610525565b604051901515815260200161028c565b34801561034957600080fd5b5061035d610358366004611230565b610547565b6040516001600160e01b0319909116815260200161028c565b34801561038257600080fd5b506102b360355481565b34801561039857600080fd5b506101686103a73660046111e4565b6105ec565b3480156103b857600080fd5b506101686103c7366004611310565b610671565b3480156103d857600080fd5b506102b3600160fe1b81565b3480156103f057600080fd5b506102b3600160ff1b81565b34801561040857600080fd5b5061032d610417366004611310565b610716565b34801561042857600080fd5b506033546001600160a01b03165b6040516001600160a01b03909116815260200161028c565b34801561045a57600080fd5b50610168610469366004611201565b61073f565b34801561047a57600080fd5b5061016861074c565b34801561048f57600080fd5b5061016861049e36600461133c565b6108c9565b3480156104af57600080fd5b50603454610436906001600160a01b031681565b3480156104cf57600080fd5b506102b36104de3660046111e4565b6109be565b3480156104ef57600080fd5b5061032d6104fe366004611201565b610b3c565b60365460000361051b576105178282610b4e565b5050565b6105178282610cc4565b30600090815260016020526040812054610541905b8316831490565b92915050565b6033546000906001600160a01b031633146105a45760405162461bcd60e51b815260206004820152601f60248201527f7265636569766564206576656e742066726f6d2077726f6e6720746f6b656e006044820152606401610146565b6034546001600160a01b038681169116146105d15760405162461bcd60e51b8152600401610146906111aa565b6105db8383610503565b50632229f29760e21b949350505050565b6034546001600160a01b031615801561060d57506001600160a01b03811615155b61064f5760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610146565b603480546001600160a01b0319166001600160a01b0392909216919091179055565b61067e600160ff1b610b3c565b6106ba5760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610146565b6105178282610711336106e2876001600160a01b031660009081526001602052604090205490565b6001600160a01b0391909116600090815260016020526040902054600019808818821618908716919091171690565b610da0565b6001600160a01b0382166000908152600160205260408120546107389061053a565b9392505050565b6107493082610671565b50565b6000610757336109be565b90506000811161079c5760405162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b6044820152606401610146565b33600090815260376020526040812060038101829055600281018054919284926107c790849061139d565b90915550506035548154670de0b6b3a7640000916107e4916113b5565b6107ee91906113d4565b60018201556033546001600160a01b03166108125761080d3383610dfa565b610890565b60335460405163a9059cbb60e01b8152336004820152602481018490526001600160a01b039091169063a9059cbb906044016020604051808303816000875af1158015610863573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610887919061140b565b61089057600080fd5b60405182815233907f106f923f993c2149d49b4255ff723acafa1f2d94393f561d3eda32ae348f72419060200160405180910390a25050565b600054610100900460ff166108e45760005460ff16156108e8565b303b155b61094b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610146565b600054610100900460ff1615801561096d576000805461ffff19166101011790555b61097684610e47565b603480546001600160a01b038086166001600160a01b031992831617909255603380549285169290911691909117905580156109b8576000805461ff00191690555b50505050565b6001600160a01b03811660009081526037602090815260408083208151608081018352815480825260018301549482018590526002830154938201939093526003909101546060820152603554909284929091670de0b6b3a764000091610a2591906113b5565b610a2f91906113d4565b8360600151610a3e919061139d565b610a489190611426565b6033549091506000906001600160a01b031615610ad0576033546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015610aa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610acb919061143d565b610ad2565b475b9050610ae281633b9aca0061139d565b8210610b245760405162461bcd60e51b81526020600482015260116024820152703234b9b1b932b830b731bc9032b93937b960791b6044820152606401610146565b808211610b315781610b33565b805b95945050505050565b60006105413383610716565b3b151590565b8051600003610b975760405162461bcd60e51b81526020600482015260156024820152741cde5b98c81b595cdcd859d948195e1c1958dd1959605a1b6044820152606401610146565b8051606014610be15760405162461bcd60e51b81526020600482015260166024820152756d616c666f726d65642073796e63206d65737361676560501b6044820152606401610146565b600080600083806020019051810190610bfa9190611456565b925092509250818015610c0e575060018110155b610c4a5760405162461bcd60e51b815260206004820152600d60248201526c696e76616c696420737461746560981b6044820152606401610146565b610c55836001610ebf565b6001811115610c7b57610c6785610f96565b610c7b83610c76600184611426565b610ebf565b6040518181526001906001600160a01b038516907fbd737de9fda35bf54b4f4a52ea425f0d646b85bafdc736be7fd40cc50dd9ed92906020015b60405180910390a35050505050565b610ccd82610f96565b8051600003610cda575050565b8051606014610d245760405162461bcd60e51b81526020600482015260166024820152756d616c666f726d65642073796e63206d65737361676560501b6044820152606401610146565b600080600083806020019051810190610d3d9190611456565b9250925092508115610d5857610d538382610ebf565b610d62565b610d628382611016565b811515836001600160a01b03167fbd737de9fda35bf54b4f4a52ea425f0d646b85bafdc736be7fd40cc50dd9ed9283604051610cb591815260200190565b6001600160a01b03831660008181526001602090815260409182902084905581518581529081018490527fe9be537308880e0f56b7d7cfd7abf85f14c4934486d138f848b92a0cbaf659b4910160405180910390a2505050565b610e048282611148565b6105175760405162461bcd60e51b81526020600482015260146024820152733330b4b632b2103a379039b2b7321032ba3432b960611b6044820152606401610146565b600054610100900460ff16610eb25760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610146565b6107498160001980610da0565b6001600160a01b0382166000908152603760205260409020805415610f385760008160010154670de0b6b3a76400006035548460000154610f0091906113b5565b610f0a91906113d4565b610f149190611426565b90508015610f365780826003016000828254610f30919061139d565b90915550505b505b81816000016000828254610f4c919061139d565b925050819055508160366000828254610f65919061139d565b90915550506035548154670de0b6b3a764000091610f82916113b5565b610f8c91906113d4565b6001909101555050565b801580610fa35750603654155b15610fab5750565b603654610fc082670de0b6b3a76400006113b5565b610fca91906113d4565b60356000828254610fdb919061139d565b90915550506040518181527f86c46efee0a638b418fa0952cd587c78b75b8bc989e7a7c13a86d448ec34a0849060200160405180910390a150565b6001600160a01b03821660009081526037602052604090205481111561108a5760405162461bcd60e51b815260206004820152602360248201527f616d6f756e74206d757374206265203c3d207265676973746572656420616d6f6044820152621d5b9d60ea1b6064820152608401610146565b6001600160a01b038216600090815260376020526040812060018101546035548254929392670de0b6b3a7640000916110c2916113b5565b6110cc91906113d4565b6110d69190611426565b905080156110f857808260030160008282546110f2919061139d565b90915550505b8154611105908490611426565b8255603654611115908490611426565b6036556035548254670de0b6b3a764000091611130916113b5565b61113a91906113d4565b826001018190555050505050565b600080836001600160a01b031661132484604051600060405180830381858888f193505050503d806000811461119a576040519150601f19603f3d011682016040523d82523d6000602084013e61119f565b606091505b509095945050505050565b6020808252600b908201526a1b9bdd08185b1b1bddd95960aa1b604082015260600190565b6001600160a01b038116811461074957600080fd5b6000602082840312156111f657600080fd5b8135610738816111cf565b60006020828403121561121357600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561124657600080fd5b8435611251816111cf565b93506020850135611261816111cf565b925060408501359150606085013567ffffffffffffffff8082111561128557600080fd5b818701915087601f83011261129957600080fd5b8135818111156112ab576112ab61121a565b604051601f8201601f19908116603f011681019083821181831017156112d3576112d361121a565b816040528281528a60208487010111156112ec57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561132357600080fd5b823561132e816111cf565b946020939093013593505050565b60008060006060848603121561135157600080fd5b833561135c816111cf565b9250602084013561136c816111cf565b9150604084013561137c816111cf565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b600082198211156113b0576113b0611387565b500190565b60008160001904831182151516156113cf576113cf611387565b500290565b6000826113f157634e487b7160e01b600052601260045260246000fd5b500490565b8051801515811461140657600080fd5b919050565b60006020828403121561141d57600080fd5b610738826113f6565b60008282101561143857611438611387565b500390565b60006020828403121561144f57600080fd5b5051919050565b60008060006060848603121561146b57600080fd5b8351611476816111cf565b9250611484602085016113f6565b915060408401519050925092509256fea264697066735822122036feda829a13929b76cc8895119347a0e3d1ac17b0ed9ee943ba44c0833e727364736f6c634300080f0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _owner (address): 0x0000000000000000000000000000000000000000
Arg [1] : _sharesContractAddress (address): 0x0000000000000000000000000000000000000000
Arg [2] : _paymentToken (address): 0x0000000000000000000000000000000000000000

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.