Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
FeeSettings
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.23; import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/metatx/ERC2771ContextUpgradeable.sol"; import "./interfaces/IFeeSettings.sol"; /** * @title FeeSettings * @author malteish, cjentzsch * @notice The FeeSettings contract is used to manage fees paid to the tokenize.it platfom */ contract FeeSettings is Ownable2StepUpgradeable, ERC165Upgradeable, ERC2771ContextUpgradeable, IFeeSettingsV2, IFeeSettingsV1 { /// max token fee is 5% uint32 public constant MAX_TOKEN_FEE_NUMERATOR = 500; /// max crowdinvesting fee is 10% uint32 public constant MAX_CROWDINVESTING_FEE_NUMERATOR = 1000; /// max private offer fee is 5% uint32 public constant MAX_PRIVATE_OFFER_FEE_NUMERATOR = 500; /// Denominator to calculate all fees uint32 public constant FEE_DENOMINATOR = 10000; /** * special fees for specific customers. If a customer has a custom fee, the custom * fee is used instead of the default fee. * Custom fees can only reduce the fee, not increase it. * The key is the customer's token address, e.g. customers are identified by their token. * The `time` field is the time up to which the custom fee is valid. * Afterwards, standard fees are used. */ mapping(address => Fees) public fees; /** * if `tokenFeeCollectors[tokenAddress]` is 0x0, the fees must be paid to `tokenFeeCollectors[address(0)]` * otherwise, the fees must be paid to `tokenFeeCollectors[tokenAddress]` */ mapping(address => address) public tokenFeeCollectors; /** * if `crowdinvestingFeeCollectors[tokenAddress]` is 0x0, the fees must be paid to `crowdinvestingFeeCollectors[address(0)]` * otherwise, the fees must be paid to `crowdinvestingFeeCollectors[tokenAddress]` */ mapping(address => address) public crowdinvestingFeeCollectors; /** * if `privateOfferFeeCollectors[tokenAddress]` is 0x0, the fees must be paid to `privateOfferFeeCollectors[address(0)]` * otherwise, the fees must be paid to `privateOfferFeeCollectors[tokenAddress]` */ mapping(address => address) public privateOfferFeeCollectors; /// new fee settings that can be activated (after a delay in case of fee increase) Fees public proposedDefaultFees; /// stores who is a manager. Managers can change fees and fee collectors for specific tokens mapping(address => bool) public managers; /** * @notice Default fees have been changed * @param tokenFeeNumerator a in fraction a/b that defines the fee paid in Token: fee = amount * a / b * @param crowdinvestingFeeNumerator a in fraction a/b that defines the fee paid in currency for crowdinvesting: fee = amount * a / b * @param privateOfferFeeNumerator a in fraction a/b that defines the fee paid in currency for private offers: fee = amount * a / b */ event SetFee(uint32 tokenFeeNumerator, uint32 crowdinvestingFeeNumerator, uint32 privateOfferFeeNumerator); /** * @notice Default fees have been changed * @param tokenFeeNumerator a in fraction a/b that defines the fee paid in Token: fee = amount * a / b * @param crowdinvestingFeeNumerator a in fraction a/b that defines the fee paid in currency for crowdinvesting: fee = amount * a / b * @param privateOfferFeeNumerator a in fraction a/b that defines the fee paid in currency for private offers: fee = amount * a / b * @param time The time when the custom fee expires */ event SetCustomFee( address indexed token, uint32 tokenFeeNumerator, uint32 crowdinvestingFeeNumerator, uint32 privateOfferFeeNumerator, uint256 time ); /// custom fee settings for the given token have been removed event RemoveCustomFee(address indexed token); /// token fees for `token` must now be paid to `feeCollector` event SetCustomTokenFeeCollector(address indexed token, address indexed feeCollector); /// crowdinvesting fees for `token` must now be paid to `feeCollector` event SetCustomCrowdinvestingFeeCollector(address indexed token, address indexed feeCollector); /// private offer fees for `token` must now be paid to `feeCollector` event SetCustomPrivateOfferFeeCollector(address indexed token, address indexed feeCollector); /// token fees for `token` must now be paid to the default fee collector event RemoveCustomTokenFeeCollector(address indexed token); /// crowdinvesting fees for `token` must now be paid to the default fee collector event RemoveCustomCrowdinvestingFeeCollector(address indexed token); /// private offer fees for `token` must now be paid to the default fee collector event RemoveCustomPrivateOfferFeeCollector(address indexed token); /** * @notice The fee collectors have changed * @param newTokenFeeCollector The new fee collector for token fees * @param newCrowdinvestingFeeCollector The new fee collector for crowdinvesting fees * @param newPrivateOfferFeeCollector The new fee collector for private offer fees */ event FeeCollectorsChanged( address indexed newTokenFeeCollector, address indexed newCrowdinvestingFeeCollector, address indexed newPrivateOfferFeeCollector ); /** * @notice A fee change has been proposed * @param proposal The new fee settings that have been proposed */ event ChangeProposed(Fees proposal); /** * This constructor deploys a logic contract with no owner, that can be used for cloning. * @param _trustedForwarder The trusted forwarder contract to use */ constructor(address _trustedForwarder) ERC2771ContextUpgradeable(_trustedForwarder) { _disableInitializers(); } /** * @notice Initializes the contract with the given fee denominators and fee collector * @param _fees The initial fee denominators * @param _tokenFeeCollector The initial fee collector * @param _crowdinvestingFeeCollector The initial crowdinvesting fee collector * @param _privateOfferFeeCollector The initial private offer fee collector */ function initialize( address _owner, Fees memory _fees, address _tokenFeeCollector, address _crowdinvestingFeeCollector, address _privateOfferFeeCollector ) external initializer { require(_owner != address(0), "owner can not be zero address"); managers[_owner] = true; _transferOwnership(_owner); checkFeeLimits(_fees); fees[address(0)] = _fees; require(_tokenFeeCollector != address(0), "Fee collector cannot be 0x0"); tokenFeeCollectors[address(0)] = _tokenFeeCollector; require(_crowdinvestingFeeCollector != address(0), "Fee collector cannot be 0x0"); crowdinvestingFeeCollectors[address(0)] = _crowdinvestingFeeCollector; require(_privateOfferFeeCollector != address(0), "Fee collector cannot be 0x0"); privateOfferFeeCollectors[address(0)] = _privateOfferFeeCollector; } /** * @notice Adds a manager * @param _manager The manager to add */ function addManager(address _manager) external onlyOwner { managers[_manager] = true; } /** * @notice Removes a manager * @param _manager The manager to remove */ function removeManager(address _manager) external onlyOwner { delete managers[_manager]; } /** * @notice Prepares a fee change. Fee increases are subject to a minimum delay of 12 weeks, while fee reductions can be executed immediately. * @dev reducing fees = increasing the denominator * @param _fees The new fee denominators */ function planFeeChange(Fees memory _fees) external onlyOwner { checkFeeLimits(_fees); // if at least one fee increases, enforce minimum delay if ( _fees.tokenFeeNumerator > fees[address(0)].tokenFeeNumerator || _fees.crowdinvestingFeeNumerator > fees[address(0)].crowdinvestingFeeNumerator || _fees.privateOfferFeeNumerator > fees[address(0)].privateOfferFeeNumerator ) { require( _fees.validityDate > block.timestamp + 12 weeks, "Fee change must be at least 12 weeks in the future" ); } proposedDefaultFees = _fees; emit ChangeProposed(_fees); } /** * @notice Executes a fee change that has been planned before */ function executeFeeChange() external onlyOwner { require( block.timestamp >= proposedDefaultFees.validityDate, "Fee change must be executed after the change time" ); fees[address(0)] = proposedDefaultFees; emit SetFee( proposedDefaultFees.tokenFeeNumerator, proposedDefaultFees.crowdinvestingFeeNumerator, proposedDefaultFees.privateOfferFeeNumerator ); delete proposedDefaultFees; } /** * @notice Sets a new fee collector * @param _tokenFeeCollector The new fee collector */ function setFeeCollectors( address _tokenFeeCollector, address _crowdinvestingFeeCollector, address _personalOfferFeeCollector ) external onlyOwner { require(_tokenFeeCollector != address(0), "Fee collector cannot be 0x0"); tokenFeeCollectors[address(0)] = _tokenFeeCollector; require(_crowdinvestingFeeCollector != address(0), "Fee collector cannot be 0x0"); crowdinvestingFeeCollectors[address(0)] = _crowdinvestingFeeCollector; require(_personalOfferFeeCollector != address(0), "Fee collector cannot be 0x0"); privateOfferFeeCollectors[address(0)] = _personalOfferFeeCollector; emit FeeCollectorsChanged(_tokenFeeCollector, _crowdinvestingFeeCollector, _personalOfferFeeCollector); } /** * @notice Checks if the given fee settings are valid * @param _fees The fees to check */ function checkFeeLimits(Fees memory _fees) internal pure { require(_fees.tokenFeeNumerator <= MAX_TOKEN_FEE_NUMERATOR, "Token fee must be <= 5%"); require( _fees.crowdinvestingFeeNumerator <= MAX_CROWDINVESTING_FEE_NUMERATOR, "Crowdinvesting fee must be <= 10%" ); require(_fees.privateOfferFeeNumerator <= MAX_PRIVATE_OFFER_FEE_NUMERATOR, "PrivateOffer fee must be <= 5%"); } /** * @notice Sets a custom fee for a specific token * @param _token The token for which the custom fee should be set * @param _fees The custom fee */ function setCustomFee(address _token, Fees memory _fees) external onlyManager { checkFeeLimits(_fees); require(_token != address(0), "Token cannot be 0x0"); require(_fees.validityDate > block.timestamp, "Custom fee expiry time must be in the future"); fees[_token] = _fees; emit SetCustomFee( _token, _fees.tokenFeeNumerator, _fees.crowdinvestingFeeNumerator, _fees.privateOfferFeeNumerator, _fees.validityDate ); } /** * @notice removes a custom fee entry for a specific token * @param _token The token for which the custom fee should be removed */ function removeCustomFee(address _token) external onlyManager { require(_token != address(0), "Token cannot be 0x0"); delete fees[_token]; emit RemoveCustomFee(_token); } /** * set `_feeCollector` as the token fee collector for `_token` * @param _token the token for which the fee collector is set * @param _feeCollector the address that will receive the token fees */ function setCustomTokenFeeCollector(address _token, address _feeCollector) external onlyManager { require(_feeCollector != address(0), "Fee collector cannot be 0x0"); require(_token != address(0), "Token cannot be 0x0"); tokenFeeCollectors[_token] = _feeCollector; emit SetCustomTokenFeeCollector(_token, _feeCollector); } /** * set `_feeCollector` as the crowdinvesting fee collector for `_token` * @param _token the token for which the fee collector is set * @param _feeCollector the address that will receive the crowdinvesting fees */ function setCustomCrowdinvestingFeeCollector(address _token, address _feeCollector) external onlyManager { require(_feeCollector != address(0), "Fee collector cannot be 0x0"); require(_token != address(0), "Token cannot be 0x0"); crowdinvestingFeeCollectors[_token] = _feeCollector; emit SetCustomCrowdinvestingFeeCollector(_token, _feeCollector); } /** * set `_feeCollector` as the private offer fee collector for `_token` * @param _token the token for which the fee collector is set * @param _feeCollector the address that will receive the private offer fees */ function setCustomPrivateOfferFeeCollector(address _token, address _feeCollector) external onlyManager { require(_feeCollector != address(0), "Fee collector cannot be 0x0"); require(_token != address(0), "Token cannot be 0x0"); privateOfferFeeCollectors[_token] = _feeCollector; emit SetCustomPrivateOfferFeeCollector(_token, _feeCollector); } /** * Reset the token fee collector for `_token` to the default fee collector * @param _token the token for which the custom fee collector is removed */ function removeCustomTokenFeeCollector(address _token) external onlyManager { require(_token != address(0), "Token cannot be 0x0"); delete tokenFeeCollectors[_token]; emit RemoveCustomTokenFeeCollector(_token); } /** * Reset the crowdinvesting fee collector for `_token` to the default fee collector * @param _token the token for which the custom fee collector is removed */ function removeCustomCrowdinvestingFeeCollector(address _token) external onlyManager { require(_token != address(0), "Token cannot be 0x0"); delete crowdinvestingFeeCollectors[_token]; emit RemoveCustomCrowdinvestingFeeCollector(_token); } /** * Reset the private offer fee collector for `_token` to the default fee collector * @param _token the token for which the custom fee collector is removed */ function removeCustomPrivateOfferFeeCollector(address _token) external onlyManager { require(_token != address(0), "Token cannot be 0x0"); delete privateOfferFeeCollectors[_token]; emit RemoveCustomPrivateOfferFeeCollector(_token); } /** * @notice Returns the token fee collector for a given token * @param _token The token to return the token fee collector for * @return The fee collector */ function tokenFeeCollector(address _token) public view override(IFeeSettingsV2) returns (address) { if (tokenFeeCollectors[_token] != address(0)) { return tokenFeeCollectors[_token]; } return tokenFeeCollectors[address(0)]; } /** * @notice Returns the crowdinvesting fee collector for a given token * @param _token The token to return the crowdinvesting fee collector for * @return The fee collector */ function crowdinvestingFeeCollector(address _token) public view override(IFeeSettingsV2) returns (address) { if (crowdinvestingFeeCollectors[_token] != address(0)) { return crowdinvestingFeeCollectors[_token]; } return crowdinvestingFeeCollectors[address(0)]; } /** * @notice Returns the private offer fee collector for a given token * @param _token The token to return the private offer fee collector for * @return The fee collector */ function privateOfferFeeCollector(address _token) public view override(IFeeSettingsV2) returns (address) { if (privateOfferFeeCollectors[_token] != address(0)) { return privateOfferFeeCollectors[_token]; } return privateOfferFeeCollectors[address(0)]; } /** * General linear fee calculation function * @param amount how many erc20 tokens are transferred * @param numerator fee numerator */ function _fee(uint256 amount, uint32 numerator) internal pure returns (uint256) { return (amount * numerator) / FEE_DENOMINATOR; } /** * Calculates the fee for a given amount of tokens. * @param amount how many erc20 tokens are transferred * @param defaultNumerator default fee numerator * @param customNumerator custom fee numerator * @param customValidityDate custom fee validity date */ function _customFee( uint256 amount, uint32 defaultNumerator, uint32 customNumerator, uint64 customValidityDate ) internal view returns (uint256) { if (customValidityDate < uint64(block.timestamp)) { return _fee(amount, defaultNumerator); } uint256 defaultFee = _fee(amount, defaultNumerator); uint256 customFee = _fee(amount, customNumerator); if (customFee < defaultFee) { return customFee; } return defaultFee; } /** * calculates the token fee in tokens for the given token amount * @param _tokenAmount number of tokens that are minted * @param _token address of the token contract minting the tokens */ function tokenFee(uint256 _tokenAmount, address _token) public view override(IFeeSettingsV2) returns (uint256) { return _customFee( _tokenAmount, fees[address(0)].tokenFeeNumerator, fees[_token].tokenFeeNumerator, fees[_token].validityDate ); } /** * Calculates the fee for a given currency amount in Crowdinvesting (v5) or ContinuousFundraising (v4) * @param _currencyAmount how much currency is raised * @param _token the token that is sold through the crowdinvesting * @return the fee */ function crowdinvestingFee( uint256 _currencyAmount, address _token ) public view override(IFeeSettingsV2) returns (uint256) { return _customFee( _currencyAmount, fees[address(0)].crowdinvestingFeeNumerator, fees[_token].crowdinvestingFeeNumerator, fees[_token].validityDate ); } /** * Calculates the fee for a given currency amount in PrivateOffer (v5) or PersonalInvite (v4) * @param _currencyAmount how much currency is raised * @return the fee */ function privateOfferFee( uint256 _currencyAmount, address _token ) public view override(IFeeSettingsV2) returns (uint256) { return _customFee( _currencyAmount, fees[address(0)].privateOfferFeeNumerator, fees[_token].privateOfferFeeNumerator, fees[_token].validityDate ); } /** * @dev Specify where the implementation of owner() is located * @return The owner of the contract */ function owner() public view override(OwnableUpgradeable, IFeeSettingsV1, IFeeSettingsV2) returns (address) { return OwnableUpgradeable.owner(); } modifier onlyManager() { require(managers[_msgSender()], "Only managers can call this function"); _; } /** * @notice This contract implements the ERC165 interface in order to enable other contracts to query which interfaces this contract implements. * @dev See https://eips.ethereum.org/EIPS/eip-165 * @return `true` for supported interfaces, otherwise `false` */ function supportsInterface( bytes4 interfaceId ) public view virtual override(ERC165Upgradeable, IFeeSettingsV1, IFeeSettingsV2) returns (bool) { return interfaceId == type(IFeeSettingsV1).interfaceId || // we implement IFeeSettingsV1 for backwards compatibility interfaceId == type(IFeeSettingsV2).interfaceId || // we implement IFeeSettingsV2 ERC165Upgradeable.supportsInterface(interfaceId); // default implementation that enables further querying } /** * @notice Returns the default token fee collector * @dev this is a compatibility function for IFeeSettingsV1. It enables older token contracts to use the new fee settings contract. * @dev as IFeeSettingsV1 only supports a single fee collector, we can not inquire the token address. Therefore, we return the default fee collector. * @return The token fee collector */ function feeCollector() external view override(IFeeSettingsV1) returns (address) { return tokenFeeCollectors[address(0)]; } /** * @notice Returns the fee for a given token amount * @dev Custom fees are only applied correctly when this function is called from the token contract itself. * To calculate fees when calling from a different address, use `tokenFee(uint256, address)` instead. */ function tokenFee(uint256 _tokenAmount) external view override(IFeeSettingsV1) returns (uint256) { return tokenFee(_tokenAmount, _msgSender()); } /** * @notice calculate the fee for a given currency amount in Crowdinvesting (formerly ContinuousFundraising) * @dev this is a compatibility function for IFeeSettingsV1. It enables older token contracts to use the new fee settings contract. * @param _currencyAmount The amount of currency to calculate the fee for */ function continuousFundraisingFee( uint256 _currencyAmount ) external view override(IFeeSettingsV1) returns (uint256) { return crowdinvestingFee(_currencyAmount, address(0)); } /** * @notice calculate the fee for a given currency amount in PrivateOffer (formerly PersonalInvite) * @dev this is a compatibility function for IFeeSettingsV1. It enables older token contracts to use the new fee settings contract. * @param _currencyAmount The amount of currency to calculate the fee for */ function personalInviteFee(uint256 _currencyAmount) external view override(IFeeSettingsV1) returns (uint256) { return privateOfferFee(_currencyAmount, address(0)); } /** * @dev both Ownable and ERC2771Context have a _msgSender() function, so we need to override and select which one to use. */ function _msgSender() internal view override(ContextUpgradeable, ERC2771ContextUpgradeable) returns (address) { return ERC2771ContextUpgradeable._msgSender(); } /** * @dev both Ownable and ERC2771Context have a _msgData() function, so we need to override and select which one to use. */ function _msgData() internal view override(ContextUpgradeable, ERC2771ContextUpgradeable) returns (bytes calldata) { return ERC2771ContextUpgradeable._msgData(); } /** * @dev both Ownable and ERC2771Context have a _contextSuffixLength() function, so we need to override and select which one to use. */ function _contextSuffixLength() internal view virtual override(ContextUpgradeable, ERC2771ContextUpgradeable) returns (uint256) { return ERC2771ContextUpgradeable._contextSuffixLength(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./OwnableUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); function __Ownable2Step_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable2Step_init_unchained() internal onlyInitializing { } /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; import {Initializable} from "../../proxy/utils/Initializable.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 ERC165Upgradeable is Initializable, IERC165Upgradeable { function __ERC165_init() internal onlyInitializing { } function __ERC165_init_unchained() internal onlyInitializing { } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165Upgradeable).interfaceId; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (metatx/ERC2771Context.sol) pragma solidity ^0.8.9; import "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Context variant with ERC2771 support. * * WARNING: The usage of `delegatecall` in this contract is dangerous and may result in context corruption. * Any forwarded request to this contract triggering a `delegatecall` to itself will result in an invalid {_msgSender} * recovery. */ abstract contract ERC2771ContextUpgradeable is Initializable, ContextUpgradeable { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address private immutable _trustedForwarder; /// @custom:oz-upgrades-unsafe-allow constructor constructor(address trustedForwarder) { _trustedForwarder = trustedForwarder; } function isTrustedForwarder(address forwarder) public view virtual returns (bool) { return forwarder == _trustedForwarder; } function _msgSender() internal view virtual override returns (address) { uint256 calldataLength = msg.data.length; uint256 contextSuffixLength = _contextSuffixLength(); if (isTrustedForwarder(msg.sender) && calldataLength >= contextSuffixLength) { return address(bytes20(msg.data[calldataLength - contextSuffixLength:])); } else { return super._msgSender(); } } function _msgData() internal view virtual override returns (bytes calldata) { uint256 calldataLength = msg.data.length; uint256 contextSuffixLength = _contextSuffixLength(); if (isTrustedForwarder(msg.sender) && calldataLength >= contextSuffixLength) { return msg.data[:calldataLength - contextSuffixLength]; } else { return super._msgData(); } } /** * @dev ERC-2771 specifies the context as being a single address (20 bytes). */ function _contextSuffixLength() internal view virtual override returns (uint256) { return 20; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.23; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; /** * @title IFeeSettingsV1 * @author malteish * @notice This is the interface for the FeeSettings contract in v4 of the tokenize.it contracts. The token contract * and the investment contracts will use this interface to get the fees for the different actions, as well as the address * of the fee collector. */ interface IFeeSettingsV1 { function tokenFee(uint256) external view returns (uint256); function continuousFundraisingFee(uint256) external view returns (uint256); function personalInviteFee(uint256) external view returns (uint256); function feeCollector() external view returns (address); function owner() external view returns (address); function supportsInterface(bytes4) external view returns (bool); //because we inherit from ERC165 } /** * @title IFeeSettingsV2 * @author malteish * @notice This is the interface for the FeeSettings contract in v5 of the tokenize.it contracts. * From v4 to v5, the contract names have changed and instead of one fee collector, there are now three. */ interface IFeeSettingsV2 { function tokenFee(uint256, address) external view returns (uint256); function tokenFeeCollector(address) external view returns (address); function crowdinvestingFee(uint256, address) external view returns (uint256); function crowdinvestingFeeCollector(address) external view returns (address); function privateOfferFee(uint256, address) external view returns (uint256); function privateOfferFeeCollector(address) external view returns (address); function owner() external view returns (address); function supportsInterface(bytes4) external view returns (bool); //because we inherit from ERC165 } /** * @notice The Fees struct contains all the parameters to change fee quantities and fee collector addresses, * as well as the time when the new settings can be activated. * @dev time has different meanings: * 1. it is ignored when the struct is used during initialization. * 2. it is the time when the new settings can be activated when the struct is used during a fee change. * 3. it is the time up to which the settings are valid when the struct is used for fee discounts for specific customers */ struct Fees { uint32 tokenFeeNumerator; uint32 crowdinvestingFeeNumerator; uint32 privateOfferFeeNumerator; uint64 validityDate; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; 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 proxied contracts do not make use of 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. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * 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 prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// 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 IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or 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 { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (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); }
{ "remappings": [ "@ethereum-waffle/=node_modules/@ethereum-waffle/", "@opengsn/=node_modules/@opengsn/", "@openzeppelin/=node_modules/@openzeppelin/", "ds-test/=lib/forge-std/lib/ds-test/src/", "eth-gas-reporter/=node_modules/eth-gas-reporter/", "forge-std/=lib/forge-std/src/", "hardhat/=node_modules/hardhat/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_trustedForwarder","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint32","name":"tokenFeeNumerator","type":"uint32"},{"internalType":"uint32","name":"crowdinvestingFeeNumerator","type":"uint32"},{"internalType":"uint32","name":"privateOfferFeeNumerator","type":"uint32"},{"internalType":"uint64","name":"validityDate","type":"uint64"}],"indexed":false,"internalType":"struct Fees","name":"proposal","type":"tuple"}],"name":"ChangeProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newTokenFeeCollector","type":"address"},{"indexed":true,"internalType":"address","name":"newCrowdinvestingFeeCollector","type":"address"},{"indexed":true,"internalType":"address","name":"newPrivateOfferFeeCollector","type":"address"}],"name":"FeeCollectorsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"RemoveCustomCrowdinvestingFeeCollector","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"RemoveCustomFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"RemoveCustomPrivateOfferFeeCollector","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"RemoveCustomTokenFeeCollector","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"feeCollector","type":"address"}],"name":"SetCustomCrowdinvestingFeeCollector","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint32","name":"tokenFeeNumerator","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"crowdinvestingFeeNumerator","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"privateOfferFeeNumerator","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"SetCustomFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"feeCollector","type":"address"}],"name":"SetCustomPrivateOfferFeeCollector","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"feeCollector","type":"address"}],"name":"SetCustomTokenFeeCollector","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"tokenFeeNumerator","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"crowdinvestingFeeNumerator","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"privateOfferFeeNumerator","type":"uint32"}],"name":"SetFee","type":"event"},{"inputs":[],"name":"FEE_DENOMINATOR","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_CROWDINVESTING_FEE_NUMERATOR","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PRIVATE_OFFER_FEE_NUMERATOR","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TOKEN_FEE_NUMERATOR","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"}],"name":"addManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_currencyAmount","type":"uint256"}],"name":"continuousFundraisingFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_currencyAmount","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"crowdinvestingFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"crowdinvestingFeeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"crowdinvestingFeeCollectors","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"executeFeeChange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"fees","outputs":[{"internalType":"uint32","name":"tokenFeeNumerator","type":"uint32"},{"internalType":"uint32","name":"crowdinvestingFeeNumerator","type":"uint32"},{"internalType":"uint32","name":"privateOfferFeeNumerator","type":"uint32"},{"internalType":"uint64","name":"validityDate","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"components":[{"internalType":"uint32","name":"tokenFeeNumerator","type":"uint32"},{"internalType":"uint32","name":"crowdinvestingFeeNumerator","type":"uint32"},{"internalType":"uint32","name":"privateOfferFeeNumerator","type":"uint32"},{"internalType":"uint64","name":"validityDate","type":"uint64"}],"internalType":"struct Fees","name":"_fees","type":"tuple"},{"internalType":"address","name":"_tokenFeeCollector","type":"address"},{"internalType":"address","name":"_crowdinvestingFeeCollector","type":"address"},{"internalType":"address","name":"_privateOfferFeeCollector","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"managers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_currencyAmount","type":"uint256"}],"name":"personalInviteFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"tokenFeeNumerator","type":"uint32"},{"internalType":"uint32","name":"crowdinvestingFeeNumerator","type":"uint32"},{"internalType":"uint32","name":"privateOfferFeeNumerator","type":"uint32"},{"internalType":"uint64","name":"validityDate","type":"uint64"}],"internalType":"struct Fees","name":"_fees","type":"tuple"}],"name":"planFeeChange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_currencyAmount","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"privateOfferFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"privateOfferFeeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"privateOfferFeeCollectors","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposedDefaultFees","outputs":[{"internalType":"uint32","name":"tokenFeeNumerator","type":"uint32"},{"internalType":"uint32","name":"crowdinvestingFeeNumerator","type":"uint32"},{"internalType":"uint32","name":"privateOfferFeeNumerator","type":"uint32"},{"internalType":"uint64","name":"validityDate","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"removeCustomCrowdinvestingFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"removeCustomFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"removeCustomPrivateOfferFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"removeCustomTokenFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_manager","type":"address"}],"name":"removeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_feeCollector","type":"address"}],"name":"setCustomCrowdinvestingFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"components":[{"internalType":"uint32","name":"tokenFeeNumerator","type":"uint32"},{"internalType":"uint32","name":"crowdinvestingFeeNumerator","type":"uint32"},{"internalType":"uint32","name":"privateOfferFeeNumerator","type":"uint32"},{"internalType":"uint64","name":"validityDate","type":"uint64"}],"internalType":"struct Fees","name":"_fees","type":"tuple"}],"name":"setCustomFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_feeCollector","type":"address"}],"name":"setCustomPrivateOfferFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_feeCollector","type":"address"}],"name":"setCustomTokenFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenFeeCollector","type":"address"},{"internalType":"address","name":"_crowdinvestingFeeCollector","type":"address"},{"internalType":"address","name":"_personalOfferFeeCollector","type":"address"}],"name":"setFeeCollectors","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"tokenFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenAmount","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"tokenFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"tokenFeeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenFeeCollectors","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a03461011a57601f611cf338819003918201601f19168301916001600160401b0383118484101761011f5780849260209460405283398101031261011a57516001600160a01b038116810361011a5760805260005460ff8160081c166100c55760ff8082160361008a575b604051611bbd908161013682396080518181816113820152611b240152f35b60ff90811916176000557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160ff8152a13861006b565b60405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b6064820152608490fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe608060408181526004918236101561001657600080fd5b600092833560e01c91826301ffc9a714611607575081631558fda41461155d5781631f497de6146115375781632068983d146114fc57816323624a10146114da5781632458f3a6146114305781632d06177a146113ec578163410305e9146113a95781634d58cfcd14610f0b578163572b6c051461135757816357a32fa9146112ad578163715018a61461124657816374c0782f1461108557816379ba509714610ff057816384b799d714610fca5781638da5cb5b14610fa157816392891b3114610f10578163943c35b214610f0b57816399d6788014610ebb5781639e338c3c14610e84578163ac18de4314610e43578163b34b367b14610e08578163b3d55f3814610deb578163b6ebfa3914610d8e578163bd0139cf14610cfd578163beca028014610af0578163c415b95c14610abe578163d73792a914610aa1578163e11e981814610a44578163e25c0b90146109b3578163e2f661d514610978578163e30c39781461094f578163e9a85eb714610874578163eaeaddee146107ef578163ec4a43c1146107ac578163ed1c9e19146104c7578163ee49e07814610498578163f2fde38b14610427578163f79c6ea41461029757508063faaebd21146102295763fdff9b4d146101e857600080fd5b346102255760203660031901126102255760209160ff9082906001600160a01b03610211611672565b168152610100855220541690519015158152f35b5080fd5b5034610225576020366003190112610225579081906001600160a01b0361024e611672565b16815260fb602090815291902054825163ffffffff808316825282841c8116938201939093529281901c90911660408301526001600160401b03606091821c1690820152608090f35b839150346102255781600319360112610225576102b2611928565b60ff908154906001600160401b0390818360601c1642106103ca575083947f70f8fd9d2f94d049b9ffca3368e6aa66ae367e3de662bb9335acd9fe5ab9866d9260609286805260fb60205282872090868203610333575b50505083549063ffffffff8151928181168452818160201c166020850152821c1690820152a15580f35b815463ffffffff93841663ffffffff19821681178455885467ffffffff000000001667ffffffffffffffff19909216171782556103c292610394908854845463ffffffff60401b191690871c9190911660401b63ffffffff60401b16178355565b8654825467ffffffffffffffff60601b191690861c9190911660601b67ffffffffffffffff60601b16179055565b868080610309565b608490602087519162461bcd60e51b8352820152603160248201527f466565206368616e6765206d75737420626520657865637574656420616674656044820152707220746865206368616e67652074696d6560781b6064820152fd5b833461049557602036600319011261049557610441611672565b610449611928565b606580546001600160a01b0319166001600160a01b039283169081179091556033549091167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227008380a380f35b80fd5b828434610495578160031936011261049557506104c06020926104b961168d565b90356118c3565b9051908152f35b9050346107a85761010090816003193601126107a4576104e5611672565b6104ee366116c0565b6001600160a01b039260a435848116939192908490036107a05760c4359185831680930361079c5760e435938685168095036107985789549060ff8260081c16159788809961078b575b8015610774575b1561071a5760ff198381166001178d559289610709575b5083169081156106c65750916105839161062694938c526020998a5260018b8d209182541617905561198b565b61058c816119dc565b88805260fb875287892081518154838a015167ffffffffffffffff1990911663ffffffff9283161760209190911b67ffffffff000000001617825590916001600160401b0391606091906105fd90828d0151865463ffffffff60401b1916911660401b63ffffffff60401b16178555565b0151825467ffffffffffffffff60601b1916911660601b67ffffffffffffffff60601b16179055565b6106318315156117a0565b86805260fc85528587206001600160601b0360a01b93848254161790556106598115156117a0565b86805260fd855285872090838254161790556106768115156117a0565b85805260fe84528486209182541617905561068f578280f35b7f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989161ff001984541684555160018152a138808280f35b60649060208c519162461bcd60e51b8352820152601d60248201527f6f776e65722063616e206e6f74206265207a65726f20616464726573730000006044820152fd5b61ffff1916610101178c5538610556565b8a5162461bcd60e51b8152602081840152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b50303b15801561053f5750600160ff84161461053f565b50600160ff841610610538565b8980fd5b8880fd5b8780fd5b8380fd5b8280fd5b9050346107a85760203660031901126107a8576104c0906001600160401b038385806020975260fb8752205463ffffffff81861c1691829160601c169235611ae4565b505034610225576020366003190112610225578161080b611672565b6001600160a01b03908161081d611b21565b16835261010060205261083560ff8585205416611748565b16916108428315156117ec565b82825260fb6020528120557f4c7c453b1f4214758a9c23894dbf661429ecc4fbaf4ac74e3e84797be602f5778280a280f35b5050346102255760603660031901126102255761088f611672565b9061089861168d565b6044356001600160a01b038181169490929185900361094b578285916108bc611928565b16926108c98415156117a0565b86805260fc60205284872080546001600160a01b031990811686179091559216936108f58515156117a0565b86805260fd60205280872085848254161790556109138215156117a0565b86805260fe6020528620918254161790557fbdcb27b9a8568e6774fdc3799a321eef59eb9594c664a63935af636028a200dd8480a480f35b8580fd5b50503461022557816003193601126102255760655490516001600160a01b039091168152602090f35b505034610225576020366003190112610225576020916001600160a01b03908290826109a2611672565b16815260fe85522054169051908152f35b505034610225576020366003190112610225576109ce611672565b6001600160a01b0390816109e0611b21565b1684526101006020526109f860ff8486205416611748565b1690610a058215156117ec565b81835260fd602052822080546001600160a01b03191690557f978239619a16f8e72997265d5fab37487f7c55b24b7986c14750a05a0333e7c28280a280f35b9050346107a857816003193601126107a8576020926104c091610a6561168d565b82805260fb86528463ffffffff938482822054831c169260018060a01b031681522054926001600160401b038460601c1693861c169135611ae4565b505034610225578160031936011261022557602090516127108152f35b50503461022557816003193601126102255781805260fc6020908152918190205490516001600160a01b039091168152f35b919050346107a85760803660031901126107a8578051916001600160401b03916080840183811185821017610cea57815263ffffffff82358181168103610ce6578552602435948186168603610ce657602080820196875260443591838316830361079c578481019283526064359587871687036107985760608201968752610b77611928565b610b80826119dc565b848251168a805260fb8452868b20549086821610908115610cd5575b8115610cc3575b50610c3b575b50918391827f85cf05d871e0ba154e0518115353d702097ff8cc887b14588afe1910caad1074999795608099979551169760ff5467ffffffff000000008251851b1663ffffffff60401b8651891b16908b6001600160401b0360601b8b5160601b16936001600160601b0360a01b161717171760ff55855198895251169087015251169084015251166060820152a180f35b87875116626ebe00420190814211610cb05711610ba957855162461bcd60e51b8152908101839052603260248201527f466565206368616e6765206d757374206265206174206c65617374203132207760448201527165656b7320696e207468652066757475726560701b6064820152608490fd5b634e487b7160e01b8c526011835260248cfd5b9050858086511691881c161038610ba3565b8a51871681861c8816109150610b9c565b8680fd5b634e487b7160e01b865260418352602486fd5b50503461022557602036600319011261022557610d18611672565b6001600160a01b039081610d2a611b21565b168452610100602052610d4260ff8486205416611748565b1690610d4f8215156117ec565b81835260fc602052822080546001600160a01b03191690557fb47f50eb03488bb1dd0e2e157ce7b84b734638183cc58443e30d8cc78e8d6d118280a280f35b9050346107a857816003193601126107a8576020926104c091610daf61168d565b82805260fb86528463ffffffff938482822054891c169260018060a01b031681522054926001600160401b038460601c1693871c169135611ae4565b505034610225578160031936011261022557602090516103e88152f35b505034610225576020366003190112610225576020916001600160a01b0390829082610e32611672565b16815260fc85522054169051908152f35b50503461022557602036600319011261022557610e5e611672565b610e66611928565b6001600160a01b031682526101006020528120805460ff1916905580f35b50503461022557602036600319011261022557602090610eaa610ea5611672565b611893565b90516001600160a01b039091168152f35b8284346104955780600319360112610495575060ff54815163ffffffff8083168252602083811c8216908301529282901c90921660408301526001600160401b03606091821c1690820152608090f35b6116a3565b50503461022557602036600319011261022557610f2b611672565b6001600160a01b039081610f3d611b21565b168452610100602052610f5560ff8486205416611748565b1690610f628215156117ec565b81835260fe602052822080546001600160a01b03191690557f6379acf5824e6b8a26493f02fd1de7722d75e692e0b5ad7ca0554f2e5f45b5408280a280f35b50503461022557816003193601126102255760335490516001600160a01b039091168152602090f35b50503461022557602036600319011261022557602090610eaa610feb611672565b611863565b9050346107a857826003193601126107a85761100a611b21565b6065549092906001600160a01b0390811690841603611030578361102d8461198b565b80f35b906020608492519162461bcd60e51b8352820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152fd5b9050346107a85760a03660031901126107a8576110a0611672565b6110a9366116c0565b906001600160a01b0390816110bc611b21565b1686526101006020526110d460ff8688205416611748565b6110dd836119dc565b16926110ea8415156117ec565b60608201906001600160401b0393848351164210156111ef5750917f281814d2cb315f077385a29f84f3df421ff3d06938c1ab2d1d94573bfd388e28939160809386885260fb602052808820926111d963ffffffff9586835116968763ffffffff19885416178755848160208601511694611182868a9067ffffffff0000000082549160201b169067ffffffff000000001916179055565b015116946111ab86889063ffffffff60401b82549160401b169063ffffffff60401b1916179055565b51865467ffffffffffffffff60601b19169116606081901b67ffffffffffffffff60601b1691909117909555565b815194855260208501528301526060820152a280f35b6020608492519162461bcd60e51b8352820152602c60248201527f437573746f6d20666565206578706972792074696d65206d757374206265206960448201526b6e207468652066757475726560a01b6064820152fd5b833461049557806003193601126104955761125f611928565b606580546001600160a01b031990811690915560338054918216905581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b5050346102255780600319360112610225576112c7611672565b906112d061168d565b6001600160a01b03908190816112e4611b21565b1686526101006020526112fc60ff8588205416611748565b16926113098415156117a0565b16906113168215156117ec565b81845260fe602052832080546001600160a01b031916831790557f45b9c7b9a32b575cf29fbf1694eab5cfe8e5addda3e666e21548e320e7ba3c458380a380f35b50503461022557602036600319011261022557602090611375611672565b60018060a01b03915191807f0000000000000000000000000000000000000000000000000000000000000000169116148152f35b9050346107a85760203660031901126107a8576104c0906001600160401b038385806020975260fb8752205463ffffffff81871c1691829160601c169235611ae4565b50503461022557602036600319011261022557611407611672565b61140f611928565b6001600160a01b031682526101006020528120805460ff1916600117905580f35b50503461022557806003193601126102255761144a611672565b9061145361168d565b6001600160a01b0390819081611467611b21565b16865261010060205261147f60ff8588205416611748565b169261148c8415156117a0565b16906114998215156117ec565b81845260fd602052832080546001600160a01b031916831790557f23c7938ba315c2f032d05636358dd558f23103665e3f365d88166bdf8e0bd8708380a380f35b82843461049557602036600319011261049557506104c06020926104b9611b21565b505034610225576020366003190112610225576020916001600160a01b0390829082611526611672565b16815260fd85522054169051908152f35b50503461022557602036600319011261022557602090610eaa611558611672565b61182e565b505034610225578060031936011261022557611577611672565b9061158061168d565b6001600160a01b0390819081611594611b21565b1686526101006020526115ac60ff8588205416611748565b16926115b98415156117a0565b16906115c68215156117ec565b81845260fc602052832080546001600160a01b031916831790557ffe796818253c16ffe16453130ccd268e0a866b24f4be1f1b57f24829572489c78380a380f35b8491346107a85760203660031901126107a8573563ffffffff60e01b81168091036107a857602092506318cc96f360e31b8114908115611661575b8115611650575b5015158152f35b6301ffc9a760e01b14905083611649565b6306057d1560e31b81149150611642565b600435906001600160a01b038216820361168857565b600080fd5b602435906001600160a01b038216820361168857565b346116885760003660031901126116885760206040516101f48152f35b608090602319011261168857604051906001600160401b036080830181811184821017611732576040528263ffffffff60243581811681036116885782526044358181168103611688576020830152606435908116810361168857604082015260843591821682036116885760600152565b634e487b7160e01b600052604160045260246000fd5b1561174f57565b60405162461bcd60e51b8152602060048201526024808201527f4f6e6c79206d616e61676572732063616e2063616c6c20746869732066756e636044820152633a34b7b760e11b6064820152608490fd5b156117a757565b60405162461bcd60e51b815260206004820152601b60248201527f46656520636f6c6c6563746f722063616e6e6f742062652030783000000000006044820152606490fd5b156117f357565b60405162461bcd60e51b81526020600482015260136024820152720546f6b656e2063616e6e6f742062652030783606c1b6044820152606490fd5b6001600160a01b03908116600090815260fe602052604090205481168061185e5750600080526040600020541690565b905090565b6001600160a01b03908116600090815260fc602052604090205481168061185e5750600080526040600020541690565b6001600160a01b03908116600090815260fd602052604090205481168061185e5750600080526040600020541690565b60fb6020527fc88390e7e62175be0932452175b6a7222b6b094ab0ef984a5153c620345d8975546001600160a01b039092166000908152604090205461192592606082901c6001600160401b03169263ffffffff928316929190911690611ae4565b90565b6033546001600160a01b039081169061193f611b21565b160361194757565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b6001600160601b0360a01b90816065541660655560335460018060a01b038092168093821617603355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b6101f49063ffffffff90828282511611611a9f576103e88260208301511611611a5057604001511611611a0b57565b60405162461bcd60e51b815260206004820152601e60248201527f507269766174654f6666657220666565206d757374206265203c3d20352500006044820152606490fd5b60405162461bcd60e51b815260206004820152602160248201527f43726f7764696e76657374696e6720666565206d757374206265203c3d2031306044820152602560f81b6064820152608490fd5b60405162461bcd60e51b815260206004820152601760248201527f546f6b656e20666565206d757374206265203c3d2035250000000000000000006044820152606490fd5b926001600160401b03804216911610611b165790611b05611b0b9284611b90565b92611b90565b81811061185e575090565b905061192591611b90565b337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161480611b85575b15611b81576013193601368111611b6b573560601c90565b634e487b7160e01b600052601160045260246000fd5b3390565b506014361015611b53565b9063ffffffff1690818102918183041490151715611b6b5761271090049056fea164736f6c6343000817000a000000000000000000000000aa3e82b4c4093b4ba13cb5714382c99adbf750ca
Deployed Bytecode
0x608060408181526004918236101561001657600080fd5b600092833560e01c91826301ffc9a714611607575081631558fda41461155d5781631f497de6146115375781632068983d146114fc57816323624a10146114da5781632458f3a6146114305781632d06177a146113ec578163410305e9146113a95781634d58cfcd14610f0b578163572b6c051461135757816357a32fa9146112ad578163715018a61461124657816374c0782f1461108557816379ba509714610ff057816384b799d714610fca5781638da5cb5b14610fa157816392891b3114610f10578163943c35b214610f0b57816399d6788014610ebb5781639e338c3c14610e84578163ac18de4314610e43578163b34b367b14610e08578163b3d55f3814610deb578163b6ebfa3914610d8e578163bd0139cf14610cfd578163beca028014610af0578163c415b95c14610abe578163d73792a914610aa1578163e11e981814610a44578163e25c0b90146109b3578163e2f661d514610978578163e30c39781461094f578163e9a85eb714610874578163eaeaddee146107ef578163ec4a43c1146107ac578163ed1c9e19146104c7578163ee49e07814610498578163f2fde38b14610427578163f79c6ea41461029757508063faaebd21146102295763fdff9b4d146101e857600080fd5b346102255760203660031901126102255760209160ff9082906001600160a01b03610211611672565b168152610100855220541690519015158152f35b5080fd5b5034610225576020366003190112610225579081906001600160a01b0361024e611672565b16815260fb602090815291902054825163ffffffff808316825282841c8116938201939093529281901c90911660408301526001600160401b03606091821c1690820152608090f35b839150346102255781600319360112610225576102b2611928565b60ff908154906001600160401b0390818360601c1642106103ca575083947f70f8fd9d2f94d049b9ffca3368e6aa66ae367e3de662bb9335acd9fe5ab9866d9260609286805260fb60205282872090868203610333575b50505083549063ffffffff8151928181168452818160201c166020850152821c1690820152a15580f35b815463ffffffff93841663ffffffff19821681178455885467ffffffff000000001667ffffffffffffffff19909216171782556103c292610394908854845463ffffffff60401b191690871c9190911660401b63ffffffff60401b16178355565b8654825467ffffffffffffffff60601b191690861c9190911660601b67ffffffffffffffff60601b16179055565b868080610309565b608490602087519162461bcd60e51b8352820152603160248201527f466565206368616e6765206d75737420626520657865637574656420616674656044820152707220746865206368616e67652074696d6560781b6064820152fd5b833461049557602036600319011261049557610441611672565b610449611928565b606580546001600160a01b0319166001600160a01b039283169081179091556033549091167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227008380a380f35b80fd5b828434610495578160031936011261049557506104c06020926104b961168d565b90356118c3565b9051908152f35b9050346107a85761010090816003193601126107a4576104e5611672565b6104ee366116c0565b6001600160a01b039260a435848116939192908490036107a05760c4359185831680930361079c5760e435938685168095036107985789549060ff8260081c16159788809961078b575b8015610774575b1561071a5760ff198381166001178d559289610709575b5083169081156106c65750916105839161062694938c526020998a5260018b8d209182541617905561198b565b61058c816119dc565b88805260fb875287892081518154838a015167ffffffffffffffff1990911663ffffffff9283161760209190911b67ffffffff000000001617825590916001600160401b0391606091906105fd90828d0151865463ffffffff60401b1916911660401b63ffffffff60401b16178555565b0151825467ffffffffffffffff60601b1916911660601b67ffffffffffffffff60601b16179055565b6106318315156117a0565b86805260fc85528587206001600160601b0360a01b93848254161790556106598115156117a0565b86805260fd855285872090838254161790556106768115156117a0565b85805260fe84528486209182541617905561068f578280f35b7f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989161ff001984541684555160018152a138808280f35b60649060208c519162461bcd60e51b8352820152601d60248201527f6f776e65722063616e206e6f74206265207a65726f20616464726573730000006044820152fd5b61ffff1916610101178c5538610556565b8a5162461bcd60e51b8152602081840152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b50303b15801561053f5750600160ff84161461053f565b50600160ff841610610538565b8980fd5b8880fd5b8780fd5b8380fd5b8280fd5b9050346107a85760203660031901126107a8576104c0906001600160401b038385806020975260fb8752205463ffffffff81861c1691829160601c169235611ae4565b505034610225576020366003190112610225578161080b611672565b6001600160a01b03908161081d611b21565b16835261010060205261083560ff8585205416611748565b16916108428315156117ec565b82825260fb6020528120557f4c7c453b1f4214758a9c23894dbf661429ecc4fbaf4ac74e3e84797be602f5778280a280f35b5050346102255760603660031901126102255761088f611672565b9061089861168d565b6044356001600160a01b038181169490929185900361094b578285916108bc611928565b16926108c98415156117a0565b86805260fc60205284872080546001600160a01b031990811686179091559216936108f58515156117a0565b86805260fd60205280872085848254161790556109138215156117a0565b86805260fe6020528620918254161790557fbdcb27b9a8568e6774fdc3799a321eef59eb9594c664a63935af636028a200dd8480a480f35b8580fd5b50503461022557816003193601126102255760655490516001600160a01b039091168152602090f35b505034610225576020366003190112610225576020916001600160a01b03908290826109a2611672565b16815260fe85522054169051908152f35b505034610225576020366003190112610225576109ce611672565b6001600160a01b0390816109e0611b21565b1684526101006020526109f860ff8486205416611748565b1690610a058215156117ec565b81835260fd602052822080546001600160a01b03191690557f978239619a16f8e72997265d5fab37487f7c55b24b7986c14750a05a0333e7c28280a280f35b9050346107a857816003193601126107a8576020926104c091610a6561168d565b82805260fb86528463ffffffff938482822054831c169260018060a01b031681522054926001600160401b038460601c1693861c169135611ae4565b505034610225578160031936011261022557602090516127108152f35b50503461022557816003193601126102255781805260fc6020908152918190205490516001600160a01b039091168152f35b919050346107a85760803660031901126107a8578051916001600160401b03916080840183811185821017610cea57815263ffffffff82358181168103610ce6578552602435948186168603610ce657602080820196875260443591838316830361079c578481019283526064359587871687036107985760608201968752610b77611928565b610b80826119dc565b848251168a805260fb8452868b20549086821610908115610cd5575b8115610cc3575b50610c3b575b50918391827f85cf05d871e0ba154e0518115353d702097ff8cc887b14588afe1910caad1074999795608099979551169760ff5467ffffffff000000008251851b1663ffffffff60401b8651891b16908b6001600160401b0360601b8b5160601b16936001600160601b0360a01b161717171760ff55855198895251169087015251169084015251166060820152a180f35b87875116626ebe00420190814211610cb05711610ba957855162461bcd60e51b8152908101839052603260248201527f466565206368616e6765206d757374206265206174206c65617374203132207760448201527165656b7320696e207468652066757475726560701b6064820152608490fd5b634e487b7160e01b8c526011835260248cfd5b9050858086511691881c161038610ba3565b8a51871681861c8816109150610b9c565b8680fd5b634e487b7160e01b865260418352602486fd5b50503461022557602036600319011261022557610d18611672565b6001600160a01b039081610d2a611b21565b168452610100602052610d4260ff8486205416611748565b1690610d4f8215156117ec565b81835260fc602052822080546001600160a01b03191690557fb47f50eb03488bb1dd0e2e157ce7b84b734638183cc58443e30d8cc78e8d6d118280a280f35b9050346107a857816003193601126107a8576020926104c091610daf61168d565b82805260fb86528463ffffffff938482822054891c169260018060a01b031681522054926001600160401b038460601c1693871c169135611ae4565b505034610225578160031936011261022557602090516103e88152f35b505034610225576020366003190112610225576020916001600160a01b0390829082610e32611672565b16815260fc85522054169051908152f35b50503461022557602036600319011261022557610e5e611672565b610e66611928565b6001600160a01b031682526101006020528120805460ff1916905580f35b50503461022557602036600319011261022557602090610eaa610ea5611672565b611893565b90516001600160a01b039091168152f35b8284346104955780600319360112610495575060ff54815163ffffffff8083168252602083811c8216908301529282901c90921660408301526001600160401b03606091821c1690820152608090f35b6116a3565b50503461022557602036600319011261022557610f2b611672565b6001600160a01b039081610f3d611b21565b168452610100602052610f5560ff8486205416611748565b1690610f628215156117ec565b81835260fe602052822080546001600160a01b03191690557f6379acf5824e6b8a26493f02fd1de7722d75e692e0b5ad7ca0554f2e5f45b5408280a280f35b50503461022557816003193601126102255760335490516001600160a01b039091168152602090f35b50503461022557602036600319011261022557602090610eaa610feb611672565b611863565b9050346107a857826003193601126107a85761100a611b21565b6065549092906001600160a01b0390811690841603611030578361102d8461198b565b80f35b906020608492519162461bcd60e51b8352820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152fd5b9050346107a85760a03660031901126107a8576110a0611672565b6110a9366116c0565b906001600160a01b0390816110bc611b21565b1686526101006020526110d460ff8688205416611748565b6110dd836119dc565b16926110ea8415156117ec565b60608201906001600160401b0393848351164210156111ef5750917f281814d2cb315f077385a29f84f3df421ff3d06938c1ab2d1d94573bfd388e28939160809386885260fb602052808820926111d963ffffffff9586835116968763ffffffff19885416178755848160208601511694611182868a9067ffffffff0000000082549160201b169067ffffffff000000001916179055565b015116946111ab86889063ffffffff60401b82549160401b169063ffffffff60401b1916179055565b51865467ffffffffffffffff60601b19169116606081901b67ffffffffffffffff60601b1691909117909555565b815194855260208501528301526060820152a280f35b6020608492519162461bcd60e51b8352820152602c60248201527f437573746f6d20666565206578706972792074696d65206d757374206265206960448201526b6e207468652066757475726560a01b6064820152fd5b833461049557806003193601126104955761125f611928565b606580546001600160a01b031990811690915560338054918216905581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b5050346102255780600319360112610225576112c7611672565b906112d061168d565b6001600160a01b03908190816112e4611b21565b1686526101006020526112fc60ff8588205416611748565b16926113098415156117a0565b16906113168215156117ec565b81845260fe602052832080546001600160a01b031916831790557f45b9c7b9a32b575cf29fbf1694eab5cfe8e5addda3e666e21548e320e7ba3c458380a380f35b50503461022557602036600319011261022557602090611375611672565b60018060a01b03915191807f000000000000000000000000aa3e82b4c4093b4ba13cb5714382c99adbf750ca169116148152f35b9050346107a85760203660031901126107a8576104c0906001600160401b038385806020975260fb8752205463ffffffff81871c1691829160601c169235611ae4565b50503461022557602036600319011261022557611407611672565b61140f611928565b6001600160a01b031682526101006020528120805460ff1916600117905580f35b50503461022557806003193601126102255761144a611672565b9061145361168d565b6001600160a01b0390819081611467611b21565b16865261010060205261147f60ff8588205416611748565b169261148c8415156117a0565b16906114998215156117ec565b81845260fd602052832080546001600160a01b031916831790557f23c7938ba315c2f032d05636358dd558f23103665e3f365d88166bdf8e0bd8708380a380f35b82843461049557602036600319011261049557506104c06020926104b9611b21565b505034610225576020366003190112610225576020916001600160a01b0390829082611526611672565b16815260fd85522054169051908152f35b50503461022557602036600319011261022557602090610eaa611558611672565b61182e565b505034610225578060031936011261022557611577611672565b9061158061168d565b6001600160a01b0390819081611594611b21565b1686526101006020526115ac60ff8588205416611748565b16926115b98415156117a0565b16906115c68215156117ec565b81845260fc602052832080546001600160a01b031916831790557ffe796818253c16ffe16453130ccd268e0a866b24f4be1f1b57f24829572489c78380a380f35b8491346107a85760203660031901126107a8573563ffffffff60e01b81168091036107a857602092506318cc96f360e31b8114908115611661575b8115611650575b5015158152f35b6301ffc9a760e01b14905083611649565b6306057d1560e31b81149150611642565b600435906001600160a01b038216820361168857565b600080fd5b602435906001600160a01b038216820361168857565b346116885760003660031901126116885760206040516101f48152f35b608090602319011261168857604051906001600160401b036080830181811184821017611732576040528263ffffffff60243581811681036116885782526044358181168103611688576020830152606435908116810361168857604082015260843591821682036116885760600152565b634e487b7160e01b600052604160045260246000fd5b1561174f57565b60405162461bcd60e51b8152602060048201526024808201527f4f6e6c79206d616e61676572732063616e2063616c6c20746869732066756e636044820152633a34b7b760e11b6064820152608490fd5b156117a757565b60405162461bcd60e51b815260206004820152601b60248201527f46656520636f6c6c6563746f722063616e6e6f742062652030783000000000006044820152606490fd5b156117f357565b60405162461bcd60e51b81526020600482015260136024820152720546f6b656e2063616e6e6f742062652030783606c1b6044820152606490fd5b6001600160a01b03908116600090815260fe602052604090205481168061185e5750600080526040600020541690565b905090565b6001600160a01b03908116600090815260fc602052604090205481168061185e5750600080526040600020541690565b6001600160a01b03908116600090815260fd602052604090205481168061185e5750600080526040600020541690565b60fb6020527fc88390e7e62175be0932452175b6a7222b6b094ab0ef984a5153c620345d8975546001600160a01b039092166000908152604090205461192592606082901c6001600160401b03169263ffffffff928316929190911690611ae4565b90565b6033546001600160a01b039081169061193f611b21565b160361194757565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b6001600160601b0360a01b90816065541660655560335460018060a01b038092168093821617603355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b6101f49063ffffffff90828282511611611a9f576103e88260208301511611611a5057604001511611611a0b57565b60405162461bcd60e51b815260206004820152601e60248201527f507269766174654f6666657220666565206d757374206265203c3d20352500006044820152606490fd5b60405162461bcd60e51b815260206004820152602160248201527f43726f7764696e76657374696e6720666565206d757374206265203c3d2031306044820152602560f81b6064820152608490fd5b60405162461bcd60e51b815260206004820152601760248201527f546f6b656e20666565206d757374206265203c3d2035250000000000000000006044820152606490fd5b926001600160401b03804216911610611b165790611b05611b0b9284611b90565b92611b90565b81811061185e575090565b905061192591611b90565b337f000000000000000000000000aa3e82b4c4093b4ba13cb5714382c99adbf750ca6001600160a01b03161480611b85575b15611b81576013193601368111611b6b573560601c90565b634e487b7160e01b600052601160045260246000fd5b3390565b506014361015611b53565b9063ffffffff1690818102918183041490151715611b6b5761271090049056fea164736f6c6343000817000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000aa3e82b4c4093b4ba13cb5714382c99adbf750ca
-----Decoded View---------------
Arg [0] : _trustedForwarder (address): 0xAa3E82b4c4093b4bA13Cb5714382C99ADBf750cA
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000aa3e82b4c4093b4ba13cb5714382c99adbf750ca
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.