Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 5 from a total of 5 transactions
Latest 12 internal transactions
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
21768950 | 15 days ago | Contract Creation | 0 ETH | |||
21768950 | 15 days ago | Contract Creation | 0 ETH | |||
21768950 | 15 days ago | Contract Creation | 0 ETH | |||
21768950 | 15 days ago | Contract Creation | 0 ETH | |||
21766687 | 15 days ago | Contract Creation | 0 ETH | |||
21738871 | 19 days ago | Contract Creation | 0 ETH | |||
21738865 | 19 days ago | Contract Creation | 0 ETH | |||
21738665 | 19 days ago | Contract Creation | 0 ETH | |||
21738658 | 19 days ago | Contract Creation | 0 ETH | |||
21738653 | 19 days ago | Contract Creation | 0 ETH | |||
21738646 | 19 days ago | Contract Creation | 0 ETH | |||
21738639 | 19 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
FrictionlessTokensFactory
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 1000 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT /** * Copyright © 2024 Frictionless Group Holdings S.à.r.l * * Permission is hereby granted, free of charge, to any person obtaining a copy of the Frictionless protocol smart contracts * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies * or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL FRICTIONLESS GROUP * HOLDINGS S.à.r.l OR AN OF ITS SUBSIDIARIES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ pragma solidity ^0.8.16; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { AgentRoleUpgradeable } from "@ERC-3643/roles/AgentRoleUpgradeable.sol"; import { IFrictionlessDigitalSecurityToken } from "@interface/IFrictionlessDigitalSecurityToken.sol"; import { IFrictionlessFundDepositToken } from "@interface/IFrictionlessFundDepositToken.sol"; import { IFrictionlessOnChainAssetToken } from "@interface/IFrictionlessOnChainAssetToken.sol"; import { IFrictionlessTokensFactory } from "@interface/IFrictionlessTokensFactory.sol"; import { FrictionlessFundDeposit } from "@modules/FrictionlessFundDeposit.sol"; import { FrictionlessDigitalSecurity } from "@modules/FrictionlessDigitalSecurity.sol"; import { FrictionlessOnChainAsset } from "@modules/FrictionlessOnChainAsset.sol"; import { IBasicFrictionlessToken } from "@interface/IBasicFrictionlessToken.sol"; /** * @title FrictionlessTokensFactory - Implementation of the IFrictionlessTokensFactory * @author Frictionless Group Holdings S.à.r.l * @notice See {IFrictionlessTokensFactory} */ contract FrictionlessTokensFactory is IFrictionlessTokensFactory, OwnableUpgradeable { /// @dev the address of the treasuryManager address public override treasuryManager; mapping(address => bool) public override existingFrictionlessTokens; /** * @dev Modifier to ensure only the treasury manager can invoke specific functions */ modifier onlyTreasuryManager() { _onlyTreasuryManager(); _; } /** * @dev Init the contract with the specified treasuryManager_ and the mappings of each Frictionless token and it's associated compliance contract. * @param treasuryManager_ the addresses of the treasury manager to set * throws `FrictionlessTokensFactoryZeroAddress` if the treasuryManager_ is a zero address */ function init(address treasuryManager_) external initializer { __Ownable_init(); _setTreasuryManager(treasuryManager_); } /// @inheritdoc IFrictionlessTokensFactory function setTreasuryManager(address newTreasuryManager_) external override onlyOwner { _setTreasuryManager(newTreasuryManager_); } /// @inheritdoc IFrictionlessTokensFactory function deployFundDepositToken( address tokenOwner_, BaseTokenInitParams calldata baseTokenInitParams_, IFrictionlessFundDepositToken.FFDImmutableData calldata initData_ ) external override onlyTreasuryManager returns (address tokenProxyAddr_) { tokenProxyAddr_ = address( new FrictionlessFundDeposit( baseTokenInitParams_.implementationAuthority, baseTokenInitParams_.identityRegistry, baseTokenInitParams_.compliance, baseTokenInitParams_.onChainId, baseTokenInitParams_.tokenName, baseTokenInitParams_.tokenSymbol, initData_ ) ); _setupToken(tokenProxyAddr_, tokenOwner_, IBasicFrictionlessToken.FrictionlessTokenTypes.FUND_DEPOSIT_TOKEN); } /// @inheritdoc IFrictionlessTokensFactory function deployDigitalSecurityToken( address tokenOwner_, BaseTokenInitParams calldata baseTokenInitParams_, IFrictionlessDigitalSecurityToken.FDSImmutableData calldata initData_, IFrictionlessDigitalSecurityToken.FDSMutableData calldata updateData_ ) external override onlyTreasuryManager returns (address tokenProxyAddr_) { tokenProxyAddr_ = address( new FrictionlessDigitalSecurity( baseTokenInitParams_.implementationAuthority, baseTokenInitParams_.identityRegistry, baseTokenInitParams_.compliance, baseTokenInitParams_.onChainId, baseTokenInitParams_.tokenName, baseTokenInitParams_.tokenSymbol, initData_, updateData_ ) ); _setupToken( tokenProxyAddr_, tokenOwner_, IBasicFrictionlessToken.FrictionlessTokenTypes.DIGITAL_SECURITY_TOKEN ); } /// @inheritdoc IFrictionlessTokensFactory function deployOnChainAssetToken( address tokenOwner_, BaseTokenInitParams calldata baseTokenInitParams_, IFrictionlessOnChainAssetToken.FOCASpecData calldata specData_, IFrictionlessOnChainAssetToken.FOCAIssuanceData calldata issuanceData_, IFrictionlessOnChainAssetToken.FOCAUpdateData calldata updateData_ ) external override onlyTreasuryManager returns (address tokenProxyAddr_) { tokenProxyAddr_ = address( new FrictionlessOnChainAsset( baseTokenInitParams_.implementationAuthority, baseTokenInitParams_.identityRegistry, baseTokenInitParams_.compliance, baseTokenInitParams_.onChainId, specData_, issuanceData_, updateData_ ) ); _setupToken(tokenProxyAddr_, tokenOwner_, IBasicFrictionlessToken.FrictionlessTokenTypes.ON_CHAIN_ASSET_TOKEN); } /// @dev sets the token owner_ as an agent on the token_, thereby permissioning and transferring ownership to the owner_ function _setupToken( address token_, address owner_, IBasicFrictionlessToken.FrictionlessTokenTypes tokenType_ ) internal { // Manage the permissions for this token AgentRoleUpgradeable(token_).addAgent(msg.sender); AgentRoleUpgradeable(token_).addAgent(owner_); AgentRoleUpgradeable(token_).transferOwnership(owner_); existingFrictionlessTokens[token_] = true; emit FrictionlessTokenDeployed(tokenType_, token_); } /// @dev See {IFrictionlessTokensFactory-setTreasuryManager} function _setTreasuryManager(address newTreasuryManager_) internal { if (newTreasuryManager_ == address(0)) { revert FrictionlessTokensFactoryZeroAddress(); } treasuryManager = newTreasuryManager_; } /** * @dev Determines if the `msg.sender` is the Treasury Manager, if not throws the error `FrictionlessComplianceFactoryNotATreasuryManager` */ function _onlyTreasuryManager() internal view { if (msg.sender != treasuryManager) { revert FrictionlessTokensFactoryNotATreasuryManager(msg.sender); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../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: GPL-3.0 // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= // :=*%@@@#=. :#@@% *@@@%= // .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- // :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. // -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ // =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- // -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: // :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. // %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. // #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ // *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- // -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: // .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- // -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- // -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# // *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- // +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: // =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: // .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. // +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. // -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. // ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. // @@@@@@+. +@@*. .+@@@@@%=. // -@@@@@= =@@%: -#@@@@%+. // +@@@@@. =@@@= .+@@@@@*: // #@@@@#:%@@#. :*@@@@#- // @@@@@%@@@= :#@@@@+. // :@@@@@@@#.:#@@@%- // +@@@@@@-.*@@@*: // #@@@@#.=@@@+. // @@@@+-%@%= // :@@@#%@%= // +@@@@%- // :#%%= // /** * NOTICE * * The T-REX software is licensed under a proprietary license or the GPL v.3. * If you choose to receive it under the GPL v.3 license, the following applies: * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * * Copyright (C) 2023, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity 0.8.17; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "./Roles.sol"; contract AgentRoleUpgradeable is OwnableUpgradeable { using Roles for Roles.Role; Roles.Role private _agents; event AgentAdded(address indexed _agent); event AgentRemoved(address indexed _agent); modifier onlyAgent() { require(isAgent(msg.sender), "AgentRole: caller does not have the Agent role"); _; } function addAgent(address _agent) public onlyOwner { require(_agent != address(0), "invalid argument - zero address"); _agents.add(_agent); emit AgentAdded(_agent); } function removeAgent(address _agent) public onlyOwner { require(_agent != address(0), "invalid argument - zero address"); _agents.remove(_agent); emit AgentRemoved(_agent); } function isAgent(address _agent) public view returns (bool) { return _agents.has(_agent); } }
// SPDX-License-Identifier: MIT /** * Copyright © 2024 Frictionless Group Holdings S.à.r.l * * Permission is hereby granted, free of charge, to any person obtaining a copy of the Frictionless protocol smart contracts * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies * or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL FRICTIONLESS * GROUP HOLDINGS S.à.r.l OR ANY OF ITS SUBSIDIARIES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * */ pragma solidity ^0.8.16; import { IBasicFrictionlessToken } from "@interface/IBasicFrictionlessToken.sol"; /** * @title IFrictionlessDigitalSecurityToken - The permissioned & transferable digital security which represents the future cash flow from the `FrictionlessOnChainAssetToken`. * @author Frictionless Group Holdings S.à.r.l * @notice This is the permissioned & transferable digital security which represents the future cash flow from the `FrictionlessOnChainAssetToken` and is purchased by * the Investor using `FrictionlessFundDepositTokens`. These digital securities are permissioned and transferable between permissioned Investors in a permissioned secondary market. * This token is linked to the `FrictionlessOnChainAssetToken` and denominated in a FIAT currency at a future date for settlement. */ interface IFrictionlessDigitalSecurityToken is IBasicFrictionlessToken { // @dev Enumeration to represent the type of the digital security, either a coupon (yield) or strip (principal) enum FrictionlessDigitalSecurityTokenType { COUPON, STRIP } /** * @dev Struct which represents the immutable data in the Token. Once set it cannot be modified. * @param baseCurrency the baseCurrency is the FIAT denomination of the digital security, this is the currency the `FrictionlessOnChainAssetToken` is issued in. * @param tokenType the type of the token as defined in the enum * @param onChainAssetAddress the address of the `FrictionlessOnChainAssetToken` for which this token is a future cash distribution. */ struct FDSImmutableData { string baseCurrency; FrictionlessDigitalSecurityTokenType tokenType; address onChainAssetAddress; } /** * @dev Struct which represents the updatable data in the Token. This data can be modified by the Agent only. * @param maturesOn the maturity date of the digital security, it can be updated if there are delays in payment or at the request of the calculating agent. */ struct FDSMutableData { uint256 maturesOn; } /// @dev error throw if there is an attempt to modify the immutable data. error FrictionlessDigitalSecurityTokenInitDataHasAlreadyBeenSet(); /// @dev error throw if there is an attempt to set zero decimals. error FrictionlessDigitalSecurityTokenZeroDecimals(); /** * @dev Sets the immutable data for the `FrictionlessDigitalSecurityToken` * @param initData the immutable data for the `FrictionlessDigitalSecurityToken` */ function setInitData(FDSImmutableData calldata initData) external; /** * @dev Sets the updatable data for the `FrictionlessDigitalSecurityToken` * @param mutableData the updatable data for the `FrictionlessDigitalSecurityToken` */ function setUpdateData(FDSMutableData calldata mutableData) external; /** * @dev Sets the custodian URI for the token * @param custodianURI the custodian URI for the token */ function setCustodianURI(string calldata custodianURI) external; /** * @dev Sets the decimals value for the token * @param decimals the decimals value for the token */ function setDecimals(uint8 decimals) external; /** * @dev Get the baseCurrency is the FIAT denomination of the digital security, this is the currency the `FrictionlessOnChainAssetToken` is issued in. * @return the baseCurrency is the FIAT denomination of the digital security, this is the currency the `FrictionlessOnChainAssetToken` is issued in. */ function getCurrency() external view returns (string memory); /** * @dev Get the type of the token as defined in the enum `FrictionlessDigitalSecurityTokenType`. * @return the type of the token as defined in the enum. */ function getTokenType() external view returns (FrictionlessDigitalSecurityTokenType); /** * @dev Get the onChainAssetAddress the address of the `FrictionlessOnChainAssetToken` for which this token is a future cash distribution. * @return onChainAssetAddress the address of the `FrictionlessOnChainAssetToken` for which this token is a future cash distribution. */ function getOnChainAssetAddress() external view returns (address); /** * @dev Get the maturity date of the digital security. * @return the maturity date of the digital security. */ function getMaturesOn() external view returns (uint256); /** * @dev Returns the custodian URI of the token */ function custodianURI() external view returns (string memory); }
// SPDX-License-Identifier: MIT /** * Copyright © 2024 Frictionless Group Holdings S.à.r.l * * Permission is hereby granted, free of charge, to any person obtaining a copy of the Frictionless protocol smart contracts * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies * or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL FRICTIONLESS GROUP * HOLDINGS S.à.r.l OR AN OF ITS SUBSIDIARIES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ pragma solidity ^0.8.16; import { IBasicFrictionlessToken } from "@interface/IBasicFrictionlessToken.sol"; /** * @title FrictionlessFundDepositToken - A Fund Deposit Token represents a permissioned Investors FIAT contribution to a specific fund IBAN in a denominated FIAT currency. * @author Frictionless Group Holdings S.à.r.l * @notice A Fund Deposit Token represents a permissioned Investors FIAT contribution to a specific fund IBAN in a denominated FIAT currency. * The Fund Deposit Token is used as a means of payment and settlement. The Fund Deposit Token can only be transferred between permissioned Investors in the fund. * A daily attestation of the fund IBAN serves to prove the 1:1 backing with FIAT. * Exclusively under Frictionless Markets S.à.r.l issuance terms Investors holding a `FrictionlessFundDepositToken` have the legal right to the FIAT value held in the fund IBAN account. */ interface IFrictionlessFundDepositToken is IBasicFrictionlessToken { /** * @dev Struct which represents the immutable data in the Token. Once set it cannot be modified. * @param currency the FIAT denomination of the deposit token. * @param description the description of the deposit token * @param fundIBAN the IBAN which Frictionless Markets S.à.r.l holds a matching FIAT currency ledger with a G-SIB for this currency, attestations are provided on this IBAN. */ struct FFDImmutableData { string currency; string description; string fundIBAN; } /// @dev error throw if there is an attempt to modify the immutable data. error FrictionlessFundDepositTokenUnableToUpdateInitData(); /** * @dev Sets the immutable data for the `FrictionlessFundDepositToken` * @param initData the immutable data for the `FrictionlessFundDepositToken` */ function setInitData(FFDImmutableData calldata initData) external; /** * @dev Get the currency the FIAT denomination of the deposit token. * @return the currency the FIAT denomination of the deposit token. */ function getCurrency() external view returns (string memory); /** * @dev Get the description the description of the deposit token. * @return the description the description of the deposit token */ function getDescription() external view returns (string memory); /** * @dev Get the IBAN which Frictionless Markets S.à.r.l holds a matching FIAT currency ledger with a G-SIB for this currency, attestations are provided on this IBAN. * This is restricted to onlyAgent roles. * @return the IBAN which Frictionless Markets S.à.r.l holds a matching FIAT currency ledger with a G-SIB for this currency, attestations are provided on this IBAN. */ function getFundIBAN() external returns (string memory); }
// SPDX-License-Identifier: MIT /** * Copyright © 2024 Frictionless Group Holdings S.à.r.l * * Permission is hereby granted, free of charge, to any person obtaining a copy of the Frictionless protocol smart contracts * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies * or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL FRICTIONLESS GROUP * HOLDINGS S.à.r.l OR AN OF ITS SUBSIDIARIES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ pragma solidity ^0.8.16; import { IBasicFrictionlessToken } from "@interface/IBasicFrictionlessToken.sol"; /** * @title FrictionlessOnChainAssetToken is the extension of the ERC-3643 Token to represent OnChain Assets * @author Frictionless Group Holdings S.à.r.l * @notice Implementation of the storage of the underlying OnChain Asset and it's data. */ interface IFrictionlessOnChainAssetToken is IBasicFrictionlessToken { /// @dev Enum for the schedule of the payments by the Manager, either pro_rat or coupon/bullet style. enum FrictionlessOnChainAssetSchedule { // The Manager will make payments for the `FrictionlessOnChainAssetToken` on an coupon_only basis, with a bullet payment for the principal investment. SCHEDULE_COUPON_ONLY, // The Manager will make pro-rata payments for the `FrictionlessOnChainAssetToken` for both the principal investment and the coupon. SCHEDULE_PRO_RATA } /// @dev Enum for the periodicity of payments by the Manager enum FrictionlessOnChainAssetPaymentFrequency { // Payments from the Manager for the `FrictionlessOnChainAssetToken` are made daily PAYMENT_FREQUENCY_DAILY, // Payments from the Manager for the `FrictionlessOnChainAssetToken` are made weekly PAYMENT_FREQUENCY_WEEKLY, // Payments from the Manager for the `FrictionlessOnChainAssetToken` are made monthly PAYMENT_FREQUENCY_MONTHLY, // Payments from the Manager for the `FrictionlessOnChainAssetToken` are made quarterly PAYMENT_FREQUENCY_QUARTERLY, // Payments from the Manager for the `FrictionlessOnChainAssetToken` are made semi-annually PAYMENT_FREQUENCY_SEMI_ANNUALLY, // Payments from the Manager for the `FrictionlessOnChainAssetToken` are made annually PAYMENT_FREQUENCY_ANNUALLY, // Payments from the Manager for the `FrictionlessOnChainAssetToken` are made once PAYMENT_FREQUENCY_SINGLE } /// @dev Enum for the yield for this `FrictionlessOnChainAssetToken` is a fixed/floating rate enum FrictionlessOnChainAssetYieldType { // The yield for this `FrictionlessOnChainAssetToken` is a fixed rate YIELD_FIXED, // The yield for this `FrictionlessOnChainAssetToken` is a floating rate YIELD_FLOATING } /// @dev Enum for the price quote status obtained at auction enum FrictionlessOnChainAssetPriceStatus { // The `FrictionlessOnChainAssetToken` did not receive enough offers at the offer price PRICE_QUOTE_STATUS_UNDER_SUBSCRIBED, // The aggregate bid at auction matched the offer PRICE_QUOTE_STATUS_PRICED_AT_PAR, // The aggregate bid at auction is lower than the offer PRICE_QUOTE_STATUS_PRICED_AT_DISCOUNT, // The aggregate bid at auction is higher than the offer PRICE_QUOTE_STATUS_PRICED_AT_PREMIUM } /// @dev Enum for the current status of the `FrictionlessOnChainAssetToken`. Updated over time by the Treasury enum FrictionlessOnChainAssetStatus { // Status reserved for `FrictionlessOnChainAssetToken` that are MINTED onChain STATUS_MINTED, // Status reserved for `FrictionlessOnChainAssetToken` that are fully purchased, which means they have minted the digital securities. STATUS_PURCHASED, // Status reserved for `FrictionlessOnChainAssetToken` that have reached their maturity event STATUS_MATURED, // Status reserved for `FrictionlessOnChainAssetToken` that are in an impaired state. The parValue may be affected. STATUS_IMPAIRED, // Status reserved for `FrictionlessOnChainAssetToken` that are fully matured and have been fully redeemed. STATUS_REDEEMED } /// @dev Enum for the current S&P style riskGrade of the `FrictionlessOnChainAssetToken`. Updated over time by the Manager/Treasury/Risk Oracle. enum FrictionlessOnChainAssetRiskGrade { BER_AAA, BER_AA, BER_A, BER_BBB, BER_BB, BER_B, BER_CCC, BER_CC, BER_C, BER_D, BER_UNRATED } /** * @dev The specification data for the `FrictionlessOnChainAssetToken`, this is an immutable data struct. * @param issuedOn the date this `FrictionlessOnChainAssetToken` is issued by the legal Issuer, Frictionless Markets S.à.r.l * @param maturityDays the number of days to maturity for this `FrictionlessOnChainAssetToken` * @param schedule the schedule of the payments by the Manager, either pro_rat or coupon/bullet style. * @param paymentFrequency the periodicity of payments by the Manager * @param yieldType the yield for this `FrictionlessOnChainAssetToken` is a fixed/floating rate * @param baseCurrency the currrency the `FrictionlessOnChainAssetToken` is issued in. * @param stripTotal the principal amount for the `FrictionlessOnChainAssetToken` * @param name the name for the `FrictionlessOnChainAssetToken` * @param symbol the ticker symbol for the `FrictionlessOnChainAssetToken` */ struct FOCASpecData { uint256 issuedOn; uint256 maturityDays; FrictionlessOnChainAssetSchedule schedule; FrictionlessOnChainAssetPaymentFrequency paymentFrequency; FrictionlessOnChainAssetYieldType yieldType; string baseCurrency; uint256 stripTotal; string name; string symbol; } /** * @dev The issuance data for the `FrictionlessOnChainAssetToken`, this is an immutable data struct. * @param auctionedOn the date this `FrictionlessOnChainAssetToken` is auctioned by the legal Issuer, Frictionless Markets S.à.r.l * @param priceQuoteStatus the price quote status obtained at auction * @param onChainAssetUUID the off-chain UUID in the graphQL for the token * @param issuerUUID the off-chain UUID in the graphQL for the Manager issuing via the legal Issuer, Frictionless Markets S.à.r.l * @param isin the ISIN numbre or equivalent for the `FrictionlessOnChainAssetToken` * @param issuanceDocs the location of the issuance docs accessible via URI or the hash of the issuance docs. * @param assetClass the Managers/Issuers definition of the underlying asset class for the `FrictionlessOnChainAssetToken` */ struct FOCAIssuanceData { uint256 auctionedOn; FrictionlessOnChainAssetPriceStatus priceQuoteStatus; string onChainAssetUUID; string issuerUUID; string isin; string issuanceDocs; string assetClass; } /** * @dev The uopdatable data for the `FrictionlessOnChainAssetToken`. * @param maturesOn the date this `FrictionlessOnChainAssetToken` fully matures. Updatable if the underlying fund is extended. * @param total the total value of the `FrictionlessOnChainAssetToken` (strip + yield over time). Updatable based on Manager IRRs, totalReturn, etc. * @param status the current status of the `FrictionlessOnChainAssetToken`. Updated over time by the Treasury * @param yield the current yield being paid on the `FrictionlessOnChainAssetToken`. Updated over time by the Manager/Calculating Agent. * @param riskGrade the current riskGrade of the `FrictionlessOnChainAssetToken`. Updated over time by the Manager/Treasury/Risk Oracle. * @param pullToParValue the calculation of the pullToPar value of this `FrictionlessOnChainAssetToken`. Updated over time by the Manager/Calculating Agent * @param custodianAddress the address of the custodian for the `FrictionlessOnChainAssetToken` */ struct FOCAUpdateData { uint256 maturesOn; uint256 total; FrictionlessOnChainAssetStatus status; uint256 yield; FrictionlessOnChainAssetRiskGrade riskGrade; uint256 pullToParValue; address custodianAddress; } /// @dev error throw if there is an attempt to modify the immutable data. error FrictionlessOnChainAssetTokenUnableToUpdateData(); /** * @dev Sets the specData data for the `FrictionlessOnChainAssetToken`. * throws `FrictionlessOnChainAssetTokenUnableToUpdateData` This data is immutable, an attempt to modify will generate the error `FrictionlessOnChainAssetTokenUnableToUpdateData` * @param specData the specData data for the `FrictionlessOnChainAssetToken` */ function setSpecificationData(FOCASpecData calldata specData) external; /** * @dev Sets the issuanceData data for the `FrictionlessOnChainAssetToken` * throws `FrictionlessOnChainAssetTokenUnableToUpdateData` This data is immutable, an attempt to modify will generate the error `FrictionlessOnChainAssetTokenUnableToUpdateData` * @param issuanceData the updatable data for the `FrictionlessOnChainAssetToken` */ function setIssuanceData(FOCAIssuanceData calldata issuanceData) external; /** * @dev Sets the updatable data for the `FrictionlessOnChainAssetToken` * @param updateData the updatable data for the `FrictionlessOnChainAssetToken` */ function setUpdateData(FOCAUpdateData calldata updateData) external; /** * @dev Get the specData data for the `FrictionlessOnChainAssetToken`. * @return the specData data for the `FrictionlessOnChainAssetToken` */ function getSpecificationData() external view returns (FOCASpecData memory); /** * @dev Get the issuanceData data for the `FrictionlessOnChainAssetToken`. * @return the issuanceData data for the `FrictionlessOnChainAssetToken` */ function getIssuanceData() external view returns (FOCAIssuanceData memory); /** * @dev Get the updateData data for the `FrictionlessOnChainAssetToken`. * @return the updateData data for the `FrictionlessOnChainAssetToken` */ function getUpdateData() external view returns (FOCAUpdateData memory); /** * @dev Get the currency the `FrictionlessOnChainAssetToken` is issued in. * @return the currency the `FrictionlessOnChainAssetToken` is issued in. */ function getCurrency() external view returns (string memory); }
// SPDX-License-Identifier: MIT /** * Copyright © 2024 Frictionless Group Holdings S.à.r.l * * Permission is hereby granted, free of charge, to any person obtaining a copy of the Frictionless protocol smart contracts * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies * or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL FRICTIONLESS GROUP * HOLDINGS S.à.r.l OR AN OF ITS SUBSIDIARIES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ pragma solidity ^0.8.16; import { IFrictionlessDigitalSecurityToken } from "@interface/IFrictionlessDigitalSecurityToken.sol"; import { IFrictionlessFundDepositToken } from "@interface/IFrictionlessFundDepositToken.sol"; import { IFrictionlessOnChainAssetToken } from "@interface/IFrictionlessOnChainAssetToken.sol"; import { IBasicFrictionlessToken } from "@interface/IBasicFrictionlessToken.sol"; /** * @title IFrictionlessComplianceFactory - Interface defining the token factory for all tokens in the Frictionless protocol. * @author Frictionless Group Holdings S.à.r.l * @notice Interface defining the token factory for all tokens in the Frictionless protocol. */ interface IFrictionlessTokensFactory { /** * @dev Struct to represent the base contract data to deploy a Frictionless token contract. * @param implementationAuthority the address of the implementationAuthority contract * @param identityRegistry the address of the OnChainId IdentityRegistry contract * @param compliance the address of the relevant compliance contract for the given Frictionless token. * @param onChainId the address of the onChainId of the PROTOCOL_ADMIN * @param tokenName the name of the token * @param tokenSymbol the ticker for the token */ struct BaseTokenInitParams { address implementationAuthority; address identityRegistry; address compliance; address onChainId; string tokenName; string tokenSymbol; } /// @dev error thrown if an attempt to set a zero address contract during function `setTreasuryManager` error FrictionlessTokensFactoryZeroAddress(); /// @dev error thrown if the `msg.sender` is not the treasury manager during the functions `deployFundDepositToken`, `deployDigitalSecurityToken`, or `deployOnChainAssetToken` error FrictionlessTokensFactoryNotATreasuryManager(address); /** * @dev Event emitted upon successful deployment of a compliance contract. * @param tokenType The Frictionless token type as defined by `IBasicFrictionlessToken.FrictionlessTokenTypes` * @param newTokenContract The token contract to deploy */ event FrictionlessTokenDeployed( IBasicFrictionlessToken.FrictionlessTokenTypes indexed tokenType, address newTokenContract ); /** * @dev Sets the Treasury Manager to be the specified address. * @param newTreasuryManager_ the addresses of the treasury manager to set * throws `FrictionlessTokensFactoryZeroAddress` if the newTreasuryManager_ is a zero address */ function setTreasuryManager(address newTreasuryManager_) external; /** * @dev Deploys the `FrictionlessFundDepositToken` contract as a proxy * @param tokenOwner_ The owner of the deployed contract * @param baseTokenInitParams_ the base contract data to deploy a Frictionless token contract * @param initData_ the immutable data for the `FrictionlessFundDepositToken` * @return tokenProxyAddr_ the address of the deployed token contract `FrictionlessFundDepositToken` * throws `FrictionlessTokensFactoryNotATreasuryManager` if the msg.sender is not the treasury manager * emits `FrictionlessTokenDeployed` event upon successful deployment of the token contract. */ function deployFundDepositToken( address tokenOwner_, BaseTokenInitParams calldata baseTokenInitParams_, IFrictionlessFundDepositToken.FFDImmutableData calldata initData_ ) external returns (address tokenProxyAddr_); /** * @dev Deploys the `FrictionlessDigitalSecurityToken` contract as a proxy * @param tokenOwner_ The owner of the deployed contract * @param baseTokenInitParams_ the base contract data to deploy a Frictionless token contract * @param initData_ the immutable data for the `FrictionlessDigitalSecurityToken` * @param updateData_ the mutable data for the `FrictionlessDigitalSecurityToken` * @return tokenProxyAddr_ the address of the deployed token contract `FrictionlessDigitalSecurityToken` * throws `FrictionlessTokensFactoryNotATreasuryManager` if the msg.sender is not the treasury manager * emits `FrictionlessTokenDeployed` event upon successful deployment of the token contract. */ function deployDigitalSecurityToken( address tokenOwner_, BaseTokenInitParams calldata baseTokenInitParams_, IFrictionlessDigitalSecurityToken.FDSImmutableData calldata initData_, IFrictionlessDigitalSecurityToken.FDSMutableData calldata updateData_ ) external returns (address tokenProxyAddr_); /** * @dev Deploys the `FrictionlessOnChainAssetToken` contract as a proxy * @param tokenOwner_ The owner of the deployed contract * @param baseTokenInitParams_ the base contract data to deploy a Frictionless token contract * @param specData_ the immutable specification data for the `FrictionlessOnChainAssetToken` * @param issuanceData_ the immutable issuance data for the `FrictionlessOnChainAssetToken` * @param updateData_ the mutable update data for the `FrictionlessOnChainAssetToken` * @return tokenProxyAddr_ the address of the deployed token contract `FrictionlessOnChainAssetToken` * throws `FrictionlessTokensFactoryNotATreasuryManager` if the msg.sender is not the treasury manager * emits `FrictionlessTokenDeployed` event upon successful deployment of the token contract. */ function deployOnChainAssetToken( address tokenOwner_, BaseTokenInitParams calldata baseTokenInitParams_, IFrictionlessOnChainAssetToken.FOCASpecData calldata specData_, IFrictionlessOnChainAssetToken.FOCAIssuanceData calldata issuanceData_, IFrictionlessOnChainAssetToken.FOCAUpdateData calldata updateData_ ) external returns (address tokenProxyAddr_); /** * @dev returns the address of the treasuryManager * @return the address of the treasuryManager */ function treasuryManager() external view returns (address); /** * @dev Checks whether a given token address is an existing frictionless token * @param tokenAddr_ the address of the token to check * @return A boolean indicating whether the token is an existing frictionless token */ function existingFrictionlessTokens(address tokenAddr_) external view returns (bool); }
// SPDX-License-Identifier: MIT /** * Copyright © 2024 Frictionless Group Holdings S.à.r.l * * Permission is hereby granted, free of charge, to any person obtaining a copy of the Frictionless protocol smart contracts * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies * or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL FRICTIONLESS GROUP * HOLDINGS S.à.r.l OR AN OF ITS SUBSIDIARIES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ pragma solidity ^0.8.16; import { TokenProxy } from "@ERC-3643/proxy/TokenProxy.sol"; import { ITREXImplementationAuthority } from "@ERC-3643/proxy/authority/ITREXImplementationAuthority.sol"; import { IBasicFrictionlessToken } from "@interface/IBasicFrictionlessToken.sol"; import { IFrictionlessFundDepositToken } from "@interface/IFrictionlessFundDepositToken.sol"; /** * @title FrictionlessFundDeposit - TokenProxy the implementation of the `IFrictionlessFundDepositToken` * @author Frictionless Group Holdings S.à.r.l * @notice See {IFrictionlessFundDepositToken} {FrictionlessFundDepositToken} */ contract FrictionlessFundDeposit is TokenProxy { /// @dev throws if setting the frictionless token type fails. error FrictionlessFundDepositSetFrictionlessTokenTypeFailed(); /// @dev throws if setting the initial immutable values based on the FCD issued state fails. error FrictionlessFundDepositSetInitDataFailed(); /// @dev instantiates the TokenProxy and sets the relevant token data, including the symbol, the precision, etc. constructor( address implementationAuthority_, address identityRegistry_, address compliance_, address onChainId_, string memory name_, string memory symbol_, IFrictionlessFundDepositToken.FFDImmutableData memory initData_ ) TokenProxy(implementationAuthority_, identityRegistry_, compliance_, name_, symbol_, 6, onChainId_) { address logic_ = (ITREXImplementationAuthority(getImplementationAuthority())).getTokenImplementation(); /// @dev Set the Frictionless token type (bool setTypeSuccess_, ) = logic_.delegatecall( abi.encodeWithSelector( IBasicFrictionlessToken.setFrictionlessTokenType.selector, IBasicFrictionlessToken.FrictionlessTokenTypes.FUND_DEPOSIT_TOKEN ) ); if (!setTypeSuccess_) { revert FrictionlessFundDepositSetFrictionlessTokenTypeFailed(); } /// @dev Set the immutable values (bool initSuccess_, ) = logic_.delegatecall( abi.encodeWithSelector(IFrictionlessFundDepositToken.setInitData.selector, initData_) ); if (!initSuccess_) { revert FrictionlessFundDepositSetInitDataFailed(); } } }
// SPDX-License-Identifier: MIT /** * Copyright © 2024 Frictionless Group Holdings S.à.r.l * * Permission is hereby granted, free of charge, to any person obtaining a copy of the Frictionless protocol smart contracts * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies * or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL FRICTIONLESS GROUP * HOLDINGS S.à.r.l OR AN OF ITS SUBSIDIARIES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ pragma solidity ^0.8.16; import { TokenProxy } from "@ERC-3643/proxy/TokenProxy.sol"; import { ITREXImplementationAuthority } from "@ERC-3643/proxy/authority/ITREXImplementationAuthority.sol"; import { IBasicFrictionlessToken } from "@interface/IBasicFrictionlessToken.sol"; import { IFrictionlessDigitalSecurityToken } from "@interface/IFrictionlessDigitalSecurityToken.sol"; /** * @title FrictionlessDigitalSecurity - TokenProxy the implementation of the IFrictionlessDigitalSecurityToken * @author Frictionless Group Holdings S.à.r.l * @notice See {IFrictionlessDigitalSecurityToken} {FrictionlessDigitalSecurityToken} */ contract FrictionlessDigitalSecurity is TokenProxy { /// @dev throws if setting the frictionless token type fails. error FrictionlessDigitalSecuritySetFrictionlessTokenTypeFailed(); /// @dev throws if setting the initial immutable values based on the FCD issued state fails. error FrictionlessDigitalSecuritySetInitDataFailed(); /// @dev throws if setting the initial updatable values based on the FCD issued state fails. error FrictionlessDigitalSecuritySetUpdateDataFailed(); /// @dev instantiates the TokenProxy and sets the relevant token data, including the symbol, the precision, etc. constructor( address implementationAuthority_, address identityRegistry_, address compliance_, address onChainId_, string memory name_, string memory symbol_, IFrictionlessDigitalSecurityToken.FDSImmutableData memory initData_, IFrictionlessDigitalSecurityToken.FDSMutableData memory updateData_ ) TokenProxy(implementationAuthority_, identityRegistry_, compliance_, name_, symbol_, 6, onChainId_) { address logic_ = (ITREXImplementationAuthority(getImplementationAuthority())).getTokenImplementation(); /// @dev Set the Frictionless token type (bool setTypeSuccess_, ) = logic_.delegatecall( abi.encodeWithSelector( IBasicFrictionlessToken.setFrictionlessTokenType.selector, IBasicFrictionlessToken.FrictionlessTokenTypes.DIGITAL_SECURITY_TOKEN ) ); if (!setTypeSuccess_) { revert FrictionlessDigitalSecuritySetFrictionlessTokenTypeFailed(); } /// @dev Set the initial immutable values based on the FCD issued state. (bool initSuccess_, ) = logic_.delegatecall( abi.encodeWithSelector(IFrictionlessDigitalSecurityToken.setInitData.selector, initData_) ); if (!initSuccess_) { revert FrictionlessDigitalSecuritySetInitDataFailed(); } /// @dev Set the initial updatable values based on the FCD issued state. (bool updateSuccess_, ) = logic_.delegatecall( abi.encodeWithSelector(IFrictionlessDigitalSecurityToken.setUpdateData.selector, updateData_) ); if (!updateSuccess_) { revert FrictionlessDigitalSecuritySetUpdateDataFailed(); } } }
// SPDX-License-Identifier: MIT /** * Copyright © 2024 Frictionless Group Holdings S.à.r.l * * Permission is hereby granted, free of charge, to any person obtaining a copy of the Frictionless protocol smart contracts * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies * or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL FRICTIONLESS GROUP * HOLDINGS S.à.r.l OR AN OF ITS SUBSIDIARIES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ pragma solidity ^0.8.16; import { TokenProxy } from "@ERC-3643/proxy/TokenProxy.sol"; import { ITREXImplementationAuthority } from "@ERC-3643/proxy/authority/ITREXImplementationAuthority.sol"; import { IBasicFrictionlessToken } from "@interface/IBasicFrictionlessToken.sol"; import { IFrictionlessOnChainAssetToken } from "@interface/IFrictionlessOnChainAssetToken.sol"; /** * @title FrictionlessOnChainAsset - TokenProxy the implementation of the `IFrictionlessOnChainAssetToken` * @author Frictionless Group Holdings S.à.r.l * @notice See {IFrictionlessOnChainAssetToken} {FrictionlessOnChainAssetToken} */ contract FrictionlessOnChainAsset is TokenProxy { /// @dev throws if setting the frictionless token type fails. error FrictionlessOnChainAssetSetFrictionlessTokenTypeFailed(); /// @dev throws if setting specification data fails. error FrictionlessOnChainAssetSetSpecificationDataFailed(); /// @dev throws if setting issuance data fails. error FrictionlessOnChainAssetSetIssuanceDataFailed(); /// @dev throws if setting update data fails. error FrictionlessOnChainAssetSetUpdateDataFailed(); /// @dev instantiates the TokenProxy and sets the relevant token data, including the symbol, the precision, etc. constructor( address implementationAuthority_, address identityRegistry_, address compliance_, address onChainId_, IFrictionlessOnChainAssetToken.FOCASpecData memory specData_, IFrictionlessOnChainAssetToken.FOCAIssuanceData memory issuanceData_, IFrictionlessOnChainAssetToken.FOCAUpdateData memory updateData_ ) TokenProxy( implementationAuthority_, identityRegistry_, compliance_, specData_.name, specData_.symbol, 6, onChainId_ ) { address logic_ = (ITREXImplementationAuthority(getImplementationAuthority())).getTokenImplementation(); /// @dev Set the Frictionless token type (bool setTypeSuccess_, ) = logic_.delegatecall( abi.encodeWithSelector( IBasicFrictionlessToken.setFrictionlessTokenType.selector, IBasicFrictionlessToken.FrictionlessTokenTypes.ON_CHAIN_ASSET_TOKEN ) ); if (!setTypeSuccess_) { revert FrictionlessOnChainAssetSetFrictionlessTokenTypeFailed(); } /// @dev Set the initial immutable values based on the OnChainAssets issued state. (bool specSuccess_, ) = logic_.delegatecall( abi.encodeWithSelector(IFrictionlessOnChainAssetToken.setSpecificationData.selector, specData_) ); if (!specSuccess_) { revert FrictionlessOnChainAssetSetSpecificationDataFailed(); } /// @dev Set the issuance values based on the OnChainAssets issued state. (bool issuanceSuccess_, ) = logic_.delegatecall( abi.encodeWithSelector(IFrictionlessOnChainAssetToken.setIssuanceData.selector, issuanceData_) ); if (!issuanceSuccess_) { revert FrictionlessOnChainAssetSetIssuanceDataFailed(); } /// @dev Set the initial mutable values based on the OnChainAssets at time of issuance. (bool updateSuccess_, ) = logic_.delegatecall( abi.encodeWithSelector(IFrictionlessOnChainAssetToken.setUpdateData.selector, updateData_) ); if (!updateSuccess_) { revert FrictionlessOnChainAssetSetUpdateDataFailed(); } } }
// SPDX-License-Identifier: MIT /** * Copyright © 2024 Frictionless Group Holdings S.à.r.l * * Permission is hereby granted, free of charge, to any person obtaining a copy of the Frictionless protocol smart contracts * (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies * or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL FRICTIONLESS GROUP * HOLDINGS S.à.r.l OR AN OF ITS SUBSIDIARIES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ pragma solidity ^0.8.16; import { IToken } from "@ERC-3643/token/IToken.sol"; /** * @title IBasicFrictionlessToken - Represents the base interface for Frictionless protocol tokens. * @author Frictionless Group Holdings S.à.r.l * @notice The IBasicFrictionlessToken Represents the base interface for Frictionless protocol tokens, this interface is used to determine a token type. */ interface IBasicFrictionlessToken is IToken { /** * @dev Enumeration to represent each of the tokens in the Frictionless protocol. */ enum FrictionlessTokenTypes { NONE, FUND_DEPOSIT_TOKEN, // IFrictionlessFundDepositToken DIGITAL_SECURITY_TOKEN, // IFrictionlessDigitalSecurityToken ON_CHAIN_ASSET_TOKEN // IFrictionlessOnChainAssetToken } /// @dev error thrown if an attempt to set an invalid token type during function `setFrictionlessTokenType` error BasicFrictionlessTokenUnableToUpdateFrictionlessTokenType(); /** * @dev Sets the token type according to the specified enumeration * @param newTokenType_ the token type to set */ function setFrictionlessTokenType(FrictionlessTokenTypes newTokenType_) external; /** * @dev Returns the token type according to the specified enumeration * @return FrictionlessTokenTypes the token type according to the specified enumeration */ function getFrictionlessTokenType() external view returns (FrictionlessTokenTypes); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../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; } /** * @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.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: GPL-3.0 // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= // :=*%@@@#=. :#@@% *@@@%= // .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- // :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. // -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ // =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- // -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: // :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. // %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. // #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ // *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- // -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: // .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- // -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- // -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# // *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- // +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: // =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: // .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. // +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. // -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. // ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. // @@@@@@+. +@@*. .+@@@@@%=. // -@@@@@= =@@%: -#@@@@%+. // +@@@@@. =@@@= .+@@@@@*: // #@@@@#:%@@#. :*@@@@#- // @@@@@%@@@= :#@@@@+. // :@@@@@@@#.:#@@@%- // +@@@@@@-.*@@@*: // #@@@@#.=@@@+. // @@@@+-%@%= // :@@@#%@%= // +@@@@%- // :#%%= // /** * NOTICE * * The T-REX software is licensed under a proprietary license or the GPL v.3. * If you choose to receive it under the GPL v.3 license, the following applies: * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * * Copyright (C) 2023, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity 0.8.17; /** * @title Roles * @dev Library for managing addresses assigned to a Role. */ library Roles { struct Role { mapping(address => bool) bearer; } /** * @dev Give an account access to this role. */ function add(Role storage role, address account) internal { require(!has(role, account), "Roles: account already has role"); role.bearer[account] = true; } /** * @dev Remove an account's access to this role. */ function remove(Role storage role, address account) internal { require(has(role, account), "Roles: account does not have role"); role.bearer[account] = false; } /** * @dev Check if an account has this role. * @return bool */ function has(Role storage role, address account) internal view returns (bool) { require(account != address(0), "Roles: account is the zero address"); return role.bearer[account]; } }
// SPDX-License-Identifier: GPL-3.0 // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= // :=*%@@@#=. :#@@% *@@@%= // .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- // :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. // -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ // =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- // -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: // :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. // %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. // #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ // *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- // -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: // .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- // -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- // -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# // *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- // +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: // =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: // .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. // +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. // -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. // ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. // @@@@@@+. +@@*. .+@@@@@%=. // -@@@@@= =@@%: -#@@@@%+. // +@@@@@. =@@@= .+@@@@@*: // #@@@@#:%@@#. :*@@@@#- // @@@@@%@@@= :#@@@@+. // :@@@@@@@#.:#@@@%- // +@@@@@@-.*@@@*: // #@@@@#.=@@@+. // @@@@+-%@%= // :@@@#%@%= // +@@@@%- // :#%%= // /** * NOTICE * * The T-REX software is licensed under a proprietary license or the GPL v.3. * If you choose to receive it under the GPL v.3 license, the following applies: * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * * Copyright (C) 2023, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity 0.8.17; import "./AbstractProxy.sol"; contract TokenProxy is AbstractProxy { constructor( address implementationAuthority, address _identityRegistry, address _compliance, string memory _name, string memory _symbol, uint8 _decimals, // _onchainID can be 0 address if the token has no ONCHAINID, ONCHAINID can be set later by the token Owner address _onchainID ) { require( implementationAuthority != address(0) && _identityRegistry != address(0) && _compliance != address(0) , "invalid argument - zero address"); require( keccak256(abi.encode(_name)) != keccak256(abi.encode("")) && keccak256(abi.encode(_symbol)) != keccak256(abi.encode("")) , "invalid argument - empty string"); require(0 <= _decimals && _decimals <= 18, "decimals between 0 and 18"); _storeImplementationAuthority(implementationAuthority); emit ImplementationAuthoritySet(implementationAuthority); address logic = (ITREXImplementationAuthority(getImplementationAuthority())).getTokenImplementation(); // solhint-disable-next-line avoid-low-level-calls (bool success, ) = logic.delegatecall( abi.encodeWithSignature( "init(address,address,string,string,uint8,address)", _identityRegistry, _compliance, _name, _symbol, _decimals, _onchainID ) ); require(success, "Initialization failed."); } // solhint-disable-next-line no-complex-fallback fallback() external payable { address logic = (ITREXImplementationAuthority(getImplementationAuthority())).getTokenImplementation(); // solhint-disable-next-line no-inline-assembly assembly { calldatacopy(0x0, 0x0, calldatasize()) let success := delegatecall(sub(gas(), 10000), logic, 0x0, calldatasize(), 0, 0) let retSz := returndatasize() returndatacopy(0, 0, retSz) switch success case 0 { revert(0, retSz) } default { return(0, retSz) } } } }
// SPDX-License-Identifier: GPL-3.0 // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= // :=*%@@@#=. :#@@% *@@@%= // .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- // :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. // -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ // =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- // -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: // :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. // %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. // #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ // *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- // -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: // .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- // -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- // -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# // *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- // +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: // =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: // .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. // +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. // -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. // ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. // @@@@@@+. +@@*. .+@@@@@%=. // -@@@@@= =@@%: -#@@@@%+. // +@@@@@. =@@@= .+@@@@@*: // #@@@@#:%@@#. :*@@@@#- // @@@@@%@@@= :#@@@@+. // :@@@@@@@#.:#@@@%- // +@@@@@@-.*@@@*: // #@@@@#.=@@@+. // @@@@+-%@%= // :@@@#%@%= // +@@@@%- // :#%%= // /** * NOTICE * * The T-REX software is licensed under a proprietary license or the GPL v.3. * If you choose to receive it under the GPL v.3 license, the following applies: * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * * Copyright (C) 2023, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity 0.8.17; interface ITREXImplementationAuthority { /// types struct TREXContracts { // address of token implementation contract address tokenImplementation; // address of ClaimTopicsRegistry implementation contract address ctrImplementation; // address of IdentityRegistry implementation contract address irImplementation; // address of IdentityRegistryStorage implementation contract address irsImplementation; // address of TrustedIssuersRegistry implementation contract address tirImplementation; // address of ModularCompliance implementation contract address mcImplementation; } struct Version { // major version uint8 major; // minor version uint8 minor; // patch version uint8 patch; } /// events /// event emitted when a new TREX version is added to the contract memory event TREXVersionAdded(Version indexed version, TREXContracts indexed trex); /// event emitted when a new TREX version is fetched from reference contract by auxiliary contract event TREXVersionFetched(Version indexed version, TREXContracts indexed trex); /// event emitted when the current version is updated event VersionUpdated(Version indexed version); /// event emitted by the constructor when the IA is deployed event ImplementationAuthoritySet(bool referenceStatus, address trexFactory); /// event emitted when the TREX factory address is set event TREXFactorySet(address indexed trexFactory); /// event emitted when the IA factory address is set event IAFactorySet(address indexed iaFactory); /// event emitted when a token issuer decides to change current IA for a new one event ImplementationAuthorityChanged(address indexed _token, address indexed _newImplementationAuthority); /// functions /** * @dev allows to fetch a TREX version available on the reference contract * can be called only from auxiliary contracts, not on reference (main) contract * throws if the version was already fetched * adds the new version on the local storage * allowing the update of contracts through the `useTREXVersion` afterwards */ function fetchVersion(Version calldata _version) external; /** * @dev setter for _trexFactory variable * _trexFactory is set at deployment for auxiliary contracts * for main contract it must be set post-deployment as main IA is * deployed before the TREXFactory. * @param trexFactory the address of TREXFactory contract * emits a TREXFactorySet event * only Owner can call * can be called only on main contract, auxiliary contracts cannot call */ function setTREXFactory(address trexFactory) external; /** * @dev setter for _iaFactory variable * _iaFactory is set at zero address for auxiliary contracts * for main contract it can be set post-deployment or at deployment * in the constructor * @param iaFactory the address of IAFactory contract * emits a IAFactorySet event * only Owner can call * can be called only on main contract, auxiliary contracts cannot call */ function setIAFactory(address iaFactory) external; /** * @dev adds a new Version of TREXContracts to the mapping * only callable on the reference contract * only Owner can call this function * @param _version the new version to add to the mapping * @param _trex the list of contracts corresponding to the new version * _trex cannot contain zero addresses * emits a `TREXVersionAdded` event */ function addTREXVersion(Version calldata _version, TREXContracts calldata _trex) external; /** * @dev updates the current version in use by the proxies * variation of the `useTREXVersion` allowing to use a new version * this function calls in a single transaction the `addTREXVersion` * and the `useTREXVersion` using an existing version * @param _version the version to use * @param _trex the set of contracts corresponding to the version * only Owner can call (check performed in addTREXVersion) * only reference contract can call (check performed in addTREXVersion) * emits a `TREXVersionAdded`event * emits a `VersionUpdated` event */ function addAndUseTREXVersion(Version calldata _version, TREXContracts calldata _trex) external; /** * @dev updates the current version in use by the proxies * @param _version the version to use * reverts if _version is already used or if version does not exist * only Owner can call * emits a `VersionUpdated` event */ function useTREXVersion(Version calldata _version) external; /** * @dev change the implementationAuthority address of all proxy contracts linked to a given token * only the owner of all proxy contracts can call this function * @param _token the address of the token proxy * @param _newImplementationAuthority the address of the new IA contract * caller has to be owner of all contracts linked to the token and impacted by the change * Set _newImplementationAuthority on zero address to deploy a new IA contract * New IA contracts can only be deployed ONCE per token and only if current IA is the main IA * if _newImplementationAuthority is not a new contract it must be using the same version * as the current IA contract. * calls `setImplementationAuthority` on all proxies linked to the token * emits a `ImplementationAuthorityChanged` event */ function changeImplementationAuthority(address _token, address _newImplementationAuthority) external; /** * @dev getter function returning the current version of contracts used by proxies */ function getCurrentVersion() external view returns (Version memory); /** * @dev getter function returning the contracts corresponding to a version * @param _version the version that contracts are requested for */ function getContracts(Version calldata _version) external view returns (TREXContracts memory); /** * @dev getter function returning address of reference TREX factory */ function getTREXFactory() external view returns (address); /** * @dev getter function returning address of token contract implementation * currently used by the proxies using this TREXImplementationAuthority */ function getTokenImplementation() external view returns (address); /** * @dev getter function returning address of ClaimTopicsRegistry contract implementation * currently used by the proxies using this TREXImplementationAuthority */ function getCTRImplementation() external view returns (address); /** * @dev getter function returning address of IdentityRegistry contract implementation * currently used by the proxies using this TREXImplementationAuthority */ function getIRImplementation() external view returns (address); /** * @dev getter function returning address of IdentityRegistryStorage contract implementation * currently used by the proxies using this TREXImplementationAuthority */ function getIRSImplementation() external view returns (address); /** * @dev getter function returning address of TrustedIssuersRegistry contract implementation * currently used by the proxies using this TREXImplementationAuthority */ function getTIRImplementation() external view returns (address); /** * @dev getter function returning address of ModularCompliance contract implementation * currently used by the proxies using this TREXImplementationAuthority */ function getMCImplementation() external view returns (address); /** * @dev returns true if the contract is the main contract * returns false if the contract is an auxiliary contract */ function isReferenceContract() external view returns (bool); /** * @dev getter for reference contract address */ function getReferenceContract() external view returns (address); }
// SPDX-License-Identifier: GPL-3.0 // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= // :=*%@@@#=. :#@@% *@@@%= // .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- // :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. // -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ // =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- // -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: // :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. // %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. // #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ // *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- // -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: // .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- // -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- // -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# // *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- // +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: // =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: // .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. // +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. // -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. // ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. // @@@@@@+. +@@*. .+@@@@@%=. // -@@@@@= =@@%: -#@@@@%+. // +@@@@@. =@@@= .+@@@@@*: // #@@@@#:%@@#. :*@@@@#- // @@@@@%@@@= :#@@@@+. // :@@@@@@@#.:#@@@%- // +@@@@@@-.*@@@*: // #@@@@#.=@@@+. // @@@@+-%@%= // :@@@#%@%= // +@@@@%- // :#%%= // /** * NOTICE * * The T-REX software is licensed under a proprietary license or the GPL v.3. * If you choose to receive it under the GPL v.3 license, the following applies: * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * * Copyright (C) 2023, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity 0.8.17; import "../registry/interface/IIdentityRegistry.sol"; import "../compliance/modular/IModularCompliance.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /// @dev interface interface IToken is IERC20 { /// events /** * this event is emitted when the token information is updated. * the event is emitted by the token init function and by the setTokenInformation function * `_newName` is the name of the token * `_newSymbol` is the symbol of the token * `_newDecimals` is the decimals of the token * `_newVersion` is the version of the token, current version is 3.0 * `_newOnchainID` is the address of the onchainID of the token */ event UpdatedTokenInformation(string indexed _newName, string indexed _newSymbol, uint8 _newDecimals, string _newVersion, address indexed _newOnchainID); /** * this event is emitted when the IdentityRegistry has been set for the token * the event is emitted by the token constructor and by the setIdentityRegistry function * `_identityRegistry` is the address of the Identity Registry of the token */ event IdentityRegistryAdded(address indexed _identityRegistry); /** * this event is emitted when the Compliance has been set for the token * the event is emitted by the token constructor and by the setCompliance function * `_compliance` is the address of the Compliance contract of the token */ event ComplianceAdded(address indexed _compliance); /** * this event is emitted when an investor successfully recovers his tokens * the event is emitted by the recoveryAddress function * `_lostWallet` is the address of the wallet that the investor lost access to * `_newWallet` is the address of the wallet that the investor provided for the recovery * `_investorOnchainID` is the address of the onchainID of the investor who asked for a recovery */ event RecoverySuccess(address indexed _lostWallet, address indexed _newWallet, address indexed _investorOnchainID); /** * this event is emitted when the wallet of an investor is frozen or unfrozen * the event is emitted by setAddressFrozen and batchSetAddressFrozen functions * `_userAddress` is the wallet of the investor that is concerned by the freezing status * `_isFrozen` is the freezing status of the wallet * if `_isFrozen` equals `true` the wallet is frozen after emission of the event * if `_isFrozen` equals `false` the wallet is unfrozen after emission of the event * `_owner` is the address of the agent who called the function to freeze the wallet */ event AddressFrozen(address indexed _userAddress, bool indexed _isFrozen, address indexed _owner); /** * this event is emitted when a certain amount of tokens is frozen on a wallet * the event is emitted by freezePartialTokens and batchFreezePartialTokens functions * `_userAddress` is the wallet of the investor that is concerned by the freezing status * `_amount` is the amount of tokens that are frozen */ event TokensFrozen(address indexed _userAddress, uint256 _amount); /** * this event is emitted when a certain amount of tokens is unfrozen on a wallet * the event is emitted by unfreezePartialTokens and batchUnfreezePartialTokens functions * `_userAddress` is the wallet of the investor that is concerned by the freezing status * `_amount` is the amount of tokens that are unfrozen */ event TokensUnfrozen(address indexed _userAddress, uint256 _amount); /** * this event is emitted when the token is paused * the event is emitted by the pause function * `_userAddress` is the address of the wallet that called the pause function */ event Paused(address _userAddress); /** * this event is emitted when the token is unpaused * the event is emitted by the unpause function * `_userAddress` is the address of the wallet that called the unpause function */ event Unpaused(address _userAddress); /// functions /** * @dev sets the token name * @param _name the name of token to set * Only the owner of the token smart contract can call this function * emits a `UpdatedTokenInformation` event */ function setName(string calldata _name) external; /** * @dev sets the token symbol * @param _symbol the token symbol to set * Only the owner of the token smart contract can call this function * emits a `UpdatedTokenInformation` event */ function setSymbol(string calldata _symbol) external; /** * @dev sets the onchain ID of the token * @param _onchainID the address of the onchain ID to set * Only the owner of the token smart contract can call this function * emits a `UpdatedTokenInformation` event */ function setOnchainID(address _onchainID) external; /** * @dev pauses the token contract, when contract is paused investors cannot transfer tokens anymore * This function can only be called by a wallet set as agent of the token * emits a `Paused` event */ function pause() external; /** * @dev unpauses the token contract, when contract is unpaused investors can transfer tokens * if their wallet is not blocked & if the amount to transfer is <= to the amount of free tokens * This function can only be called by a wallet set as agent of the token * emits an `Unpaused` event */ function unpause() external; /** * @dev sets an address frozen status for this token. * @param _userAddress The address for which to update frozen status * @param _freeze Frozen status of the address * This function can only be called by a wallet set as agent of the token * emits an `AddressFrozen` event */ function setAddressFrozen(address _userAddress, bool _freeze) external; /** * @dev freezes token amount specified for given address. * @param _userAddress The address for which to update frozen tokens * @param _amount Amount of Tokens to be frozen * This function can only be called by a wallet set as agent of the token * emits a `TokensFrozen` event */ function freezePartialTokens(address _userAddress, uint256 _amount) external; /** * @dev unfreezes token amount specified for given address * @param _userAddress The address for which to update frozen tokens * @param _amount Amount of Tokens to be unfrozen * This function can only be called by a wallet set as agent of the token * emits a `TokensUnfrozen` event */ function unfreezePartialTokens(address _userAddress, uint256 _amount) external; /** * @dev sets the Identity Registry for the token * @param _identityRegistry the address of the Identity Registry to set * Only the owner of the token smart contract can call this function * emits an `IdentityRegistryAdded` event */ function setIdentityRegistry(address _identityRegistry) external; /** * @dev sets the compliance contract of the token * @param _compliance the address of the compliance contract to set * Only the owner of the token smart contract can call this function * calls bindToken on the compliance contract * emits a `ComplianceAdded` event */ function setCompliance(address _compliance) external; /** * @dev force a transfer of tokens between 2 whitelisted wallets * In case the `from` address has not enough free tokens (unfrozen tokens) * but has a total balance higher or equal to the `amount` * the amount of frozen tokens is reduced in order to have enough free tokens * to proceed the transfer, in such a case, the remaining balance on the `from` * account is 100% composed of frozen tokens post-transfer. * Require that the `to` address is a verified address, * @param _from The address of the sender * @param _to The address of the receiver * @param _amount The number of tokens to transfer * @return `true` if successful and revert if unsuccessful * This function can only be called by a wallet set as agent of the token * emits a `TokensUnfrozen` event if `_amount` is higher than the free balance of `_from` * emits a `Transfer` event */ function forcedTransfer( address _from, address _to, uint256 _amount ) external returns (bool); /** * @dev mint tokens on a wallet * Improved version of default mint method. Tokens can be minted * to an address if only it is a verified address as per the security token. * @param _to Address to mint the tokens to. * @param _amount Amount of tokens to mint. * This function can only be called by a wallet set as agent of the token * emits a `Transfer` event */ function mint(address _to, uint256 _amount) external; /** * @dev burn tokens on a wallet * In case the `account` address has not enough free tokens (unfrozen tokens) * but has a total balance higher or equal to the `value` amount * the amount of frozen tokens is reduced in order to have enough free tokens * to proceed the burn, in such a case, the remaining balance on the `account` * is 100% composed of frozen tokens post-transaction. * @param _userAddress Address to burn the tokens from. * @param _amount Amount of tokens to burn. * This function can only be called by a wallet set as agent of the token * emits a `TokensUnfrozen` event if `_amount` is higher than the free balance of `_userAddress` * emits a `Transfer` event */ function burn(address _userAddress, uint256 _amount) external; /** * @dev recovery function used to force transfer tokens from a * lost wallet to a new wallet for an investor. * @param _lostWallet the wallet that the investor lost * @param _newWallet the newly provided wallet on which tokens have to be transferred * @param _investorOnchainID the onchainID of the investor asking for a recovery * This function can only be called by a wallet set as agent of the token * emits a `TokensUnfrozen` event if there is some frozen tokens on the lost wallet if the recovery process is successful * emits a `Transfer` event if the recovery process is successful * emits a `RecoverySuccess` event if the recovery process is successful * emits a `RecoveryFails` event if the recovery process fails */ function recoveryAddress( address _lostWallet, address _newWallet, address _investorOnchainID ) external returns (bool); /** * @dev function allowing to issue transfers in batch * Require that the msg.sender and `to` addresses are not frozen. * Require that the total value should not exceed available balance. * Require that the `to` addresses are all verified addresses, * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_toList.length` IS TOO HIGH, * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION * @param _toList The addresses of the receivers * @param _amounts The number of tokens to transfer to the corresponding receiver * emits _toList.length `Transfer` events */ function batchTransfer(address[] calldata _toList, uint256[] calldata _amounts) external; /** * @dev function allowing to issue forced transfers in batch * Require that `_amounts[i]` should not exceed available balance of `_fromList[i]`. * Require that the `_toList` addresses are all verified addresses * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_fromList.length` IS TOO HIGH, * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION * @param _fromList The addresses of the senders * @param _toList The addresses of the receivers * @param _amounts The number of tokens to transfer to the corresponding receiver * This function can only be called by a wallet set as agent of the token * emits `TokensUnfrozen` events if `_amounts[i]` is higher than the free balance of `_fromList[i]` * emits _fromList.length `Transfer` events */ function batchForcedTransfer( address[] calldata _fromList, address[] calldata _toList, uint256[] calldata _amounts ) external; /** * @dev function allowing to mint tokens in batch * Require that the `_toList` addresses are all verified addresses * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_toList.length` IS TOO HIGH, * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION * @param _toList The addresses of the receivers * @param _amounts The number of tokens to mint to the corresponding receiver * This function can only be called by a wallet set as agent of the token * emits _toList.length `Transfer` events */ function batchMint(address[] calldata _toList, uint256[] calldata _amounts) external; /** * @dev function allowing to burn tokens in batch * Require that the `_userAddresses` addresses are all verified addresses * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH, * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION * @param _userAddresses The addresses of the wallets concerned by the burn * @param _amounts The number of tokens to burn from the corresponding wallets * This function can only be called by a wallet set as agent of the token * emits _userAddresses.length `Transfer` events */ function batchBurn(address[] calldata _userAddresses, uint256[] calldata _amounts) external; /** * @dev function allowing to set frozen addresses in batch * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH, * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION * @param _userAddresses The addresses for which to update frozen status * @param _freeze Frozen status of the corresponding address * This function can only be called by a wallet set as agent of the token * emits _userAddresses.length `AddressFrozen` events */ function batchSetAddressFrozen(address[] calldata _userAddresses, bool[] calldata _freeze) external; /** * @dev function allowing to freeze tokens partially in batch * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH, * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION * @param _userAddresses The addresses on which tokens need to be frozen * @param _amounts the amount of tokens to freeze on the corresponding address * This function can only be called by a wallet set as agent of the token * emits _userAddresses.length `TokensFrozen` events */ function batchFreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external; /** * @dev function allowing to unfreeze tokens partially in batch * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH, * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION * @param _userAddresses The addresses on which tokens need to be unfrozen * @param _amounts the amount of tokens to unfreeze on the corresponding address * This function can only be called by a wallet set as agent of the token * emits _userAddresses.length `TokensUnfrozen` events */ function batchUnfreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external; /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 1 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * balanceOf() and transfer(). */ function decimals() external view returns (uint8); /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the address of the onchainID of the token. * the onchainID of the token gives all the information available * about the token and is managed by the token issuer or his agent. */ function onchainID() external view returns (address); /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() external view returns (string memory); /** * @dev Returns the TREX version of the token. * current version is 3.0.0 */ function version() external view returns (string memory); /** * @dev Returns the Identity Registry linked to the token */ function identityRegistry() external view returns (IIdentityRegistry); /** * @dev Returns the Compliance contract linked to the token */ function compliance() external view returns (IModularCompliance); /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() external view returns (bool); /** * @dev Returns the freezing status of a wallet * if isFrozen returns `true` the wallet is frozen * if isFrozen returns `false` the wallet is not frozen * isFrozen returning `true` doesn't mean that the balance is free, tokens could be blocked by * a partial freeze or the whole token could be blocked by pause * @param _userAddress the address of the wallet on which isFrozen is called */ function isFrozen(address _userAddress) external view returns (bool); /** * @dev Returns the amount of tokens that are partially frozen on a wallet * the amount of frozen tokens is always <= to the total balance of the wallet * @param _userAddress the address of the wallet on which getFrozenTokens is called */ function getFrozenTokens(address _userAddress) external view returns (uint256); }
// 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: GPL-3.0 // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= // :=*%@@@#=. :#@@% *@@@%= // .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- // :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. // -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ // =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- // -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: // :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. // %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. // #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ // *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- // -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: // .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- // -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- // -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# // *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- // +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: // =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: // .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. // +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. // -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. // ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. // @@@@@@+. +@@*. .+@@@@@%=. // -@@@@@= =@@%: -#@@@@%+. // +@@@@@. =@@@= .+@@@@@*: // #@@@@#:%@@#. :*@@@@#- // @@@@@%@@@= :#@@@@+. // :@@@@@@@#.:#@@@%- // +@@@@@@-.*@@@*: // #@@@@#.=@@@+. // @@@@+-%@%= // :@@@#%@%= // +@@@@%- // :#%%= // /** * NOTICE * * The T-REX software is licensed under a proprietary license or the GPL v.3. * If you choose to receive it under the GPL v.3 license, the following applies: * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * * Copyright (C) 2023, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity 0.8.17; import "./interface/IProxy.sol"; import "./authority/ITREXImplementationAuthority.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; abstract contract AbstractProxy is IProxy, Initializable { /** * @dev See {IProxy-setImplementationAuthority}. */ function setImplementationAuthority(address _newImplementationAuthority) external override { require(msg.sender == getImplementationAuthority(), "only current implementationAuthority can call"); require(_newImplementationAuthority != address(0), "invalid argument - zero address"); require( (ITREXImplementationAuthority(_newImplementationAuthority)).getTokenImplementation() != address(0) && (ITREXImplementationAuthority(_newImplementationAuthority)).getCTRImplementation() != address(0) && (ITREXImplementationAuthority(_newImplementationAuthority)).getIRImplementation() != address(0) && (ITREXImplementationAuthority(_newImplementationAuthority)).getIRSImplementation() != address(0) && (ITREXImplementationAuthority(_newImplementationAuthority)).getMCImplementation() != address(0) && (ITREXImplementationAuthority(_newImplementationAuthority)).getTIRImplementation() != address(0) , "invalid Implementation Authority"); _storeImplementationAuthority(_newImplementationAuthority); emit ImplementationAuthoritySet(_newImplementationAuthority); } /** * @dev See {IProxy-getImplementationAuthority}. */ function getImplementationAuthority() public override view returns(address) { address implemAuth; // solhint-disable-next-line no-inline-assembly assembly { implemAuth := sload(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7) } return implemAuth; } /** * @dev store the implementationAuthority contract address using the ERC-1822 implementation slot in storage */ function _storeImplementationAuthority(address implementationAuthority) internal { // solhint-disable-next-line no-inline-assembly assembly { sstore(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7, implementationAuthority) } } }
// SPDX-License-Identifier: GPL-3.0 // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= // :=*%@@@#=. :#@@% *@@@%= // .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- // :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. // -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ // =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- // -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: // :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. // %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. // #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ // *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- // -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: // .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- // -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- // -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# // *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- // +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: // =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: // .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. // +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. // -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. // ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. // @@@@@@+. +@@*. .+@@@@@%=. // -@@@@@= =@@%: -#@@@@%+. // +@@@@@. =@@@= .+@@@@@*: // #@@@@#:%@@#. :*@@@@#- // @@@@@%@@@= :#@@@@+. // :@@@@@@@#.:#@@@%- // +@@@@@@-.*@@@*: // #@@@@#.=@@@+. // @@@@+-%@%= // :@@@#%@%= // +@@@@%- // :#%%= // /** * NOTICE * * The T-REX software is licensed under a proprietary license or the GPL v.3. * If you choose to receive it under the GPL v.3 license, the following applies: * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * * Copyright (C) 2023, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity 0.8.17; import "./ITrustedIssuersRegistry.sol"; import "./IClaimTopicsRegistry.sol"; import "./IIdentityRegistryStorage.sol"; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; interface IIdentityRegistry { /** * this event is emitted when the ClaimTopicsRegistry has been set for the IdentityRegistry * the event is emitted by the IdentityRegistry constructor * `claimTopicsRegistry` is the address of the Claim Topics Registry contract */ event ClaimTopicsRegistrySet(address indexed claimTopicsRegistry); /** * this event is emitted when the IdentityRegistryStorage has been set for the IdentityRegistry * the event is emitted by the IdentityRegistry constructor * `identityStorage` is the address of the Identity Registry Storage contract */ event IdentityStorageSet(address indexed identityStorage); /** * this event is emitted when the TrustedIssuersRegistry has been set for the IdentityRegistry * the event is emitted by the IdentityRegistry constructor * `trustedIssuersRegistry` is the address of the Trusted Issuers Registry contract */ event TrustedIssuersRegistrySet(address indexed trustedIssuersRegistry); /** * this event is emitted when an Identity is registered into the Identity Registry. * the event is emitted by the 'registerIdentity' function * `investorAddress` is the address of the investor's wallet * `identity` is the address of the Identity smart contract (onchainID) */ event IdentityRegistered(address indexed investorAddress, IIdentity indexed identity); /** * this event is emitted when an Identity is removed from the Identity Registry. * the event is emitted by the 'deleteIdentity' function * `investorAddress` is the address of the investor's wallet * `identity` is the address of the Identity smart contract (onchainID) */ event IdentityRemoved(address indexed investorAddress, IIdentity indexed identity); /** * this event is emitted when an Identity has been updated * the event is emitted by the 'updateIdentity' function * `oldIdentity` is the old Identity contract's address to update * `newIdentity` is the new Identity contract's */ event IdentityUpdated(IIdentity indexed oldIdentity, IIdentity indexed newIdentity); /** * this event is emitted when an Identity's country has been updated * the event is emitted by the 'updateCountry' function * `investorAddress` is the address on which the country has been updated * `country` is the numeric code (ISO 3166-1) of the new country */ event CountryUpdated(address indexed investorAddress, uint16 indexed country); /** * @dev Register an identity contract corresponding to a user address. * Requires that the user doesn't have an identity contract already registered. * This function can only be called by a wallet set as agent of the smart contract * @param _userAddress The address of the user * @param _identity The address of the user's identity contract * @param _country The country of the investor * emits `IdentityRegistered` event */ function registerIdentity( address _userAddress, IIdentity _identity, uint16 _country ) external; /** * @dev Removes an user from the identity registry. * Requires that the user have an identity contract already deployed that will be deleted. * This function can only be called by a wallet set as agent of the smart contract * @param _userAddress The address of the user to be removed * emits `IdentityRemoved` event */ function deleteIdentity(address _userAddress) external; /** * @dev Replace the actual identityRegistryStorage contract with a new one. * This function can only be called by the wallet set as owner of the smart contract * @param _identityRegistryStorage The address of the new Identity Registry Storage * emits `IdentityStorageSet` event */ function setIdentityRegistryStorage(address _identityRegistryStorage) external; /** * @dev Replace the actual claimTopicsRegistry contract with a new one. * This function can only be called by the wallet set as owner of the smart contract * @param _claimTopicsRegistry The address of the new claim Topics Registry * emits `ClaimTopicsRegistrySet` event */ function setClaimTopicsRegistry(address _claimTopicsRegistry) external; /** * @dev Replace the actual trustedIssuersRegistry contract with a new one. * This function can only be called by the wallet set as owner of the smart contract * @param _trustedIssuersRegistry The address of the new Trusted Issuers Registry * emits `TrustedIssuersRegistrySet` event */ function setTrustedIssuersRegistry(address _trustedIssuersRegistry) external; /** * @dev Updates the country corresponding to a user address. * Requires that the user should have an identity contract already deployed that will be replaced. * This function can only be called by a wallet set as agent of the smart contract * @param _userAddress The address of the user * @param _country The new country of the user * emits `CountryUpdated` event */ function updateCountry(address _userAddress, uint16 _country) external; /** * @dev Updates an identity contract corresponding to a user address. * Requires that the user address should be the owner of the identity contract. * Requires that the user should have an identity contract already deployed that will be replaced. * This function can only be called by a wallet set as agent of the smart contract * @param _userAddress The address of the user * @param _identity The address of the user's new identity contract * emits `IdentityUpdated` event */ function updateIdentity(address _userAddress, IIdentity _identity) external; /** * @dev function allowing to register identities in batch * This function can only be called by a wallet set as agent of the smart contract * Requires that none of the users has an identity contract already registered. * IMPORTANT : THIS TRANSACTION COULD EXCEED GAS LIMIT IF `_userAddresses.length` IS TOO HIGH, * USE WITH CARE OR YOU COULD LOSE TX FEES WITH AN "OUT OF GAS" TRANSACTION * @param _userAddresses The addresses of the users * @param _identities The addresses of the corresponding identity contracts * @param _countries The countries of the corresponding investors * emits _userAddresses.length `IdentityRegistered` events */ function batchRegisterIdentity( address[] calldata _userAddresses, IIdentity[] calldata _identities, uint16[] calldata _countries ) external; /** * @dev This functions checks whether a wallet has its Identity registered or not * in the Identity Registry. * @param _userAddress The address of the user to be checked. * @return 'True' if the address is contained in the Identity Registry, 'false' if not. */ function contains(address _userAddress) external view returns (bool); /** * @dev This functions checks whether an identity contract * corresponding to the provided user address has the required claims or not based * on the data fetched from trusted issuers registry and from the claim topics registry * @param _userAddress The address of the user to be verified. * @return 'True' if the address is verified, 'false' if not. */ function isVerified(address _userAddress) external view returns (bool); /** * @dev Returns the onchainID of an investor. * @param _userAddress The wallet of the investor */ function identity(address _userAddress) external view returns (IIdentity); /** * @dev Returns the country code of an investor. * @param _userAddress The wallet of the investor */ function investorCountry(address _userAddress) external view returns (uint16); /** * @dev Returns the IdentityRegistryStorage linked to the current IdentityRegistry. */ function identityStorage() external view returns (IIdentityRegistryStorage); /** * @dev Returns the TrustedIssuersRegistry linked to the current IdentityRegistry. */ function issuersRegistry() external view returns (ITrustedIssuersRegistry); /** * @dev Returns the ClaimTopicsRegistry linked to the current IdentityRegistry. */ function topicsRegistry() external view returns (IClaimTopicsRegistry); }
// SPDX-License-Identifier: GPL-3.0 // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= // :=*%@@@#=. :#@@% *@@@%= // .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- // :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. // -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ // =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- // -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: // :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. // %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. // #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ // *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- // -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: // .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- // -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- // -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# // *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- // +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: // =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: // .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. // +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. // -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. // ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. // @@@@@@+. +@@*. .+@@@@@%=. // -@@@@@= =@@%: -#@@@@%+. // +@@@@@. =@@@= .+@@@@@*: // #@@@@#:%@@#. :*@@@@#- // @@@@@%@@@= :#@@@@+. // :@@@@@@@#.:#@@@%- // +@@@@@@-.*@@@*: // #@@@@#.=@@@+. // @@@@+-%@%= // :@@@#%@%= // +@@@@%- // :#%%= // /** * NOTICE * * The T-REX software is licensed under a proprietary license or the GPL v.3. * If you choose to receive it under the GPL v.3 license, the following applies: * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * * Copyright (C) 2023, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity 0.8.17; interface IModularCompliance { /// events /** * @dev Event emitted for each executed interaction with a module contract. * For gas efficiency, only the interaction calldata selector (first 4 * bytes) is included in the event. For interactions without calldata or * whose calldata is shorter than 4 bytes, the selector will be `0`. */ event ModuleInteraction(address indexed target, bytes4 selector); /** * this event is emitted when a token has been bound to the compliance contract * the event is emitted by the bindToken function * `_token` is the address of the token to bind */ event TokenBound(address _token); /** * this event is emitted when a token has been unbound from the compliance contract * the event is emitted by the unbindToken function * `_token` is the address of the token to unbind */ event TokenUnbound(address _token); /** * this event is emitted when a module has been added to the list of modules bound to the compliance contract * the event is emitted by the addModule function * `_module` is the address of the compliance module */ event ModuleAdded(address indexed _module); /** * this event is emitted when a module has been removed from the list of modules bound to the compliance contract * the event is emitted by the removeModule function * `_module` is the address of the compliance module */ event ModuleRemoved(address indexed _module); /// functions /** * @dev binds a token to the compliance contract * @param _token address of the token to bind * This function can be called ONLY by the owner of the compliance contract * Emits a TokenBound event */ function bindToken(address _token) external; /** * @dev unbinds a token from the compliance contract * @param _token address of the token to unbind * This function can be called ONLY by the owner of the compliance contract * Emits a TokenUnbound event */ function unbindToken(address _token) external; /** * @dev adds a module to the list of compliance modules * @param _module address of the module to add * there cannot be more than 25 modules bound to the modular compliance for gas cost reasons * This function can be called ONLY by the owner of the compliance contract * Emits a ModuleAdded event */ function addModule(address _module) external; /** * @dev removes a module from the list of compliance modules * @param _module address of the module to remove * This function can be called ONLY by the owner of the compliance contract * Emits a ModuleRemoved event */ function removeModule(address _module) external; /** * @dev calls any function on bound modules * can be called only on bound modules * @param callData the bytecode for interaction with the module, abi encoded * @param _module The address of the module * This function can be called only by the modular compliance owner * emits a `ModuleInteraction` event */ function callModuleFunction(bytes calldata callData, address _module) external; /** * @dev function called whenever tokens are transferred * from one wallet to another * this function can update state variables in the modules bound to the compliance * these state variables being used by the module checks to decide if a transfer * is compliant or not depending on the values stored in these state variables and on * the parameters of the modules * This function can be called ONLY by the token contract bound to the compliance * @param _from The address of the sender * @param _to The address of the receiver * @param _amount The amount of tokens involved in the transfer * This function calls moduleTransferAction() on each module bound to the compliance contract */ function transferred( address _from, address _to, uint256 _amount ) external; /** * @dev function called whenever tokens are created on a wallet * this function can update state variables in the modules bound to the compliance * these state variables being used by the module checks to decide if a transfer * is compliant or not depending on the values stored in these state variables and on * the parameters of the modules * This function can be called ONLY by the token contract bound to the compliance * @param _to The address of the receiver * @param _amount The amount of tokens involved in the minting * This function calls moduleMintAction() on each module bound to the compliance contract */ function created(address _to, uint256 _amount) external; /** * @dev function called whenever tokens are destroyed from a wallet * this function can update state variables in the modules bound to the compliance * these state variables being used by the module checks to decide if a transfer * is compliant or not depending on the values stored in these state variables and on * the parameters of the modules * This function can be called ONLY by the token contract bound to the compliance * @param _from The address on which tokens are burnt * @param _amount The amount of tokens involved in the burn * This function calls moduleBurnAction() on each module bound to the compliance contract */ function destroyed(address _from, uint256 _amount) external; /** * @dev checks that the transfer is compliant. * default compliance always returns true * READ ONLY FUNCTION, this function cannot be used to increment * counters, emit events, ... * @param _from The address of the sender * @param _to The address of the receiver * @param _amount The amount of tokens involved in the transfer * This function will call moduleCheck() on every module bound to the compliance * If each of the module checks return TRUE, this function will return TRUE as well * returns FALSE otherwise */ function canTransfer( address _from, address _to, uint256 _amount ) external view returns (bool); /** * @dev getter for the modules bound to the compliance contract * returns address array of module contracts bound to the compliance */ function getModules() external view returns (address[] memory); /** * @dev getter for the address of the token bound * returns the address of the token */ function getTokenBound() external view returns (address); /** * @dev checks if a module is bound to the compliance contract * returns true if module is bound, false otherwise */ function isModuleBound(address _module) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: GPL-3.0 // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= // :=*%@@@#=. :#@@% *@@@%= // .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- // :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. // -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ // =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- // -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: // :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. // %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. // #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ // *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- // -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: // .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- // -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- // -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# // *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- // +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: // =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: // .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. // +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. // -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. // ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. // @@@@@@+. +@@*. .+@@@@@%=. // -@@@@@= =@@%: -#@@@@%+. // +@@@@@. =@@@= .+@@@@@*: // #@@@@#:%@@#. :*@@@@#- // @@@@@%@@@= :#@@@@+. // :@@@@@@@#.:#@@@%- // +@@@@@@-.*@@@*: // #@@@@#.=@@@+. // @@@@+-%@%= // :@@@#%@%= // +@@@@%- // :#%%= // /** * NOTICE * * The T-REX software is licensed under a proprietary license or the GPL v.3. * If you choose to receive it under the GPL v.3 license, the following applies: * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * * Copyright (C) 2023, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity 0.8.17; interface IProxy { /// events event ImplementationAuthoritySet(address indexed _implementationAuthority); /// functions function setImplementationAuthority(address _newImplementationAuthority) external; function getImplementationAuthority() external view returns(address); }
// SPDX-License-Identifier: GPL-3.0 // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= // :=*%@@@#=. :#@@% *@@@%= // .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- // :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. // -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ // =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- // -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: // :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. // %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. // #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ // *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- // -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: // .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- // -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- // -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# // *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- // +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: // =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: // .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. // +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. // -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. // ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. // @@@@@@+. +@@*. .+@@@@@%=. // -@@@@@= =@@%: -#@@@@%+. // +@@@@@. =@@@= .+@@@@@*: // #@@@@#:%@@#. :*@@@@#- // @@@@@%@@@= :#@@@@+. // :@@@@@@@#.:#@@@%- // +@@@@@@-.*@@@*: // #@@@@#.=@@@+. // @@@@+-%@%= // :@@@#%@%= // +@@@@%- // :#%%= // /** * NOTICE * * The T-REX software is licensed under a proprietary license or the GPL v.3. * If you choose to receive it under the GPL v.3 license, the following applies: * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * * Copyright (C) 2023, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity 0.8.17; import "@onchain-id/solidity/contracts/interface/IClaimIssuer.sol"; interface ITrustedIssuersRegistry { /** * this event is emitted when a trusted issuer is added in the registry. * the event is emitted by the addTrustedIssuer function * `trustedIssuer` is the address of the trusted issuer's ClaimIssuer contract * `claimTopics` is the set of claims that the trusted issuer is allowed to emit */ event TrustedIssuerAdded(IClaimIssuer indexed trustedIssuer, uint256[] claimTopics); /** * this event is emitted when a trusted issuer is removed from the registry. * the event is emitted by the removeTrustedIssuer function * `trustedIssuer` is the address of the trusted issuer's ClaimIssuer contract */ event TrustedIssuerRemoved(IClaimIssuer indexed trustedIssuer); /** * this event is emitted when the set of claim topics is changed for a given trusted issuer. * the event is emitted by the updateIssuerClaimTopics function * `trustedIssuer` is the address of the trusted issuer's ClaimIssuer contract * `claimTopics` is the set of claims that the trusted issuer is allowed to emit */ event ClaimTopicsUpdated(IClaimIssuer indexed trustedIssuer, uint256[] claimTopics); /** * @dev registers a ClaimIssuer contract as trusted claim issuer. * Requires that a ClaimIssuer contract doesn't already exist * Requires that the claimTopics set is not empty * Requires that there is no more than 15 claimTopics * Requires that there is no more than 50 Trusted issuers * @param _trustedIssuer The ClaimIssuer contract address of the trusted claim issuer. * @param _claimTopics the set of claim topics that the trusted issuer is allowed to emit * This function can only be called by the owner of the Trusted Issuers Registry contract * emits a `TrustedIssuerAdded` event */ function addTrustedIssuer(IClaimIssuer _trustedIssuer, uint256[] calldata _claimTopics) external; /** * @dev Removes the ClaimIssuer contract of a trusted claim issuer. * Requires that the claim issuer contract to be registered first * @param _trustedIssuer the claim issuer to remove. * This function can only be called by the owner of the Trusted Issuers Registry contract * emits a `TrustedIssuerRemoved` event */ function removeTrustedIssuer(IClaimIssuer _trustedIssuer) external; /** * @dev Updates the set of claim topics that a trusted issuer is allowed to emit. * Requires that this ClaimIssuer contract already exists in the registry * Requires that the provided claimTopics set is not empty * Requires that there is no more than 15 claimTopics * @param _trustedIssuer the claim issuer to update. * @param _claimTopics the set of claim topics that the trusted issuer is allowed to emit * This function can only be called by the owner of the Trusted Issuers Registry contract * emits a `ClaimTopicsUpdated` event */ function updateIssuerClaimTopics(IClaimIssuer _trustedIssuer, uint256[] calldata _claimTopics) external; /** * @dev Function for getting all the trusted claim issuers stored. * @return array of all claim issuers registered. */ function getTrustedIssuers() external view returns (IClaimIssuer[] memory); /** * @dev Function for getting all the trusted issuer allowed for a given claim topic. * @param claimTopic the claim topic to get the trusted issuers for. * @return array of all claim issuer addresses that are allowed for the given claim topic. */ function getTrustedIssuersForClaimTopic(uint256 claimTopic) external view returns (IClaimIssuer[] memory); /** * @dev Checks if the ClaimIssuer contract is trusted * @param _issuer the address of the ClaimIssuer contract * @return true if the issuer is trusted, false otherwise. */ function isTrustedIssuer(address _issuer) external view returns (bool); /** * @dev Function for getting all the claim topic of trusted claim issuer * Requires the provided ClaimIssuer contract to be registered in the trusted issuers registry. * @param _trustedIssuer the trusted issuer concerned. * @return The set of claim topics that the trusted issuer is allowed to emit */ function getTrustedIssuerClaimTopics(IClaimIssuer _trustedIssuer) external view returns (uint256[] memory); /** * @dev Function for checking if the trusted claim issuer is allowed * to emit a certain claim topic * @param _issuer the address of the trusted issuer's ClaimIssuer contract * @param _claimTopic the Claim Topic that has to be checked to know if the `issuer` is allowed to emit it * @return true if the issuer is trusted for this claim topic. */ function hasClaimTopic(address _issuer, uint256 _claimTopic) external view returns (bool); }
// SPDX-License-Identifier: GPL-3.0 // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= // :=*%@@@#=. :#@@% *@@@%= // .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- // :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. // -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ // =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- // -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: // :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. // %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. // #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ // *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- // -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: // .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- // -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- // -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# // *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- // +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: // =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: // .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. // +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. // -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. // ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. // @@@@@@+. +@@*. .+@@@@@%=. // -@@@@@= =@@%: -#@@@@%+. // +@@@@@. =@@@= .+@@@@@*: // #@@@@#:%@@#. :*@@@@#- // @@@@@%@@@= :#@@@@+. // :@@@@@@@#.:#@@@%- // +@@@@@@-.*@@@*: // #@@@@#.=@@@+. // @@@@+-%@%= // :@@@#%@%= // +@@@@%- // :#%%= // /** * NOTICE * * The T-REX software is licensed under a proprietary license or the GPL v.3. * If you choose to receive it under the GPL v.3 license, the following applies: * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * * Copyright (C) 2023, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity 0.8.17; interface IClaimTopicsRegistry { /** * this event is emitted when a claim topic has been added to the ClaimTopicsRegistry * the event is emitted by the 'addClaimTopic' function * `claimTopic` is the required claim added to the Claim Topics Registry */ event ClaimTopicAdded(uint256 indexed claimTopic); /** * this event is emitted when a claim topic has been removed from the ClaimTopicsRegistry * the event is emitted by the 'removeClaimTopic' function * `claimTopic` is the required claim removed from the Claim Topics Registry */ event ClaimTopicRemoved(uint256 indexed claimTopic); /** * @dev Add a trusted claim topic (For example: KYC=1, AML=2). * Only owner can call. * emits `ClaimTopicAdded` event * cannot add more than 15 topics for 1 token as adding more could create gas issues * @param _claimTopic The claim topic index */ function addClaimTopic(uint256 _claimTopic) external; /** * @dev Remove a trusted claim topic (For example: KYC=1, AML=2). * Only owner can call. * emits `ClaimTopicRemoved` event * @param _claimTopic The claim topic index */ function removeClaimTopic(uint256 _claimTopic) external; /** * @dev Get the trusted claim topics for the security token * @return Array of trusted claim topics */ function getClaimTopics() external view returns (uint256[] memory); }
// SPDX-License-Identifier: GPL-3.0 // // :+#####%%%%%%%%%%%%%%+ // .-*@@@%+.:+%@@@@@%%#***%@@%= // :=*%@@@#=. :#@@% *@@@%= // .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%- // :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#. // -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+ // =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%- // -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%: // :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#. // %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*. // #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+ // *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@- // -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#: // .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#- // -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%- // -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@# // *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+- // +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=: // =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+: // .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+. // +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+. // -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=. // ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=. // @@@@@@+. +@@*. .+@@@@@%=. // -@@@@@= =@@%: -#@@@@%+. // +@@@@@. =@@@= .+@@@@@*: // #@@@@#:%@@#. :*@@@@#- // @@@@@%@@@= :#@@@@+. // :@@@@@@@#.:#@@@%- // +@@@@@@-.*@@@*: // #@@@@#.=@@@+. // @@@@+-%@%= // :@@@#%@%= // +@@@@%- // :#%%= // /** * NOTICE * * The T-REX software is licensed under a proprietary license or the GPL v.3. * If you choose to receive it under the GPL v.3 license, the following applies: * T-REX is a suite of smart contracts implementing the ERC-3643 standard and * developed by Tokeny to manage and transfer financial assets on EVM blockchains * * Copyright (C) 2023, Tokeny sàrl. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity 0.8.17; import "@onchain-id/solidity/contracts/interface/IIdentity.sol"; interface IIdentityRegistryStorage { /// events /** * this event is emitted when an Identity is registered into the storage contract. * the event is emitted by the 'registerIdentity' function * `investorAddress` is the address of the investor's wallet * `identity` is the address of the Identity smart contract (onchainID) */ event IdentityStored(address indexed investorAddress, IIdentity indexed identity); /** * this event is emitted when an Identity is removed from the storage contract. * the event is emitted by the 'deleteIdentity' function * `investorAddress` is the address of the investor's wallet * `identity` is the address of the Identity smart contract (onchainID) */ event IdentityUnstored(address indexed investorAddress, IIdentity indexed identity); /** * this event is emitted when an Identity has been updated * the event is emitted by the 'updateIdentity' function * `oldIdentity` is the old Identity contract's address to update * `newIdentity` is the new Identity contract's */ event IdentityModified(IIdentity indexed oldIdentity, IIdentity indexed newIdentity); /** * this event is emitted when an Identity's country has been updated * the event is emitted by the 'updateCountry' function * `investorAddress` is the address on which the country has been updated * `country` is the numeric code (ISO 3166-1) of the new country */ event CountryModified(address indexed investorAddress, uint16 indexed country); /** * this event is emitted when an Identity Registry is bound to the storage contract * the event is emitted by the 'addIdentityRegistry' function * `identityRegistry` is the address of the identity registry added */ event IdentityRegistryBound(address indexed identityRegistry); /** * this event is emitted when an Identity Registry is unbound from the storage contract * the event is emitted by the 'removeIdentityRegistry' function * `identityRegistry` is the address of the identity registry removed */ event IdentityRegistryUnbound(address indexed identityRegistry); /// functions /** * @dev adds an identity contract corresponding to a user address in the storage. * Requires that the user doesn't have an identity contract already registered. * This function can only be called by an address set as agent of the smart contract * @param _userAddress The address of the user * @param _identity The address of the user's identity contract * @param _country The country of the investor * emits `IdentityStored` event */ function addIdentityToStorage( address _userAddress, IIdentity _identity, uint16 _country ) external; /** * @dev Removes an user from the storage. * Requires that the user have an identity contract already deployed that will be deleted. * This function can only be called by an address set as agent of the smart contract * @param _userAddress The address of the user to be removed * emits `IdentityUnstored` event */ function removeIdentityFromStorage(address _userAddress) external; /** * @dev Updates the country corresponding to a user address. * Requires that the user should have an identity contract already deployed that will be replaced. * This function can only be called by an address set as agent of the smart contract * @param _userAddress The address of the user * @param _country The new country of the user * emits `CountryModified` event */ function modifyStoredInvestorCountry(address _userAddress, uint16 _country) external; /** * @dev Updates an identity contract corresponding to a user address. * Requires that the user address should be the owner of the identity contract. * Requires that the user should have an identity contract already deployed that will be replaced. * This function can only be called by an address set as agent of the smart contract * @param _userAddress The address of the user * @param _identity The address of the user's new identity contract * emits `IdentityModified` event */ function modifyStoredIdentity(address _userAddress, IIdentity _identity) external; /** * @notice Adds an identity registry as agent of the Identity Registry Storage Contract. * This function can only be called by the wallet set as owner of the smart contract * This function adds the identity registry to the list of identityRegistries linked to the storage contract * cannot bind more than 300 IR to 1 IRS * @param _identityRegistry The identity registry address to add. */ function bindIdentityRegistry(address _identityRegistry) external; /** * @notice Removes an identity registry from being agent of the Identity Registry Storage Contract. * This function can only be called by the wallet set as owner of the smart contract * This function removes the identity registry from the list of identityRegistries linked to the storage contract * @param _identityRegistry The identity registry address to remove. */ function unbindIdentityRegistry(address _identityRegistry) external; /** * @dev Returns the identity registries linked to the storage contract */ function linkedIdentityRegistries() external view returns (address[] memory); /** * @dev Returns the onchainID of an investor. * @param _userAddress The wallet of the investor */ function storedIdentity(address _userAddress) external view returns (IIdentity); /** * @dev Returns the country code of an investor. * @param _userAddress The wallet of the investor */ function storedInvestorCountry(address _userAddress) external view returns (uint16); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.17; import "./IIdentity.sol"; interface IClaimIssuer is IIdentity { /** * @dev Emitted when a claim is revoked. * * Specification: MUST be triggered when revoking a claim. */ event ClaimRevoked(bytes indexed signature); /** * @dev Revoke a claim previously issued, the claim is no longer considered as valid after revocation. * @notice will fetch the claim from the identity contract (unsafe). * @param _claimId the id of the claim * @param _identity the address of the identity contract * @return isRevoked true when the claim is revoked */ function revokeClaim(bytes32 _claimId, address _identity) external returns(bool); /** * @dev Revoke a claim previously issued, the claim is no longer considered as valid after revocation. * @param signature the signature of the claim */ function revokeClaimBySignature(bytes calldata signature) external; /** * @dev Returns revocation status of a claim. * @param _sig the signature of the claim * @return isRevoked true if the claim is revoked and false otherwise */ function isClaimRevoked(bytes calldata _sig) external view returns (bool); /** * @dev Checks if a claim is valid. * @param _identity the identity contract related to the claim * @param claimTopic the claim topic of the claim * @param sig the signature of the claim * @param data the data field of the claim * @return claimValid true if the claim is valid, false otherwise */ function isClaimValid( IIdentity _identity, uint256 claimTopic, bytes calldata sig, bytes calldata data) external view returns (bool); /** * @dev returns the address that signed the given data * @param sig the signature of the data * @param dataHash the data that was signed * returns the address that signed dataHash and created the signature sig */ function getRecoveredAddress(bytes calldata sig, bytes32 dataHash) external pure returns (address); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.17; import "./IERC734.sol"; import "./IERC735.sol"; // solhint-disable-next-line no-empty-blocks interface IIdentity is IERC734, IERC735 {}
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.17; /** * @dev interface of the ERC734 (Key Holder) standard as defined in the EIP. */ interface IERC734 { /** * @dev Emitted when an execution request was approved. * * Specification: MUST be triggered when approve was successfully called. */ event Approved(uint256 indexed executionId, bool approved); /** * @dev Emitted when an execute operation was approved and successfully performed. * * Specification: MUST be triggered when approve was called and the execution was successfully approved. */ event Executed(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data); /** * @dev Emitted when an execution request was performed via `execute`. * * Specification: MUST be triggered when execute was successfully called. */ event ExecutionRequested(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data); /** * @dev Emitted when an execute operation was called and failed * * Specification: MUST be triggered when execute call failed */ event ExecutionFailed(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data); /** * @dev Emitted when a key was added to the Identity. * * Specification: MUST be triggered when addKey was successfully called. */ event KeyAdded(bytes32 indexed key, uint256 indexed purpose, uint256 indexed keyType); /** * @dev Emitted when a key was removed from the Identity. * * Specification: MUST be triggered when removeKey was successfully called. */ event KeyRemoved(bytes32 indexed key, uint256 indexed purpose, uint256 indexed keyType); /** * @dev Adds a _key to the identity. The _purpose specifies the purpose of the key. * * Triggers Event: `KeyAdded` * * Specification: MUST only be done by keys of purpose 1, or the identity * itself. If it's the identity itself, the approval process will determine its approval. */ function addKey(bytes32 _key, uint256 _purpose, uint256 _keyType) external returns (bool success); /** * @dev Approves an execution. * * Triggers Event: `Approved` * Triggers on execution successful Event: `Executed` * Triggers on execution failure Event: `ExecutionFailed` */ function approve(uint256 _id, bool _approve) external returns (bool success); /** * @dev Removes _purpose for _key from the identity. * * Triggers Event: `KeyRemoved` * * Specification: MUST only be done by keys of purpose 1, or the identity itself. * If it's the identity itself, the approval process will determine its approval. */ function removeKey(bytes32 _key, uint256 _purpose) external returns (bool success); /** * @dev Passes an execution instruction to an ERC734 identity. * How the execution is handled is up to the identity implementation: * An execution COULD be requested and require `approve` to be called with one or more keys of purpose 1 or 2 to * approve this execution. * Execute COULD be used as the only accessor for `addKey` and `removeKey`. * * Triggers Event: ExecutionRequested * Triggers on direct execution Event: Executed */ function execute(address _to, uint256 _value, bytes calldata _data) external payable returns (uint256 executionId); /** * @dev Returns the full key data, if present in the identity. */ function getKey(bytes32 _key) external view returns (uint256[] memory purposes, uint256 keyType, bytes32 key); /** * @dev Returns the list of purposes associated with a key. */ function getKeyPurposes(bytes32 _key) external view returns(uint256[] memory _purposes); /** * @dev Returns an array of public key bytes32 held by this identity. */ function getKeysByPurpose(uint256 _purpose) external view returns (bytes32[] memory keys); /** * @dev Returns TRUE if a key is present and has the given purpose. If the key is not present it returns FALSE. */ function keyHasPurpose(bytes32 _key, uint256 _purpose) external view returns (bool exists); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.17; /** * @dev interface of the ERC735 (Claim Holder) standard as defined in the EIP. */ interface IERC735 { /** * @dev Emitted when a claim was added. * * Specification: MUST be triggered when a claim was successfully added. */ event ClaimAdded( bytes32 indexed claimId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri); /** * @dev Emitted when a claim was removed. * * Specification: MUST be triggered when removeClaim was successfully called. */ event ClaimRemoved( bytes32 indexed claimId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri); /** * @dev Emitted when a claim was changed. * * Specification: MUST be triggered when addClaim was successfully called on an existing claimId. */ event ClaimChanged( bytes32 indexed claimId, uint256 indexed topic, uint256 scheme, address indexed issuer, bytes signature, bytes data, string uri); /** * @dev Add or update a claim. * * Triggers Event: `ClaimAdded`, `ClaimChanged` * * Specification: Add or update a claim from an issuer. * * _signature is a signed message of the following structure: * `keccak256(abi.encode(address identityHolder_address, uint256 topic, bytes data))`. * Claim IDs are generated using `keccak256(abi.encode(address issuer_address + uint256 topic))`. */ function addClaim( uint256 _topic, uint256 _scheme, address issuer, bytes calldata _signature, bytes calldata _data, string calldata _uri) external returns (bytes32 claimRequestId); /** * @dev Removes a claim. * * Triggers Event: `ClaimRemoved` * * Claim IDs are generated using `keccak256(abi.encode(address issuer_address, uint256 topic))`. */ function removeClaim(bytes32 _claimId) external returns (bool success); /** * @dev Get a claim by its ID. * * Claim IDs are generated using `keccak256(abi.encode(address issuer_address, uint256 topic))`. */ function getClaim(bytes32 _claimId) external view returns( uint256 topic, uint256 scheme, address issuer, bytes memory signature, bytes memory data, string memory uri); /** * @dev Returns an array of claim IDs by topic. */ function getClaimIdsByTopic(uint256 _topic) external view returns(bytes32[] memory claimIds); }
{ "remappings": [ "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@solady/=lib/solady/src/", "@solidity-lib/=lib/solidity-lib/contracts/", "@forge-std/=lib/forge-std/src/", "@onchain-id/solidity/=lib/solidity/", "@ERC-3643/=lib/ERC-3643/contracts/", "@core/=contracts/core/", "@modules/=contracts/modules/", "@rules/=contracts/rules/", "@interface/=contracts/interface/", "@abstract/=contracts/abstract/", "@mock/=tests/mock/", "@chainlink/=node_modules/@chainlink/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@onchain-id/solidity/=lib/solidity/", "@core/=contracts/core/", "@modules/=contracts/modules/", "@rules/=contracts/rules/", "@interface/=contracts/interface/", "@abstract/=contracts/abstract/", "@mock/=tests/mock/", "ERC-3643/=lib/ERC-3643/contracts/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/", "solady/=lib/solady/src/", "solidity-lib/=lib/solidity-lib/contracts/", "solidity/=lib/solidity/contracts/", "solmate/=lib/solady/lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 1000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"FrictionlessTokensFactoryNotATreasuryManager","type":"error"},{"inputs":[],"name":"FrictionlessTokensFactoryZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum IBasicFrictionlessToken.FrictionlessTokenTypes","name":"tokenType","type":"uint8"},{"indexed":false,"internalType":"address","name":"newTokenContract","type":"address"}],"name":"FrictionlessTokenDeployed","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":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"address","name":"tokenOwner_","type":"address"},{"components":[{"internalType":"address","name":"implementationAuthority","type":"address"},{"internalType":"address","name":"identityRegistry","type":"address"},{"internalType":"address","name":"compliance","type":"address"},{"internalType":"address","name":"onChainId","type":"address"},{"internalType":"string","name":"tokenName","type":"string"},{"internalType":"string","name":"tokenSymbol","type":"string"}],"internalType":"struct IFrictionlessTokensFactory.BaseTokenInitParams","name":"baseTokenInitParams_","type":"tuple"},{"components":[{"internalType":"string","name":"baseCurrency","type":"string"},{"internalType":"enum IFrictionlessDigitalSecurityToken.FrictionlessDigitalSecurityTokenType","name":"tokenType","type":"uint8"},{"internalType":"address","name":"onChainAssetAddress","type":"address"}],"internalType":"struct IFrictionlessDigitalSecurityToken.FDSImmutableData","name":"initData_","type":"tuple"},{"components":[{"internalType":"uint256","name":"maturesOn","type":"uint256"}],"internalType":"struct IFrictionlessDigitalSecurityToken.FDSMutableData","name":"updateData_","type":"tuple"}],"name":"deployDigitalSecurityToken","outputs":[{"internalType":"address","name":"tokenProxyAddr_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOwner_","type":"address"},{"components":[{"internalType":"address","name":"implementationAuthority","type":"address"},{"internalType":"address","name":"identityRegistry","type":"address"},{"internalType":"address","name":"compliance","type":"address"},{"internalType":"address","name":"onChainId","type":"address"},{"internalType":"string","name":"tokenName","type":"string"},{"internalType":"string","name":"tokenSymbol","type":"string"}],"internalType":"struct IFrictionlessTokensFactory.BaseTokenInitParams","name":"baseTokenInitParams_","type":"tuple"},{"components":[{"internalType":"string","name":"currency","type":"string"},{"internalType":"string","name":"description","type":"string"},{"internalType":"string","name":"fundIBAN","type":"string"}],"internalType":"struct IFrictionlessFundDepositToken.FFDImmutableData","name":"initData_","type":"tuple"}],"name":"deployFundDepositToken","outputs":[{"internalType":"address","name":"tokenProxyAddr_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOwner_","type":"address"},{"components":[{"internalType":"address","name":"implementationAuthority","type":"address"},{"internalType":"address","name":"identityRegistry","type":"address"},{"internalType":"address","name":"compliance","type":"address"},{"internalType":"address","name":"onChainId","type":"address"},{"internalType":"string","name":"tokenName","type":"string"},{"internalType":"string","name":"tokenSymbol","type":"string"}],"internalType":"struct IFrictionlessTokensFactory.BaseTokenInitParams","name":"baseTokenInitParams_","type":"tuple"},{"components":[{"internalType":"uint256","name":"issuedOn","type":"uint256"},{"internalType":"uint256","name":"maturityDays","type":"uint256"},{"internalType":"enum IFrictionlessOnChainAssetToken.FrictionlessOnChainAssetSchedule","name":"schedule","type":"uint8"},{"internalType":"enum IFrictionlessOnChainAssetToken.FrictionlessOnChainAssetPaymentFrequency","name":"paymentFrequency","type":"uint8"},{"internalType":"enum IFrictionlessOnChainAssetToken.FrictionlessOnChainAssetYieldType","name":"yieldType","type":"uint8"},{"internalType":"string","name":"baseCurrency","type":"string"},{"internalType":"uint256","name":"stripTotal","type":"uint256"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"}],"internalType":"struct IFrictionlessOnChainAssetToken.FOCASpecData","name":"specData_","type":"tuple"},{"components":[{"internalType":"uint256","name":"auctionedOn","type":"uint256"},{"internalType":"enum IFrictionlessOnChainAssetToken.FrictionlessOnChainAssetPriceStatus","name":"priceQuoteStatus","type":"uint8"},{"internalType":"string","name":"onChainAssetUUID","type":"string"},{"internalType":"string","name":"issuerUUID","type":"string"},{"internalType":"string","name":"isin","type":"string"},{"internalType":"string","name":"issuanceDocs","type":"string"},{"internalType":"string","name":"assetClass","type":"string"}],"internalType":"struct IFrictionlessOnChainAssetToken.FOCAIssuanceData","name":"issuanceData_","type":"tuple"},{"components":[{"internalType":"uint256","name":"maturesOn","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"enum IFrictionlessOnChainAssetToken.FrictionlessOnChainAssetStatus","name":"status","type":"uint8"},{"internalType":"uint256","name":"yield","type":"uint256"},{"internalType":"enum IFrictionlessOnChainAssetToken.FrictionlessOnChainAssetRiskGrade","name":"riskGrade","type":"uint8"},{"internalType":"uint256","name":"pullToParValue","type":"uint256"},{"internalType":"address","name":"custodianAddress","type":"address"}],"internalType":"struct IFrictionlessOnChainAssetToken.FOCAUpdateData","name":"updateData_","type":"tuple"}],"name":"deployOnChainAssetToken","outputs":[{"internalType":"address","name":"tokenProxyAddr_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"existingFrictionlessTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"treasuryManager_","type":"address"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTreasuryManager_","type":"address"}],"name":"setTreasuryManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasuryManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50614bc7806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620000cd5760003560e01c80638d5dc33b116200007f578063e27cab021162000062578063e27cab02146200017d578063f2fde38b14620001b4578063fe47a9f214620001cb57600080fd5b80638d5dc33b14620001545780638da5cb5b146200016b57600080fd5b806343bdb45811620000b457806343bdb458146200011c578063715018a614620001335780637351a9fd146200013d57600080fd5b806319ab453c14620000d25780633cea70d914620000eb575b600080fd5b620000e9620000e336600462000a6a565b620001e2565b005b606554620000ff906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b620000ff6200012d36600462000ab4565b6200031b565b620000e9620003e5565b620000ff6200014e36600462000b60565b620003fd565b620000ff6200016536600462000c22565b620004a8565b6033546001600160a01b0316620000ff565b620001a36200018e36600462000a6a565b60666020526000908152604090205460ff1681565b604051901515815260200162000113565b620000e9620001c536600462000a6a565b6200056f565b620000e9620001dc36600462000a6a565b62000605565b600054610100900460ff1615808015620002035750600054600160ff909116105b806200021f5750303b1580156200021f575060005460ff166001145b620002975760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b6000805460ff191660011790558015620002bb576000805461ff0019166101001790555b620002c56200061a565b620002d08262000691565b801562000317576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60006200032762000701565b62000336602085018562000a6a565b62000348604086016020870162000a6a565b6200035a606087016040880162000a6a565b6200036c608088016060890162000a6a565b6200037b608089018962000c9f565b6200038a60a08b018b62000c9f565b8a8a6040516200039a9062000a23565b620003af9a9998979695949392919062000dbf565b604051809103906000f080158015620003cc573d6000803e3d6000fd5b509050620003dd8186600262000749565b949350505050565b620003ef620008f0565b620003fb60006200094c565b565b60006200040962000701565b62000418602086018662000a6a565b6200042a604087016020880162000a6a565b6200043c606088016040890162000a6a565b6200044e6080890160608a0162000a6a565b8787876040516200045f9062000a31565b62000471979695949392919062001049565b604051809103906000f0801580156200048e573d6000803e3d6000fd5b5090506200049f8187600362000749565b95945050505050565b6000620004b462000701565b620004c3602084018462000a6a565b620004d5604085016020860162000a6a565b620004e7606086016040870162000a6a565b620004f9608087016060880162000a6a565b62000508608088018862000c9f565b6200051760a08a018a62000c9f565b89604051620005269062000a3f565b6200053a99989796959493929190620011b0565b604051809103906000f08015801562000557573d6000803e3d6000fd5b509050620005688185600162000749565b9392505050565b62000579620008f0565b6001600160a01b038116620005f75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016200028e565b62000602816200094c565b50565b6200060f620008f0565b620006028162000691565b600054610100900460ff16620006875760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200028e565b620003fb620009ab565b6001600160a01b038116620006d2576040517ffd34162600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6065805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6065546001600160a01b03163314620003fb576040517f0d02f8790000000000000000000000000000000000000000000000000000000081523360048201526024016200028e565b604051634273cc2160e11b81523360048201526001600160a01b038416906384e7984290602401600060405180830381600087803b1580156200078b57600080fd5b505af1158015620007a0573d6000803e3d6000fd5b5050604051634273cc2160e11b81526001600160a01b038581166004830152861692506384e798429150602401600060405180830381600087803b158015620007e857600080fd5b505af1158015620007fd573d6000803e3d6000fd5b50506040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528616925063f2fde38b9150602401600060405180830381600087803b1580156200085e57600080fd5b505af115801562000873573d6000803e3d6000fd5b5050506001600160a01b0384166000908152606660205260409020805460ff1916600117905550806003811115620008af57620008af62000d7d565b6040516001600160a01b03851681527fe0cbb8f98bd53e851ff2b22053a5160602f741269b7a51cdc1f7f646731bef919060200160405180910390a2505050565b6033546001600160a01b03163314620003fb5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016200028e565b603380546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff1662000a185760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200028e565b620003fb336200094c565b6111bd806200129183390190565b611685806200244e83390190565b6110bf8062003ad383390190565b80356001600160a01b038116811462000a6557600080fd5b919050565b60006020828403121562000a7d57600080fd5b620005688262000a4d565b600060c0828403121562000a9b57600080fd5b50919050565b60006060828403121562000a9b57600080fd5b600080600080848603608081121562000acc57600080fd5b62000ad78662000a4d565b9450602086013567ffffffffffffffff8082111562000af557600080fd5b62000b0389838a0162000a88565b9550604088013591508082111562000b1a57600080fd5b5062000b298882890162000aa1565b9350506020605f198201121562000b3f57600080fd5b509295919450926060019150565b600060e0828403121562000a9b57600080fd5b6000806000806000610160868803121562000b7a57600080fd5b62000b858662000a4d565b9450602086013567ffffffffffffffff8082111562000ba357600080fd5b62000bb189838a0162000a88565b9550604088013591508082111562000bc857600080fd5b90870190610120828a03121562000bde57600080fd5b9093506060870135908082111562000bf557600080fd5b5062000c048882890162000b4d565b92505062000c16876080880162000b4d565b90509295509295909350565b60008060006060848603121562000c3857600080fd5b62000c438462000a4d565b9250602084013567ffffffffffffffff8082111562000c6157600080fd5b62000c6f8783880162000a88565b9350604086013591508082111562000c8657600080fd5b5062000c958682870162000aa1565b9150509250925092565b6000808335601e1984360301811262000cb757600080fd5b83018035915067ffffffffffffffff82111562000cd357600080fd5b60200191503681900382131562000ce957600080fd5b9250929050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000808335601e1984360301811262000d3157600080fd5b830160208101925035905067ffffffffffffffff81111562000d5257600080fd5b80360382131562000ce957600080fd5b600281106200060257600080fd5b803562000a658162000d62565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6002811062000602576200060262000d7d565b60006101006001600160a01b03808e168452808d166020850152808c166040850152808b16606085015281608085015262000dfe8285018a8c62000cf0565b915083820360a085015262000e1582888a62000cf0565b915083820360c085015262000e2b868762000d19565b6060845262000e3f60608501828462000cf0565b915050602087013562000e528162000d62565b62000e5d8162000dac565b60208401528162000e716040890162000a4d565b16604084015280935050505062000e8b60e0830184359052565b9b9a5050505050505050505050565b62000ea58162000dac565b9052565b80356007811062000a6557600080fd5b6007811062000ea55762000ea562000d7d565b6004811062000ea55762000ea562000d7d565b80358252600060208201356004811062000ef857600080fd5b62000f07602085018262000ecc565b5062000f17604083018362000d19565b60e0604086015262000f2e60e08601828462000cf0565b91505062000f40606084018462000d19565b858303606087015262000f5583828462000cf0565b9250505062000f68608084018462000d19565b858303608087015262000f7d83828462000cf0565b9250505062000f9060a084018462000d19565b85830360a087015262000fa583828462000cf0565b9250505062000fb860c084018462000d19565b85830360c087015262000fcd83828462000cf0565b9695505050505050565b803582526020810135602083015260408101356005811062000ff857600080fd5b6040830152606081810135908301526080810135600b81106200101a57600080fd5b608083015260a081810135908301526001600160a01b036200103f60c0830162000a4d565b1660c08301525050565b60006101a06001600160a01b03808b168452808a16602085015280891660408501528088166060850152508060808401528535818401525060208501356101c08301526200109a6040860162000d70565b620010aa6101e084018262000e9a565b50620010b96060860162000ea9565b620010c961020084018262000eb9565b50620010d86080860162000d70565b620010e861022084018262000e9a565b50620010f860a086018662000d19565b610120610240850152620011126102c08501828462000cf0565b91505060c08601356102608401526200112f60e087018762000d19565b61019f1980868503016102808701526200114b84838562000cf0565b93506200115d6101008a018a62000d19565b9350915080868503016102a0870152506200117a83838362000cf0565b9250505082810360a084015262001192818662000edf565b915050620011a460c083018462000fd7565b98975050505050505050565b60006001600160a01b03808c168352808b166020840152808a16604084015280891660608401525060e06080830152620011ef60e08301878962000cf0565b82810360a08401526200120481868862000cf0565b905082810360c08401526200121a848562000d19565b606083526200122e60608401828462000cf0565b91505062001240602086018662000d19565b83830360208501526200125583828462000cf0565b9250505062001268604086018662000d19565b83830360408501526200127d83828462000cf0565b9f9e50505050505050505050505050505056fe60806040523480156200001157600080fd5b50604051620011bd380380620011bd8339810160408190526200003491620008ac565b878787868660068a6001600160a01b038716158015906200005d57506001600160a01b03861615155b80156200007257506001600160a01b03851615155b620000c45760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f20616464726573730060448201526064015b60405180910390fd5b604051602001620000e090602080825260009082015260400190565b6040516020818303038152906040528051906020012084604051602001620001099190620009cb565b60405160208183030381529060405280519060200120141580156200018757506040516020016200014590602080825260009082015260400190565b60405160208183030381529060405280519060200120836040516020016200016e9190620009cb565b6040516020818303038152906040528051906020012014155b620001d55760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d20656d70747920737472696e67006044820152606401620000bb565b60128260ff1611156200022b5760405162461bcd60e51b815260206004820152601960248201527f646563696d616c73206265747765656e203020616e64203138000000000000006044820152606401620000bb565b62000243876000805160206200119d83398151915255565b6040516001600160a01b038816907f3b1074392ed8e8424715d0dda2197eede67080b377fc8370e26f3e882207f6b890600090a26000620002916000805160206200119d8339815191525490565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002cf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f59190620009e7565b90506000816001600160a01b0316888888888888604051602401620003209695949392919062000a05565b60408051601f198184030181529181526020820180516001600160e01b0316633e46d86760e21b1790525162000357919062000a64565b600060405180830381855af49150503d806000811462000394576040519150601f19603f3d011682016040523d82523d6000602084013e62000399565b606091505b5050905080620003ec5760405162461bcd60e51b815260206004820152601660248201527f496e697469616c697a6174696f6e206661696c65642e000000000000000000006044820152606401620000bb565b505050505050505050600062000407620006d360201b60201c565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000445573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200046b9190620009e7565b90506000816001600160a01b0316637de4fba960e01b600260405160240162000495919062000a98565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620004d5919062000a64565b600060405180830381855af49150503d806000811462000512576040519150601f19603f3d011682016040523d82523d6000602084013e62000517565b606091505b50509050806200053a576040516311c8524960e31b815260040160405180910390fd5b6000826001600160a01b031663670b34c660e01b8660405160240162000561919062000ab5565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620005a1919062000a64565b600060405180830381855af49150503d8060008114620005de576040519150601f19603f3d011682016040523d82523d6000602084013e620005e3565b606091505b50509050806200060657604051635dba357d60e01b815260040160405180910390fd5b60408051855160248083019190915282518083039091018152604490910182526020810180516001600160e01b03166350062e8b60e11b17905290516000916001600160a01b038616916200065c919062000a64565b600060405180830381855af49150503d806000811462000699576040519150601f19603f3d011682016040523d82523d6000602084013e6200069e565b606091505b5050905080620006c1576040516301a74a2f60e61b815260040160405180910390fd5b50505050505050505050505062000b11565b6000805160206200119d8339815191525490565b80516001600160a01b0381168114620006ff57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620007375781810151838201526020016200071d565b50506000910152565b600082601f8301126200075257600080fd5b81516001600160401b03808211156200076f576200076f62000704565b604051601f8301601f19908116603f011681019082821181831017156200079a576200079a62000704565b81604052838152866020858801011115620007b457600080fd5b620007c78460208301602089016200071a565b9695505050505050565b600060608284031215620007e457600080fd5b604051606081016001600160401b0380821183831017156200080a576200080a62000704565b8160405282935084519150808211156200082357600080fd5b50620008328582860162000740565b8252506020830151600281106200084857600080fd5b60208201526200085b60408401620006e7565b60408201525092915050565b6000602082840312156200087a57600080fd5b604051602081016001600160401b03811182821017156200089f576200089f62000704565b6040529151825250919050565b600080600080600080600080610100898b031215620008ca57600080fd5b620008d589620006e7565b9750620008e560208a01620006e7565b9650620008f560408a01620006e7565b95506200090560608a01620006e7565b60808a01519095506001600160401b03808211156200092357600080fd5b620009318c838d0162000740565b955060a08b01519150808211156200094857600080fd5b620009568c838d0162000740565b945060c08b01519150808211156200096d57600080fd5b506200097c8b828c01620007d1565b9250506200098e8a60e08b0162000867565b90509295985092959890939650565b60008151808452620009b78160208601602086016200071a565b601f01601f19169290920160200192915050565b602081526000620009e060208301846200099d565b9392505050565b600060208284031215620009fa57600080fd5b620009e082620006e7565b600060018060a01b038089168352808816602084015260c0604084015262000a3160c08401886200099d565b838103606085015262000a4581886200099d565b60ff969096166080850152509290921660a09091015250949350505050565b6000825162000a788184602087016200071a565b9190910192915050565b634e487b7160e01b600052602160045260246000fd5b602081016004831062000aaf5762000aaf62000a82565b91905290565b60208152600082516060602084015262000ad360808401826200099d565b905060208401516002811062000aed5762000aed62000a82565b60408481019190915293909301516001600160a01b03166060909201919091525090565b61067c8062000b216000396000f3fe6080604052600436106100295760003560e01c80632d5f1187146100e157806392dd9d651461012c575b60006100537fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf75490565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610090573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100b49190610605565b90503660008037600080366000846127105a03f43d806000803e8180156100da57816000f35b816000fd5b005b3480156100ed57600080fd5b507fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7546040516001600160a01b03909116815260200160405180910390f35b34801561013857600080fd5b506100df610147366004610629565b7fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7546001600160a01b0316336001600160a01b0316146101f45760405162461bcd60e51b815260206004820152602d60248201527f6f6e6c792063757272656e7420696d706c656d656e746174696f6e417574686f60448201527f726974792063616e2063616c6c0000000000000000000000000000000000000060648201526084015b60405180910390fd5b6001600160a01b03811661024a5760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f20616464726573730060448201526064016101eb565b60006001600160a01b0316816001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b79190610605565b6001600160a01b031614158015610342575060006001600160a01b0316816001600160a01b0316636ff6e83f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610312573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103369190610605565b6001600160a01b031614155b80156103c2575060006001600160a01b0316816001600160a01b0316631ee9ce8b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b69190610605565b6001600160a01b031614155b8015610442575060006001600160a01b0316816001600160a01b0316639e3e7bb96040518163ffffffff1660e01b8152600401602060405180830381865afa158015610412573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104369190610605565b6001600160a01b031614155b80156104c2575060006001600160a01b0316816001600160a01b03166361f898256040518163ffffffff1660e01b8152600401602060405180830381865afa158015610492573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b69190610605565b6001600160a01b031614155b8015610542575060006001600160a01b0316816001600160a01b031663fedcc0526040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190610605565b6001600160a01b031614155b61058e5760405162461bcd60e51b815260206004820181905260248201527f696e76616c696420496d706c656d656e746174696f6e20417574686f7269747960448201526064016101eb565b6105b6817fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf755565b6040516001600160a01b038216907f3b1074392ed8e8424715d0dda2197eede67080b377fc8370e26f3e882207f6b890600090a250565b6001600160a01b038116811461060257600080fd5b50565b60006020828403121561061757600080fd5b8151610622816105ed565b9392505050565b60006020828403121561063b57600080fd5b8135610622816105ed56fea2646970667358221220e2b3607324991b75ea05434eed06ce75e7e2545c439a3e7eaba40e7d7c281cf564736f6c63430008110033c5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf760806040523480156200001157600080fd5b506040516200168538038062001685833981016040819052620000349162000ad9565b8686868560e0015186610100015160068960006001600160a01b0316876001600160a01b0316141580156200007157506001600160a01b03861615155b80156200008657506001600160a01b03851615155b620000d85760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f20616464726573730060448201526064015b60405180910390fd5b604051602001620000f490602080825260009082015260400190565b60405160208183030381529060405280519060200120846040516020016200011d919062000cad565b60405160208183030381529060405280519060200120141580156200019b57506040516020016200015990602080825260009082015260400190565b604051602081830303815290604052805190602001208360405160200162000182919062000cad565b6040516020818303038152906040528051906020012014155b620001e95760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d20656d70747920737472696e67006044820152606401620000cf565b60128260ff1611156200023f5760405162461bcd60e51b815260206004820152601960248201527f646563696d616c73206265747765656e203020616e64203138000000000000006044820152606401620000cf565b62000257876000805160206200166583398151915255565b6040516001600160a01b038816907f3b1074392ed8e8424715d0dda2197eede67080b377fc8370e26f3e882207f6b890600090a26000620002a5600080516020620016658339815191525490565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000309919062000cc9565b90506000816001600160a01b0316888888888888604051602401620003349695949392919062000ce7565b60408051601f198184030181529181526020820180516001600160e01b0316633e46d86760e21b179052516200036b919062000d46565b600060405180830381855af49150503d8060008114620003a8576040519150601f19603f3d011682016040523d82523d6000602084013e620003ad565b606091505b5050905080620004005760405162461bcd60e51b815260206004820152601660248201527f496e697469616c697a6174696f6e206661696c65642e000000000000000000006044820152606401620000cf565b50505050505050505060006200041b620007c460201b60201c565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000459573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200047f919062000cc9565b90506000816001600160a01b0316637de4fba960e01b6003604051602401620004a9919062000d90565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620004e9919062000d46565b600060405180830381855af49150503d806000811462000526576040519150601f19603f3d011682016040523d82523d6000602084013e6200052b565b606091505b50509050806200054e5760405163c0602fd160e01b815260040160405180910390fd5b6000826001600160a01b0316630b9fff7460e01b8760405160240162000575919062000dcf565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620005b5919062000d46565b600060405180830381855af49150503d8060008114620005f2576040519150601f19603f3d011682016040523d82523d6000602084013e620005f7565b606091505b50509050806200061a576040516303aa38ab60e01b815260040160405180910390fd5b6000836001600160a01b031663a1e4b78660e01b8760405160240162000641919062000e8d565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905162000681919062000d46565b600060405180830381855af49150503d8060008114620006be576040519150601f19603f3d011682016040523d82523d6000602084013e620006c3565b606091505b5050905080620006e6576040516341de8ffd60e01b815260040160405180910390fd5b6000846001600160a01b03166344ed4f8960e01b876040516024016200070d919062000f54565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516200074d919062000d46565b600060405180830381855af49150503d80600081146200078a576040519150601f19603f3d011682016040523d82523d6000602084013e6200078f565b606091505b5050905080620007b257604051638274ff7760e01b815260040160405180910390fd5b50505050505050505050505062000fd9565b600080516020620016658339815191525490565b80516001600160a01b0381168114620007f057600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b0381118282101715620008305762000830620007f5565b60405290565b60405161012081016001600160401b0381118282101715620008305762000830620007f5565b805160028110620007f057600080fd5b805160078110620007f057600080fd5b60005b83811015620008995781810151838201526020016200087f565b50506000910152565b600082601f830112620008b457600080fd5b81516001600160401b0380821115620008d157620008d1620007f5565b604051601f8301601f19908116603f01168101908282118183101715620008fc57620008fc620007f5565b816040528381528660208588010111156200091657600080fd5b620009298460208301602089016200087c565b9695505050505050565b805160048110620007f057600080fd5b600060e082840312156200095657600080fd5b620009606200080b565b905081518152620009746020830162000933565b602082015260408201516001600160401b03808211156200099457600080fd5b620009a285838601620008a2565b60408401526060840151915080821115620009bc57600080fd5b620009ca85838601620008a2565b60608401526080840151915080821115620009e457600080fd5b620009f285838601620008a2565b608084015260a084015191508082111562000a0c57600080fd5b62000a1a85838601620008a2565b60a084015260c084015191508082111562000a3457600080fd5b5062000a4384828501620008a2565b60c08301525092915050565b600060e0828403121562000a6257600080fd5b62000a6c6200080b565b9050815181526020820151602082015260408201516005811062000a8f57600080fd5b6040820152606082810151908201526080820151600b811062000ab157600080fd5b608082015260a0828101519082015262000ace60c08301620007d8565b60c082015292915050565b60008060008060008060006101a0888a03121562000af657600080fd5b62000b0188620007d8565b965062000b1160208901620007d8565b955062000b2160408901620007d8565b945062000b3160608901620007d8565b60808901519094506001600160401b038082111562000b4f57600080fd5b90890190610120828c03121562000b6557600080fd5b62000b6f62000836565b825181526020830151602082015262000b8b604084016200085c565b604082015262000b9e606084016200086c565b606082015262000bb1608084016200085c565b608082015260a08301518281111562000bc957600080fd5b62000bd78d828601620008a2565b60a08301525060c083015160c082015260e08301518281111562000bfa57600080fd5b62000c088d828601620008a2565b60e083015250610100808401518381111562000c2357600080fd5b62000c318e828701620008a2565b8284015250508095505060a08a015191508082111562000c5057600080fd5b5062000c5f8a828b0162000943565b92505062000c718960c08a0162000a4f565b905092959891949750929550565b6000815180845262000c998160208601602086016200087c565b601f01601f19169290920160200192915050565b60208152600062000cc2602083018462000c7f565b9392505050565b60006020828403121562000cdc57600080fd5b62000cc282620007d8565b600060018060a01b038089168352808816602084015260c0604084015262000d1360c084018862000c7f565b838103606085015262000d27818862000c7f565b60ff969096166080850152509290921660a09091015250949350505050565b6000825162000d5a8184602087016200087c565b9190910192915050565b634e487b7160e01b600052602160045260246000fd5b6004811062000d8d5762000d8d62000d64565b50565b6020810162000d9f8362000d7a565b91905290565b6002811062000db85762000db862000d64565b9052565b6007811062000db85762000db862000d64565b6020815281516020820152602082015160408201526000604083015162000dfa606084018262000da5565b50606083015162000e0f608084018262000dbc565b50608083015162000e2460a084018262000da5565b5060a08301516101208060c085015262000e4361014085018362000c7f565b915060c085015160e085015260e0850151601f1961010081878603018188015262000e6f858462000c7f565b90880151878203909201848801529350905062000929838262000c7f565b60208152815160208201526000602083015162000eaa8162000d7a565b80604084015250604083015160e0606084015262000ecd61010084018262000c7f565b90506060840151601f198085840301608086015262000eed838362000c7f565b925060808601519150808584030160a086015262000f0c838362000c7f565b925060a08601519150808584030160c086015262000f2b838362000c7f565b925060c08601519150808584030160e08601525062000f4b828262000c7f565b95945050505050565b8151815260208083015190820152604082015160e08201906005811062000f7f5762000f7f62000d64565b6040830152606083810151908301526080830151600b811062000fa65762000fa662000d64565b8060808401525060a083015160a083015260c083015162000fd260c08401826001600160a01b03169052565b5092915050565b61067c8062000fe96000396000f3fe6080604052600436106100295760003560e01c80632d5f1187146100e157806392dd9d651461012c575b60006100537fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf75490565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610090573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100b49190610605565b90503660008037600080366000846127105a03f43d806000803e8180156100da57816000f35b816000fd5b005b3480156100ed57600080fd5b507fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7546040516001600160a01b03909116815260200160405180910390f35b34801561013857600080fd5b506100df610147366004610629565b7fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7546001600160a01b0316336001600160a01b0316146101f45760405162461bcd60e51b815260206004820152602d60248201527f6f6e6c792063757272656e7420696d706c656d656e746174696f6e417574686f60448201527f726974792063616e2063616c6c0000000000000000000000000000000000000060648201526084015b60405180910390fd5b6001600160a01b03811661024a5760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f20616464726573730060448201526064016101eb565b60006001600160a01b0316816001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b79190610605565b6001600160a01b031614158015610342575060006001600160a01b0316816001600160a01b0316636ff6e83f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610312573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103369190610605565b6001600160a01b031614155b80156103c2575060006001600160a01b0316816001600160a01b0316631ee9ce8b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b69190610605565b6001600160a01b031614155b8015610442575060006001600160a01b0316816001600160a01b0316639e3e7bb96040518163ffffffff1660e01b8152600401602060405180830381865afa158015610412573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104369190610605565b6001600160a01b031614155b80156104c2575060006001600160a01b0316816001600160a01b03166361f898256040518163ffffffff1660e01b8152600401602060405180830381865afa158015610492573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b69190610605565b6001600160a01b031614155b8015610542575060006001600160a01b0316816001600160a01b031663fedcc0526040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190610605565b6001600160a01b031614155b61058e5760405162461bcd60e51b815260206004820181905260248201527f696e76616c696420496d706c656d656e746174696f6e20417574686f7269747960448201526064016101eb565b6105b6817fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf755565b6040516001600160a01b038216907f3b1074392ed8e8424715d0dda2197eede67080b377fc8370e26f3e882207f6b890600090a250565b6001600160a01b038116811461060257600080fd5b50565b60006020828403121561061757600080fd5b8151610622816105ed565b9392505050565b60006020828403121561063b57600080fd5b8135610622816105ed56fea264697066735822122022a9c01e849f34319575950c89541bbfb0e2abafb7d994e66d7b0ffc5adbfff464736f6c63430008110033c5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf760806040523480156200001157600080fd5b50604051620010bf380380620010bf83398101604081905262000034916200073f565b86868685856006896001600160a01b038716158015906200005d57506001600160a01b03861615155b80156200007257506001600160a01b03851615155b620000c45760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f20616464726573730060448201526064015b60405180910390fd5b604051602001620000e090602080825260009082015260400190565b6040516020818303038152906040528051906020012084604051602001620001099190620008cc565b60405160208183030381529060405280519060200120141580156200018757506040516020016200014590602080825260009082015260400190565b60405160208183030381529060405280519060200120836040516020016200016e9190620008cc565b6040516020818303038152906040528051906020012014155b620001d55760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d20656d70747920737472696e67006044820152606401620000bb565b60128260ff1611156200022b5760405162461bcd60e51b815260206004820152601960248201527f646563696d616c73206265747765656e203020616e64203138000000000000006044820152606401620000bb565b62000243876000805160206200109f83398151915255565b6040516001600160a01b038816907f3b1074392ed8e8424715d0dda2197eede67080b377fc8370e26f3e882207f6b890600090a26000620002916000805160206200109f8339815191525490565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002cf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f59190620008e8565b90506000816001600160a01b0316888888888888604051602401620003209695949392919062000906565b60408051601f198184030181529181526020820180516001600160e01b0316633e46d86760e21b1790525162000357919062000965565b600060405180830381855af49150503d806000811462000394576040519150601f19603f3d011682016040523d82523d6000602084013e62000399565b606091505b5050905080620003ec5760405162461bcd60e51b815260206004820152601660248201527f496e697469616c697a6174696f6e206661696c65642e000000000000000000006044820152606401620000bb565b5050505050505050506000620004076200061660201b60201c565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000445573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200046b9190620008e8565b90506000816001600160a01b0316637de4fba960e01b600160405160240162000495919062000983565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620004d5919062000965565b600060405180830381855af49150503d806000811462000512576040519150601f19603f3d011682016040523d82523d6000602084013e62000517565b606091505b50509050806200053a57604051631d815ba160e31b815260040160405180910390fd5b6000826001600160a01b031663d18c2cec60e01b85604051602401620005619190620009ac565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620005a1919062000965565b600060405180830381855af49150503d8060008114620005de576040519150601f19603f3d011682016040523d82523d6000602084013e620005e3565b606091505b505090508062000606576040516304b1dbbb60e41b815260040160405180910390fd5b5050505050505050505062000a13565b6000805160206200109f8339815191525490565b80516001600160a01b03811681146200064257600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171562000682576200068262000647565b60405290565b60005b83811015620006a55781810151838201526020016200068b565b50506000910152565b600082601f830112620006c057600080fd5b81516001600160401b0380821115620006dd57620006dd62000647565b604051601f8301601f19908116603f0116810190828211818310171562000708576200070862000647565b816040528381528660208588010111156200072257600080fd5b6200073584602083016020890162000688565b9695505050505050565b600080600080600080600060e0888a0312156200075b57600080fd5b62000766886200062a565b965062000776602089016200062a565b955062000786604089016200062a565b945062000796606089016200062a565b60808901519094506001600160401b0380821115620007b457600080fd5b620007c28b838c01620006ae565b945060a08a0151915080821115620007d957600080fd5b620007e78b838c01620006ae565b935060c08a0151915080821115620007fe57600080fd5b908901906060828c0312156200081357600080fd5b6200081d6200065d565b8251828111156200082d57600080fd5b6200083b8d828601620006ae565b8252506020830151828111156200085157600080fd5b6200085f8d828601620006ae565b6020830152506040830151828111156200087857600080fd5b620008868d828601620006ae565b60408301525080935050505092959891949750929550565b60008151808452620008b881602086016020860162000688565b601f01601f19169290920160200192915050565b602081526000620008e160208301846200089e565b9392505050565b600060208284031215620008fb57600080fd5b620008e1826200062a565b600060018060a01b038089168352808816602084015260c060408401526200093260c08401886200089e565b83810360608501526200094681886200089e565b60ff969096166080850152509290921660a09091015250949350505050565b600082516200097981846020870162000688565b9190910192915050565b6020810160048310620009a657634e487b7160e01b600052602160045260246000fd5b91905290565b602081526000825160606020840152620009ca60808401826200089e565b90506020840151601f1980858403016040860152620009ea83836200089e565b925060408601519150808584030160608601525062000a0a82826200089e565b95945050505050565b61067c8062000a236000396000f3fe6080604052600436106100295760003560e01c80632d5f1187146100e157806392dd9d651461012c575b60006100537fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf75490565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610090573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100b49190610605565b90503660008037600080366000846127105a03f43d806000803e8180156100da57816000f35b816000fd5b005b3480156100ed57600080fd5b507fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7546040516001600160a01b03909116815260200160405180910390f35b34801561013857600080fd5b506100df610147366004610629565b7fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7546001600160a01b0316336001600160a01b0316146101f45760405162461bcd60e51b815260206004820152602d60248201527f6f6e6c792063757272656e7420696d706c656d656e746174696f6e417574686f60448201527f726974792063616e2063616c6c0000000000000000000000000000000000000060648201526084015b60405180910390fd5b6001600160a01b03811661024a5760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f20616464726573730060448201526064016101eb565b60006001600160a01b0316816001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b79190610605565b6001600160a01b031614158015610342575060006001600160a01b0316816001600160a01b0316636ff6e83f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610312573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103369190610605565b6001600160a01b031614155b80156103c2575060006001600160a01b0316816001600160a01b0316631ee9ce8b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b69190610605565b6001600160a01b031614155b8015610442575060006001600160a01b0316816001600160a01b0316639e3e7bb96040518163ffffffff1660e01b8152600401602060405180830381865afa158015610412573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104369190610605565b6001600160a01b031614155b80156104c2575060006001600160a01b0316816001600160a01b03166361f898256040518163ffffffff1660e01b8152600401602060405180830381865afa158015610492573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b69190610605565b6001600160a01b031614155b8015610542575060006001600160a01b0316816001600160a01b031663fedcc0526040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190610605565b6001600160a01b031614155b61058e5760405162461bcd60e51b815260206004820181905260248201527f696e76616c696420496d706c656d656e746174696f6e20417574686f7269747960448201526064016101eb565b6105b6817fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf755565b6040516001600160a01b038216907f3b1074392ed8e8424715d0dda2197eede67080b377fc8370e26f3e882207f6b890600090a250565b6001600160a01b038116811461060257600080fd5b50565b60006020828403121561061757600080fd5b8151610622816105ed565b9392505050565b60006020828403121561063b57600080fd5b8135610622816105ed56fea26469706673582212203016a425840f79186f918e1c7a57764b1f07d0d62c2379ff3388882ee26cbaed64736f6c63430008110033c5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7a2646970667358221220d989ba8e5d265a20f0554796c890394e63c76efcb104890ef318ee4f2017317d64736f6c63430008110033
Deployed Bytecode
0x60806040523480156200001157600080fd5b5060043610620000cd5760003560e01c80638d5dc33b116200007f578063e27cab021162000062578063e27cab02146200017d578063f2fde38b14620001b4578063fe47a9f214620001cb57600080fd5b80638d5dc33b14620001545780638da5cb5b146200016b57600080fd5b806343bdb45811620000b457806343bdb458146200011c578063715018a614620001335780637351a9fd146200013d57600080fd5b806319ab453c14620000d25780633cea70d914620000eb575b600080fd5b620000e9620000e336600462000a6a565b620001e2565b005b606554620000ff906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b620000ff6200012d36600462000ab4565b6200031b565b620000e9620003e5565b620000ff6200014e36600462000b60565b620003fd565b620000ff6200016536600462000c22565b620004a8565b6033546001600160a01b0316620000ff565b620001a36200018e36600462000a6a565b60666020526000908152604090205460ff1681565b604051901515815260200162000113565b620000e9620001c536600462000a6a565b6200056f565b620000e9620001dc36600462000a6a565b62000605565b600054610100900460ff1615808015620002035750600054600160ff909116105b806200021f5750303b1580156200021f575060005460ff166001145b620002975760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b6000805460ff191660011790558015620002bb576000805461ff0019166101001790555b620002c56200061a565b620002d08262000691565b801562000317576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60006200032762000701565b62000336602085018562000a6a565b62000348604086016020870162000a6a565b6200035a606087016040880162000a6a565b6200036c608088016060890162000a6a565b6200037b608089018962000c9f565b6200038a60a08b018b62000c9f565b8a8a6040516200039a9062000a23565b620003af9a9998979695949392919062000dbf565b604051809103906000f080158015620003cc573d6000803e3d6000fd5b509050620003dd8186600262000749565b949350505050565b620003ef620008f0565b620003fb60006200094c565b565b60006200040962000701565b62000418602086018662000a6a565b6200042a604087016020880162000a6a565b6200043c606088016040890162000a6a565b6200044e6080890160608a0162000a6a565b8787876040516200045f9062000a31565b62000471979695949392919062001049565b604051809103906000f0801580156200048e573d6000803e3d6000fd5b5090506200049f8187600362000749565b95945050505050565b6000620004b462000701565b620004c3602084018462000a6a565b620004d5604085016020860162000a6a565b620004e7606086016040870162000a6a565b620004f9608087016060880162000a6a565b62000508608088018862000c9f565b6200051760a08a018a62000c9f565b89604051620005269062000a3f565b6200053a99989796959493929190620011b0565b604051809103906000f08015801562000557573d6000803e3d6000fd5b509050620005688185600162000749565b9392505050565b62000579620008f0565b6001600160a01b038116620005f75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016200028e565b62000602816200094c565b50565b6200060f620008f0565b620006028162000691565b600054610100900460ff16620006875760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200028e565b620003fb620009ab565b6001600160a01b038116620006d2576040517ffd34162600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6065805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6065546001600160a01b03163314620003fb576040517f0d02f8790000000000000000000000000000000000000000000000000000000081523360048201526024016200028e565b604051634273cc2160e11b81523360048201526001600160a01b038416906384e7984290602401600060405180830381600087803b1580156200078b57600080fd5b505af1158015620007a0573d6000803e3d6000fd5b5050604051634273cc2160e11b81526001600160a01b038581166004830152861692506384e798429150602401600060405180830381600087803b158015620007e857600080fd5b505af1158015620007fd573d6000803e3d6000fd5b50506040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528616925063f2fde38b9150602401600060405180830381600087803b1580156200085e57600080fd5b505af115801562000873573d6000803e3d6000fd5b5050506001600160a01b0384166000908152606660205260409020805460ff1916600117905550806003811115620008af57620008af62000d7d565b6040516001600160a01b03851681527fe0cbb8f98bd53e851ff2b22053a5160602f741269b7a51cdc1f7f646731bef919060200160405180910390a2505050565b6033546001600160a01b03163314620003fb5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016200028e565b603380546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff1662000a185760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200028e565b620003fb336200094c565b6111bd806200129183390190565b611685806200244e83390190565b6110bf8062003ad383390190565b80356001600160a01b038116811462000a6557600080fd5b919050565b60006020828403121562000a7d57600080fd5b620005688262000a4d565b600060c0828403121562000a9b57600080fd5b50919050565b60006060828403121562000a9b57600080fd5b600080600080848603608081121562000acc57600080fd5b62000ad78662000a4d565b9450602086013567ffffffffffffffff8082111562000af557600080fd5b62000b0389838a0162000a88565b9550604088013591508082111562000b1a57600080fd5b5062000b298882890162000aa1565b9350506020605f198201121562000b3f57600080fd5b509295919450926060019150565b600060e0828403121562000a9b57600080fd5b6000806000806000610160868803121562000b7a57600080fd5b62000b858662000a4d565b9450602086013567ffffffffffffffff8082111562000ba357600080fd5b62000bb189838a0162000a88565b9550604088013591508082111562000bc857600080fd5b90870190610120828a03121562000bde57600080fd5b9093506060870135908082111562000bf557600080fd5b5062000c048882890162000b4d565b92505062000c16876080880162000b4d565b90509295509295909350565b60008060006060848603121562000c3857600080fd5b62000c438462000a4d565b9250602084013567ffffffffffffffff8082111562000c6157600080fd5b62000c6f8783880162000a88565b9350604086013591508082111562000c8657600080fd5b5062000c958682870162000aa1565b9150509250925092565b6000808335601e1984360301811262000cb757600080fd5b83018035915067ffffffffffffffff82111562000cd357600080fd5b60200191503681900382131562000ce957600080fd5b9250929050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000808335601e1984360301811262000d3157600080fd5b830160208101925035905067ffffffffffffffff81111562000d5257600080fd5b80360382131562000ce957600080fd5b600281106200060257600080fd5b803562000a658162000d62565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6002811062000602576200060262000d7d565b60006101006001600160a01b03808e168452808d166020850152808c166040850152808b16606085015281608085015262000dfe8285018a8c62000cf0565b915083820360a085015262000e1582888a62000cf0565b915083820360c085015262000e2b868762000d19565b6060845262000e3f60608501828462000cf0565b915050602087013562000e528162000d62565b62000e5d8162000dac565b60208401528162000e716040890162000a4d565b16604084015280935050505062000e8b60e0830184359052565b9b9a5050505050505050505050565b62000ea58162000dac565b9052565b80356007811062000a6557600080fd5b6007811062000ea55762000ea562000d7d565b6004811062000ea55762000ea562000d7d565b80358252600060208201356004811062000ef857600080fd5b62000f07602085018262000ecc565b5062000f17604083018362000d19565b60e0604086015262000f2e60e08601828462000cf0565b91505062000f40606084018462000d19565b858303606087015262000f5583828462000cf0565b9250505062000f68608084018462000d19565b858303608087015262000f7d83828462000cf0565b9250505062000f9060a084018462000d19565b85830360a087015262000fa583828462000cf0565b9250505062000fb860c084018462000d19565b85830360c087015262000fcd83828462000cf0565b9695505050505050565b803582526020810135602083015260408101356005811062000ff857600080fd5b6040830152606081810135908301526080810135600b81106200101a57600080fd5b608083015260a081810135908301526001600160a01b036200103f60c0830162000a4d565b1660c08301525050565b60006101a06001600160a01b03808b168452808a16602085015280891660408501528088166060850152508060808401528535818401525060208501356101c08301526200109a6040860162000d70565b620010aa6101e084018262000e9a565b50620010b96060860162000ea9565b620010c961020084018262000eb9565b50620010d86080860162000d70565b620010e861022084018262000e9a565b50620010f860a086018662000d19565b610120610240850152620011126102c08501828462000cf0565b91505060c08601356102608401526200112f60e087018762000d19565b61019f1980868503016102808701526200114b84838562000cf0565b93506200115d6101008a018a62000d19565b9350915080868503016102a0870152506200117a83838362000cf0565b9250505082810360a084015262001192818662000edf565b915050620011a460c083018462000fd7565b98975050505050505050565b60006001600160a01b03808c168352808b166020840152808a16604084015280891660608401525060e06080830152620011ef60e08301878962000cf0565b82810360a08401526200120481868862000cf0565b905082810360c08401526200121a848562000d19565b606083526200122e60608401828462000cf0565b91505062001240602086018662000d19565b83830360208501526200125583828462000cf0565b9250505062001268604086018662000d19565b83830360408501526200127d83828462000cf0565b9f9e50505050505050505050505050505056fe60806040523480156200001157600080fd5b50604051620011bd380380620011bd8339810160408190526200003491620008ac565b878787868660068a6001600160a01b038716158015906200005d57506001600160a01b03861615155b80156200007257506001600160a01b03851615155b620000c45760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f20616464726573730060448201526064015b60405180910390fd5b604051602001620000e090602080825260009082015260400190565b6040516020818303038152906040528051906020012084604051602001620001099190620009cb565b60405160208183030381529060405280519060200120141580156200018757506040516020016200014590602080825260009082015260400190565b60405160208183030381529060405280519060200120836040516020016200016e9190620009cb565b6040516020818303038152906040528051906020012014155b620001d55760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d20656d70747920737472696e67006044820152606401620000bb565b60128260ff1611156200022b5760405162461bcd60e51b815260206004820152601960248201527f646563696d616c73206265747765656e203020616e64203138000000000000006044820152606401620000bb565b62000243876000805160206200119d83398151915255565b6040516001600160a01b038816907f3b1074392ed8e8424715d0dda2197eede67080b377fc8370e26f3e882207f6b890600090a26000620002916000805160206200119d8339815191525490565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002cf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f59190620009e7565b90506000816001600160a01b0316888888888888604051602401620003209695949392919062000a05565b60408051601f198184030181529181526020820180516001600160e01b0316633e46d86760e21b1790525162000357919062000a64565b600060405180830381855af49150503d806000811462000394576040519150601f19603f3d011682016040523d82523d6000602084013e62000399565b606091505b5050905080620003ec5760405162461bcd60e51b815260206004820152601660248201527f496e697469616c697a6174696f6e206661696c65642e000000000000000000006044820152606401620000bb565b505050505050505050600062000407620006d360201b60201c565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000445573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200046b9190620009e7565b90506000816001600160a01b0316637de4fba960e01b600260405160240162000495919062000a98565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620004d5919062000a64565b600060405180830381855af49150503d806000811462000512576040519150601f19603f3d011682016040523d82523d6000602084013e62000517565b606091505b50509050806200053a576040516311c8524960e31b815260040160405180910390fd5b6000826001600160a01b031663670b34c660e01b8660405160240162000561919062000ab5565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620005a1919062000a64565b600060405180830381855af49150503d8060008114620005de576040519150601f19603f3d011682016040523d82523d6000602084013e620005e3565b606091505b50509050806200060657604051635dba357d60e01b815260040160405180910390fd5b60408051855160248083019190915282518083039091018152604490910182526020810180516001600160e01b03166350062e8b60e11b17905290516000916001600160a01b038616916200065c919062000a64565b600060405180830381855af49150503d806000811462000699576040519150601f19603f3d011682016040523d82523d6000602084013e6200069e565b606091505b5050905080620006c1576040516301a74a2f60e61b815260040160405180910390fd5b50505050505050505050505062000b11565b6000805160206200119d8339815191525490565b80516001600160a01b0381168114620006ff57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620007375781810151838201526020016200071d565b50506000910152565b600082601f8301126200075257600080fd5b81516001600160401b03808211156200076f576200076f62000704565b604051601f8301601f19908116603f011681019082821181831017156200079a576200079a62000704565b81604052838152866020858801011115620007b457600080fd5b620007c78460208301602089016200071a565b9695505050505050565b600060608284031215620007e457600080fd5b604051606081016001600160401b0380821183831017156200080a576200080a62000704565b8160405282935084519150808211156200082357600080fd5b50620008328582860162000740565b8252506020830151600281106200084857600080fd5b60208201526200085b60408401620006e7565b60408201525092915050565b6000602082840312156200087a57600080fd5b604051602081016001600160401b03811182821017156200089f576200089f62000704565b6040529151825250919050565b600080600080600080600080610100898b031215620008ca57600080fd5b620008d589620006e7565b9750620008e560208a01620006e7565b9650620008f560408a01620006e7565b95506200090560608a01620006e7565b60808a01519095506001600160401b03808211156200092357600080fd5b620009318c838d0162000740565b955060a08b01519150808211156200094857600080fd5b620009568c838d0162000740565b945060c08b01519150808211156200096d57600080fd5b506200097c8b828c01620007d1565b9250506200098e8a60e08b0162000867565b90509295985092959890939650565b60008151808452620009b78160208601602086016200071a565b601f01601f19169290920160200192915050565b602081526000620009e060208301846200099d565b9392505050565b600060208284031215620009fa57600080fd5b620009e082620006e7565b600060018060a01b038089168352808816602084015260c0604084015262000a3160c08401886200099d565b838103606085015262000a4581886200099d565b60ff969096166080850152509290921660a09091015250949350505050565b6000825162000a788184602087016200071a565b9190910192915050565b634e487b7160e01b600052602160045260246000fd5b602081016004831062000aaf5762000aaf62000a82565b91905290565b60208152600082516060602084015262000ad360808401826200099d565b905060208401516002811062000aed5762000aed62000a82565b60408481019190915293909301516001600160a01b03166060909201919091525090565b61067c8062000b216000396000f3fe6080604052600436106100295760003560e01c80632d5f1187146100e157806392dd9d651461012c575b60006100537fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf75490565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610090573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100b49190610605565b90503660008037600080366000846127105a03f43d806000803e8180156100da57816000f35b816000fd5b005b3480156100ed57600080fd5b507fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7546040516001600160a01b03909116815260200160405180910390f35b34801561013857600080fd5b506100df610147366004610629565b7fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7546001600160a01b0316336001600160a01b0316146101f45760405162461bcd60e51b815260206004820152602d60248201527f6f6e6c792063757272656e7420696d706c656d656e746174696f6e417574686f60448201527f726974792063616e2063616c6c0000000000000000000000000000000000000060648201526084015b60405180910390fd5b6001600160a01b03811661024a5760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f20616464726573730060448201526064016101eb565b60006001600160a01b0316816001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b79190610605565b6001600160a01b031614158015610342575060006001600160a01b0316816001600160a01b0316636ff6e83f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610312573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103369190610605565b6001600160a01b031614155b80156103c2575060006001600160a01b0316816001600160a01b0316631ee9ce8b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b69190610605565b6001600160a01b031614155b8015610442575060006001600160a01b0316816001600160a01b0316639e3e7bb96040518163ffffffff1660e01b8152600401602060405180830381865afa158015610412573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104369190610605565b6001600160a01b031614155b80156104c2575060006001600160a01b0316816001600160a01b03166361f898256040518163ffffffff1660e01b8152600401602060405180830381865afa158015610492573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b69190610605565b6001600160a01b031614155b8015610542575060006001600160a01b0316816001600160a01b031663fedcc0526040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190610605565b6001600160a01b031614155b61058e5760405162461bcd60e51b815260206004820181905260248201527f696e76616c696420496d706c656d656e746174696f6e20417574686f7269747960448201526064016101eb565b6105b6817fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf755565b6040516001600160a01b038216907f3b1074392ed8e8424715d0dda2197eede67080b377fc8370e26f3e882207f6b890600090a250565b6001600160a01b038116811461060257600080fd5b50565b60006020828403121561061757600080fd5b8151610622816105ed565b9392505050565b60006020828403121561063b57600080fd5b8135610622816105ed56fea2646970667358221220e2b3607324991b75ea05434eed06ce75e7e2545c439a3e7eaba40e7d7c281cf564736f6c63430008110033c5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf760806040523480156200001157600080fd5b506040516200168538038062001685833981016040819052620000349162000ad9565b8686868560e0015186610100015160068960006001600160a01b0316876001600160a01b0316141580156200007157506001600160a01b03861615155b80156200008657506001600160a01b03851615155b620000d85760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f20616464726573730060448201526064015b60405180910390fd5b604051602001620000f490602080825260009082015260400190565b60405160208183030381529060405280519060200120846040516020016200011d919062000cad565b60405160208183030381529060405280519060200120141580156200019b57506040516020016200015990602080825260009082015260400190565b604051602081830303815290604052805190602001208360405160200162000182919062000cad565b6040516020818303038152906040528051906020012014155b620001e95760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d20656d70747920737472696e67006044820152606401620000cf565b60128260ff1611156200023f5760405162461bcd60e51b815260206004820152601960248201527f646563696d616c73206265747765656e203020616e64203138000000000000006044820152606401620000cf565b62000257876000805160206200166583398151915255565b6040516001600160a01b038816907f3b1074392ed8e8424715d0dda2197eede67080b377fc8370e26f3e882207f6b890600090a26000620002a5600080516020620016658339815191525490565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000309919062000cc9565b90506000816001600160a01b0316888888888888604051602401620003349695949392919062000ce7565b60408051601f198184030181529181526020820180516001600160e01b0316633e46d86760e21b179052516200036b919062000d46565b600060405180830381855af49150503d8060008114620003a8576040519150601f19603f3d011682016040523d82523d6000602084013e620003ad565b606091505b5050905080620004005760405162461bcd60e51b815260206004820152601660248201527f496e697469616c697a6174696f6e206661696c65642e000000000000000000006044820152606401620000cf565b50505050505050505060006200041b620007c460201b60201c565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000459573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200047f919062000cc9565b90506000816001600160a01b0316637de4fba960e01b6003604051602401620004a9919062000d90565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620004e9919062000d46565b600060405180830381855af49150503d806000811462000526576040519150601f19603f3d011682016040523d82523d6000602084013e6200052b565b606091505b50509050806200054e5760405163c0602fd160e01b815260040160405180910390fd5b6000826001600160a01b0316630b9fff7460e01b8760405160240162000575919062000dcf565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620005b5919062000d46565b600060405180830381855af49150503d8060008114620005f2576040519150601f19603f3d011682016040523d82523d6000602084013e620005f7565b606091505b50509050806200061a576040516303aa38ab60e01b815260040160405180910390fd5b6000836001600160a01b031663a1e4b78660e01b8760405160240162000641919062000e8d565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905162000681919062000d46565b600060405180830381855af49150503d8060008114620006be576040519150601f19603f3d011682016040523d82523d6000602084013e620006c3565b606091505b5050905080620006e6576040516341de8ffd60e01b815260040160405180910390fd5b6000846001600160a01b03166344ed4f8960e01b876040516024016200070d919062000f54565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516200074d919062000d46565b600060405180830381855af49150503d80600081146200078a576040519150601f19603f3d011682016040523d82523d6000602084013e6200078f565b606091505b5050905080620007b257604051638274ff7760e01b815260040160405180910390fd5b50505050505050505050505062000fd9565b600080516020620016658339815191525490565b80516001600160a01b0381168114620007f057600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b0381118282101715620008305762000830620007f5565b60405290565b60405161012081016001600160401b0381118282101715620008305762000830620007f5565b805160028110620007f057600080fd5b805160078110620007f057600080fd5b60005b83811015620008995781810151838201526020016200087f565b50506000910152565b600082601f830112620008b457600080fd5b81516001600160401b0380821115620008d157620008d1620007f5565b604051601f8301601f19908116603f01168101908282118183101715620008fc57620008fc620007f5565b816040528381528660208588010111156200091657600080fd5b620009298460208301602089016200087c565b9695505050505050565b805160048110620007f057600080fd5b600060e082840312156200095657600080fd5b620009606200080b565b905081518152620009746020830162000933565b602082015260408201516001600160401b03808211156200099457600080fd5b620009a285838601620008a2565b60408401526060840151915080821115620009bc57600080fd5b620009ca85838601620008a2565b60608401526080840151915080821115620009e457600080fd5b620009f285838601620008a2565b608084015260a084015191508082111562000a0c57600080fd5b62000a1a85838601620008a2565b60a084015260c084015191508082111562000a3457600080fd5b5062000a4384828501620008a2565b60c08301525092915050565b600060e0828403121562000a6257600080fd5b62000a6c6200080b565b9050815181526020820151602082015260408201516005811062000a8f57600080fd5b6040820152606082810151908201526080820151600b811062000ab157600080fd5b608082015260a0828101519082015262000ace60c08301620007d8565b60c082015292915050565b60008060008060008060006101a0888a03121562000af657600080fd5b62000b0188620007d8565b965062000b1160208901620007d8565b955062000b2160408901620007d8565b945062000b3160608901620007d8565b60808901519094506001600160401b038082111562000b4f57600080fd5b90890190610120828c03121562000b6557600080fd5b62000b6f62000836565b825181526020830151602082015262000b8b604084016200085c565b604082015262000b9e606084016200086c565b606082015262000bb1608084016200085c565b608082015260a08301518281111562000bc957600080fd5b62000bd78d828601620008a2565b60a08301525060c083015160c082015260e08301518281111562000bfa57600080fd5b62000c088d828601620008a2565b60e083015250610100808401518381111562000c2357600080fd5b62000c318e828701620008a2565b8284015250508095505060a08a015191508082111562000c5057600080fd5b5062000c5f8a828b0162000943565b92505062000c718960c08a0162000a4f565b905092959891949750929550565b6000815180845262000c998160208601602086016200087c565b601f01601f19169290920160200192915050565b60208152600062000cc2602083018462000c7f565b9392505050565b60006020828403121562000cdc57600080fd5b62000cc282620007d8565b600060018060a01b038089168352808816602084015260c0604084015262000d1360c084018862000c7f565b838103606085015262000d27818862000c7f565b60ff969096166080850152509290921660a09091015250949350505050565b6000825162000d5a8184602087016200087c565b9190910192915050565b634e487b7160e01b600052602160045260246000fd5b6004811062000d8d5762000d8d62000d64565b50565b6020810162000d9f8362000d7a565b91905290565b6002811062000db85762000db862000d64565b9052565b6007811062000db85762000db862000d64565b6020815281516020820152602082015160408201526000604083015162000dfa606084018262000da5565b50606083015162000e0f608084018262000dbc565b50608083015162000e2460a084018262000da5565b5060a08301516101208060c085015262000e4361014085018362000c7f565b915060c085015160e085015260e0850151601f1961010081878603018188015262000e6f858462000c7f565b90880151878203909201848801529350905062000929838262000c7f565b60208152815160208201526000602083015162000eaa8162000d7a565b80604084015250604083015160e0606084015262000ecd61010084018262000c7f565b90506060840151601f198085840301608086015262000eed838362000c7f565b925060808601519150808584030160a086015262000f0c838362000c7f565b925060a08601519150808584030160c086015262000f2b838362000c7f565b925060c08601519150808584030160e08601525062000f4b828262000c7f565b95945050505050565b8151815260208083015190820152604082015160e08201906005811062000f7f5762000f7f62000d64565b6040830152606083810151908301526080830151600b811062000fa65762000fa662000d64565b8060808401525060a083015160a083015260c083015162000fd260c08401826001600160a01b03169052565b5092915050565b61067c8062000fe96000396000f3fe6080604052600436106100295760003560e01c80632d5f1187146100e157806392dd9d651461012c575b60006100537fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf75490565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610090573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100b49190610605565b90503660008037600080366000846127105a03f43d806000803e8180156100da57816000f35b816000fd5b005b3480156100ed57600080fd5b507fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7546040516001600160a01b03909116815260200160405180910390f35b34801561013857600080fd5b506100df610147366004610629565b7fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7546001600160a01b0316336001600160a01b0316146101f45760405162461bcd60e51b815260206004820152602d60248201527f6f6e6c792063757272656e7420696d706c656d656e746174696f6e417574686f60448201527f726974792063616e2063616c6c0000000000000000000000000000000000000060648201526084015b60405180910390fd5b6001600160a01b03811661024a5760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f20616464726573730060448201526064016101eb565b60006001600160a01b0316816001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b79190610605565b6001600160a01b031614158015610342575060006001600160a01b0316816001600160a01b0316636ff6e83f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610312573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103369190610605565b6001600160a01b031614155b80156103c2575060006001600160a01b0316816001600160a01b0316631ee9ce8b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b69190610605565b6001600160a01b031614155b8015610442575060006001600160a01b0316816001600160a01b0316639e3e7bb96040518163ffffffff1660e01b8152600401602060405180830381865afa158015610412573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104369190610605565b6001600160a01b031614155b80156104c2575060006001600160a01b0316816001600160a01b03166361f898256040518163ffffffff1660e01b8152600401602060405180830381865afa158015610492573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b69190610605565b6001600160a01b031614155b8015610542575060006001600160a01b0316816001600160a01b031663fedcc0526040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190610605565b6001600160a01b031614155b61058e5760405162461bcd60e51b815260206004820181905260248201527f696e76616c696420496d706c656d656e746174696f6e20417574686f7269747960448201526064016101eb565b6105b6817fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf755565b6040516001600160a01b038216907f3b1074392ed8e8424715d0dda2197eede67080b377fc8370e26f3e882207f6b890600090a250565b6001600160a01b038116811461060257600080fd5b50565b60006020828403121561061757600080fd5b8151610622816105ed565b9392505050565b60006020828403121561063b57600080fd5b8135610622816105ed56fea264697066735822122022a9c01e849f34319575950c89541bbfb0e2abafb7d994e66d7b0ffc5adbfff464736f6c63430008110033c5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf760806040523480156200001157600080fd5b50604051620010bf380380620010bf83398101604081905262000034916200073f565b86868685856006896001600160a01b038716158015906200005d57506001600160a01b03861615155b80156200007257506001600160a01b03851615155b620000c45760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f20616464726573730060448201526064015b60405180910390fd5b604051602001620000e090602080825260009082015260400190565b6040516020818303038152906040528051906020012084604051602001620001099190620008cc565b60405160208183030381529060405280519060200120141580156200018757506040516020016200014590602080825260009082015260400190565b60405160208183030381529060405280519060200120836040516020016200016e9190620008cc565b6040516020818303038152906040528051906020012014155b620001d55760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d20656d70747920737472696e67006044820152606401620000bb565b60128260ff1611156200022b5760405162461bcd60e51b815260206004820152601960248201527f646563696d616c73206265747765656e203020616e64203138000000000000006044820152606401620000bb565b62000243876000805160206200109f83398151915255565b6040516001600160a01b038816907f3b1074392ed8e8424715d0dda2197eede67080b377fc8370e26f3e882207f6b890600090a26000620002916000805160206200109f8339815191525490565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002cf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f59190620008e8565b90506000816001600160a01b0316888888888888604051602401620003209695949392919062000906565b60408051601f198184030181529181526020820180516001600160e01b0316633e46d86760e21b1790525162000357919062000965565b600060405180830381855af49150503d806000811462000394576040519150601f19603f3d011682016040523d82523d6000602084013e62000399565b606091505b5050905080620003ec5760405162461bcd60e51b815260206004820152601660248201527f496e697469616c697a6174696f6e206661696c65642e000000000000000000006044820152606401620000bb565b5050505050505050506000620004076200061660201b60201c565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000445573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200046b9190620008e8565b90506000816001600160a01b0316637de4fba960e01b600160405160240162000495919062000983565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620004d5919062000965565b600060405180830381855af49150503d806000811462000512576040519150601f19603f3d011682016040523d82523d6000602084013e62000517565b606091505b50509050806200053a57604051631d815ba160e31b815260040160405180910390fd5b6000826001600160a01b031663d18c2cec60e01b85604051602401620005619190620009ac565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620005a1919062000965565b600060405180830381855af49150503d8060008114620005de576040519150601f19603f3d011682016040523d82523d6000602084013e620005e3565b606091505b505090508062000606576040516304b1dbbb60e41b815260040160405180910390fd5b5050505050505050505062000a13565b6000805160206200109f8339815191525490565b80516001600160a01b03811681146200064257600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171562000682576200068262000647565b60405290565b60005b83811015620006a55781810151838201526020016200068b565b50506000910152565b600082601f830112620006c057600080fd5b81516001600160401b0380821115620006dd57620006dd62000647565b604051601f8301601f19908116603f0116810190828211818310171562000708576200070862000647565b816040528381528660208588010111156200072257600080fd5b6200073584602083016020890162000688565b9695505050505050565b600080600080600080600060e0888a0312156200075b57600080fd5b62000766886200062a565b965062000776602089016200062a565b955062000786604089016200062a565b945062000796606089016200062a565b60808901519094506001600160401b0380821115620007b457600080fd5b620007c28b838c01620006ae565b945060a08a0151915080821115620007d957600080fd5b620007e78b838c01620006ae565b935060c08a0151915080821115620007fe57600080fd5b908901906060828c0312156200081357600080fd5b6200081d6200065d565b8251828111156200082d57600080fd5b6200083b8d828601620006ae565b8252506020830151828111156200085157600080fd5b6200085f8d828601620006ae565b6020830152506040830151828111156200087857600080fd5b620008868d828601620006ae565b60408301525080935050505092959891949750929550565b60008151808452620008b881602086016020860162000688565b601f01601f19169290920160200192915050565b602081526000620008e160208301846200089e565b9392505050565b600060208284031215620008fb57600080fd5b620008e1826200062a565b600060018060a01b038089168352808816602084015260c060408401526200093260c08401886200089e565b83810360608501526200094681886200089e565b60ff969096166080850152509290921660a09091015250949350505050565b600082516200097981846020870162000688565b9190910192915050565b6020810160048310620009a657634e487b7160e01b600052602160045260246000fd5b91905290565b602081526000825160606020840152620009ca60808401826200089e565b90506020840151601f1980858403016040860152620009ea83836200089e565b925060408601519150808584030160608601525062000a0a82826200089e565b95945050505050565b61067c8062000a236000396000f3fe6080604052600436106100295760003560e01c80632d5f1187146100e157806392dd9d651461012c575b60006100537fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf75490565b6001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610090573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100b49190610605565b90503660008037600080366000846127105a03f43d806000803e8180156100da57816000f35b816000fd5b005b3480156100ed57600080fd5b507fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7546040516001600160a01b03909116815260200160405180910390f35b34801561013857600080fd5b506100df610147366004610629565b7fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7546001600160a01b0316336001600160a01b0316146101f45760405162461bcd60e51b815260206004820152602d60248201527f6f6e6c792063757272656e7420696d706c656d656e746174696f6e417574686f60448201527f726974792063616e2063616c6c0000000000000000000000000000000000000060648201526084015b60405180910390fd5b6001600160a01b03811661024a5760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f20616464726573730060448201526064016101eb565b60006001600160a01b0316816001600160a01b031663709bc7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b79190610605565b6001600160a01b031614158015610342575060006001600160a01b0316816001600160a01b0316636ff6e83f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610312573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103369190610605565b6001600160a01b031614155b80156103c2575060006001600160a01b0316816001600160a01b0316631ee9ce8b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b69190610605565b6001600160a01b031614155b8015610442575060006001600160a01b0316816001600160a01b0316639e3e7bb96040518163ffffffff1660e01b8152600401602060405180830381865afa158015610412573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104369190610605565b6001600160a01b031614155b80156104c2575060006001600160a01b0316816001600160a01b03166361f898256040518163ffffffff1660e01b8152600401602060405180830381865afa158015610492573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b69190610605565b6001600160a01b031614155b8015610542575060006001600160a01b0316816001600160a01b031663fedcc0526040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190610605565b6001600160a01b031614155b61058e5760405162461bcd60e51b815260206004820181905260248201527f696e76616c696420496d706c656d656e746174696f6e20417574686f7269747960448201526064016101eb565b6105b6817fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf755565b6040516001600160a01b038216907f3b1074392ed8e8424715d0dda2197eede67080b377fc8370e26f3e882207f6b890600090a250565b6001600160a01b038116811461060257600080fd5b50565b60006020828403121561061757600080fd5b8151610622816105ed565b9392505050565b60006020828403121561063b57600080fd5b8135610622816105ed56fea26469706673582212203016a425840f79186f918e1c7a57764b1f07d0d62c2379ff3388882ee26cbaed64736f6c63430008110033c5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7a2646970667358221220d989ba8e5d265a20f0554796c890394e63c76efcb104890ef318ee4f2017317d64736f6c63430008110033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.