Overview
ETH Balance
ETH Value
$0.00Latest 25 from a total of 39 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Remove User | 308092583 | 288 days ago | IN | 0 ETH | 0.00000348 | ||||
| Add User | 292971101 | 332 days ago | IN | 0 ETH | 0.00015535 | ||||
| Register Identit... | 292971067 | 332 days ago | IN | 0 ETH | 0.00017825 | ||||
| Add User | 267975968 | 405 days ago | IN | 0 ETH | 0.00000514 | ||||
| Register Identit... | 267975953 | 405 days ago | IN | 0 ETH | 0.00000538 | ||||
| Add User | 267975938 | 405 days ago | IN | 0 ETH | 0.00000514 | ||||
| Register Identit... | 267975923 | 405 days ago | IN | 0 ETH | 0.00000538 | ||||
| Add User | 267975573 | 405 days ago | IN | 0 ETH | 0.00000513 | ||||
| Register Identit... | 267975557 | 405 days ago | IN | 0 ETH | 0.00000538 | ||||
| Add User | 254924342 | 443 days ago | IN | 0 ETH | 0.00000719 | ||||
| Register Identit... | 254924307 | 443 days ago | IN | 0 ETH | 0.00000651 | ||||
| Add User | 254793049 | 443 days ago | IN | 0 ETH | 0.00000528 | ||||
| Register Identit... | 254793036 | 443 days ago | IN | 0 ETH | 0.00000545 | ||||
| Add User | 254793023 | 443 days ago | IN | 0 ETH | 0.00000528 | ||||
| Register Identit... | 254793010 | 443 days ago | IN | 0 ETH | 0.00000545 | ||||
| Add User | 254792997 | 443 days ago | IN | 0 ETH | 0.0000053 | ||||
| Register Identit... | 254792983 | 443 days ago | IN | 0 ETH | 0.00000545 | ||||
| Add User | 254792238 | 443 days ago | IN | 0 ETH | 0.00000529 | ||||
| Register Identit... | 254792224 | 443 days ago | IN | 0 ETH | 0.00000545 | ||||
| Add User | 254792211 | 443 days ago | IN | 0 ETH | 0.00000529 | ||||
| Register Identit... | 254792198 | 443 days ago | IN | 0 ETH | 0.00000545 | ||||
| Add User | 254792185 | 443 days ago | IN | 0 ETH | 0.00000529 | ||||
| Register Identit... | 254792172 | 443 days ago | IN | 0 ETH | 0.00000545 | ||||
| Add User | 254792159 | 443 days ago | IN | 0 ETH | 0.00000528 | ||||
| Register Identit... | 254792146 | 443 days ago | IN | 0 ETH | 0.00000545 |
Latest 17 internal transactions
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 292971067 | 332 days ago | Contract Creation | 0 ETH | |||
| 267975953 | 405 days ago | Contract Creation | 0 ETH | |||
| 267975923 | 405 days ago | Contract Creation | 0 ETH | |||
| 267975557 | 405 days ago | Contract Creation | 0 ETH | |||
| 254924307 | 443 days ago | Contract Creation | 0 ETH | |||
| 254793036 | 443 days ago | Contract Creation | 0 ETH | |||
| 254793010 | 443 days ago | Contract Creation | 0 ETH | |||
| 254792983 | 443 days ago | Contract Creation | 0 ETH | |||
| 254792224 | 443 days ago | Contract Creation | 0 ETH | |||
| 254792198 | 443 days ago | Contract Creation | 0 ETH | |||
| 254792172 | 443 days ago | Contract Creation | 0 ETH | |||
| 254792146 | 443 days ago | Contract Creation | 0 ETH | |||
| 254792117 | 443 days ago | Contract Creation | 0 ETH | |||
| 254792065 | 443 days ago | Contract Creation | 0 ETH | |||
| 254791890 | 443 days ago | Contract Creation | 0 ETH | |||
| 254532071 | 444 days ago | Contract Creation | 0 ETH | |||
| 254532003 | 444 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
/**
* Copyright © 2023 DEFYCA Labs 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 DEFYCA LABS
* S.à.r.l 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 { IdentityProxy } from "@onchain-id/solidity/contracts/proxy/IdentityProxy.sol";
import { IIdentity } from "@onchain-id/solidity/contracts/interface/IIdentity.sol";
import { IIdentityRegistry } from "@ERC-3643/registry/interface/IIdentityRegistry.sol";
import { AgentRoleUpgradeable } from "@ERC-3643/roles/AgentRoleUpgradeable.sol";
import { IFrictionlessPermissionsManager } from "@interface/IFrictionlessPermissionsManager.sol";
/**
* @title FrictionlessPermissionsManager - Smart contract to manage the permission of participants in the Frictionless protocol
* @author DEFYCA Labs S.à.r.l
* @notice See {IFrictionlessPermissionsManager}
*/
contract FrictionlessPermissionsManager is IFrictionlessPermissionsManager, AgentRoleUpgradeable {
/// @dev the address of the deployed TREX Implementation Authority
address private _implAuthority;
/// @dev the address of the deployed TREX Identity Registry
address private _identityRegistry;
/// @dev the address of the deployed TREX Claim Issuer
address private _claimIssuer;
/**
* @dev The storage of claimData for the market participants in the order of the `FrictionlessPermissionedUser` enum
*/
bytes[] private _claimData;
/// @dev the relevant claim topic for the Frictionless protocol
uint256 private _claimTopic;
/**
* @dev initialize the FrictionlessPermissionsManager
* @param implAuthority_ the address of the deployed TREX Implementation Authority
* @param identityRegistry_ the address of the deployed TREX Identity Registry
* @param claimIssuer_ the address of the deployed TREX Claim Issuer
* @param claimTopic_ the relevant claim topic for the Frictionless protocol
* requires implAuthority_ to be valid contract address
* requires identityRegistry_ to be valid contract address
* requires claimIssuer_ to be valid contract address
*/
function init(
address implAuthority_,
address identityRegistry_,
address claimIssuer_,
uint256 claimTopic_
) external initializer {
if (implAuthority_ == address(0)) revert FrictionlessIsZeroAddress("ImplAuthority");
if (identityRegistry_ == address(0)) revert FrictionlessIsZeroAddress("IdentityRegistry");
if (claimIssuer_ == address(0)) revert FrictionlessIsZeroAddress("ClaimIssuer");
_implAuthority = implAuthority_;
_identityRegistry = identityRegistry_;
_claimIssuer = claimIssuer_;
_claimTopic = claimTopic_;
_claimData.push(abi.encodePacked("Frictionless Markets Treasury."));
_claimData.push(abi.encodePacked("Frictionless Markets Qualified Custodian."));
_claimData.push(abi.encodePacked("Frictionless Markets Permissioned Investor."));
_claimData.push(abi.encodePacked("Frictionless Markets Permissioned Manager."));
_claimData.push(abi.encodePacked("Frictionless Markets Permissioned Calculating Agent."));
_claimData.push(abi.encodePacked("Frictionless Markets Permissioned Transfer Agent."));
_claimData.push(abi.encodePacked("Frictionless Markets Permissioned Fund Accountant."));
__Ownable_init();
}
/// @inheritdoc IFrictionlessPermissionsManager
function registerIdentity(
address userAddress_,
uint16 userISOCountry_
) public override onlyAgent returns (address) {
IdentityProxy identityProxy = new IdentityProxy(address(_implAuthority), address(this));
address identity = address(identityProxy);
IIdentity(identity).addKey(keccak256(abi.encodePacked(address(this))), 1, 3);
IIdentityRegistry(_identityRegistry).registerIdentity(userAddress_, IIdentity(identity), userISOCountry_);
emit FrictionlessPermissionedUserRegistered(userAddress_, userISOCountry_);
return identity;
}
/// @inheritdoc IFrictionlessPermissionsManager
function getIdentity(address userAddress_) public override onlyAgent returns (address) {
return address(IIdentityRegistry(_identityRegistry).identity(userAddress_));
}
/// @inheritdoc IFrictionlessPermissionsManager
function addUser(
address userIdentity_,
IFrictionlessPermissionsManager.FrictionlessPermissionedUser userType_,
bytes memory signature_,
string memory claimURI_
) public override onlyAgent returns (address) {
// only owner can add treasury
if (
userType_ == IFrictionlessPermissionsManager.FrictionlessPermissionedUser.PROTOCOL_TREASURY &&
owner() != msg.sender
) revert FrictionlessInvalidPermissionForTreasury();
Claim memory claimForUser = Claim({
data: _claimData[uint(userType_)],
issuer: _claimIssuer,
topic: _claimTopic,
scheme: 1,
identity: userIdentity_,
signature: signature_
});
IIdentity(userIdentity_).addClaim(
claimForUser.topic,
claimForUser.scheme,
claimForUser.issuer,
claimForUser.signature,
claimForUser.data,
claimURI_
);
emit FrictionlessPermissionedUserAdded(userIdentity_, uint(userType_), claimURI_);
return address(userIdentity_);
}
/// @inheritdoc IFrictionlessPermissionsManager
function removeUser(address userAddress_) public override onlyAgent returns (bool) {
// only owner can remove treasury
if (
hasClaim(userAddress_, IFrictionlessPermissionsManager.FrictionlessPermissionedUser.PROTOCOL_TREASURY) &&
owner() != msg.sender
) revert FrictionlessInvalidPermissionForTreasury();
if (!isPermissioned(userAddress_)) {
revert FrictionlessUserIsNotPermssionedInvestor();
}
_removePermission(userAddress_, _claimTopic);
emit FrictionlessPermissionedUserRemoved(userAddress_);
return true;
}
/// @inheritdoc IFrictionlessPermissionsManager
function getClaimMsgHash(
address userIdentity_,
IFrictionlessPermissionsManager.FrictionlessPermissionedUser userType_
) public view override returns (bytes32) {
bytes32 claimMsgHash = keccak256(
abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
keccak256(abi.encode(userIdentity_, _claimTopic, _claimData[uint(userType_)]))
)
);
return claimMsgHash;
}
/// @inheritdoc IFrictionlessPermissionsManager
function isPermissioned(address userAddress_) public view override returns (bool) {
return IIdentityRegistry(_identityRegistry).isVerified(userAddress_);
}
/// @inheritdoc IFrictionlessPermissionsManager
function hasClaim(
address userAddress_,
IFrictionlessPermissionsManager.FrictionlessPermissionedUser userType_
) public view override returns (bool) {
if (!isPermissioned(userAddress_)) return false;
IIdentity identity = IIdentityRegistry(_identityRegistry).identity(userAddress_);
bytes32 claimId = keccak256(abi.encode(_claimIssuer, _claimTopic));
(, , , , bytes memory data, ) = IIdentity(identity).getClaim(claimId);
return keccak256(abi.encodePacked(_claimData[uint(userType_)])) == keccak256(data);
}
/**
* @dev Removes the permissioned user from the IdentityRegistry and any associated claims
* @param userAddress_ the user wallet address to remove
* @param claimTopic_ the topic to remove user claims from
*/
function _removePermission(address userAddress_, uint256 claimTopic_) internal {
bytes32 claimId = keccak256(abi.encode(_claimIssuer, claimTopic_));
IIdentity userIdentity_ = IIdentityRegistry(_identityRegistry).identity(userAddress_);
userIdentity_.removeClaim(claimId);
IIdentityRegistry(_identityRegistry).deleteIdentity(userAddress_);
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
import "../interface/IImplementationAuthority.sol";
contract IdentityProxy {
/**
* @dev constructor of the proxy Identity contract
* @param _implementationAuthority the implementation Authority contract address
* @param initialManagementKey the management key at deployment
* the proxy is going to use the logic deployed on the implementation contract
* deployed at an address listed in the ImplementationAuthority contract
*/
constructor(address _implementationAuthority, address initialManagementKey) {
require(_implementationAuthority != address(0), "invalid argument - zero address");
require(initialManagementKey != address(0), "invalid argument - zero address");
// solhint-disable-next-line no-inline-assembly
assembly {
sstore(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7, _implementationAuthority)
}
address logic = IImplementationAuthority(_implementationAuthority).getImplementation();
// solhint-disable-next-line avoid-low-level-calls
(bool success,) = logic.delegatecall(abi.encodeWithSignature("initialize(address)", initialManagementKey));
require(success, "Initialization failed.");
}
/**
* @dev fallback proxy function used for any transaction call that is made using
* the Identity contract ABI and called on the proxy contract
* The proxy will update its local storage depending on the behaviour requested
* by the implementation contract given by the Implementation Authority
*/
// solhint-disable-next-line no-complex-fallback
fallback() external payable {
address logic = IImplementationAuthority(implementationAuthority()).getImplementation();
// 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)
}
}
}
function implementationAuthority() public view returns(address) {
address implemAuth;
// solhint-disable-next-line no-inline-assembly
assembly {
implemAuth := sload(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7)
}
return implemAuth;
}
}// 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
//
// :+#####%%%%%%%%%%%%%%+
// .-*@@@%+.:+%@@@@@%%#***%@@%=
// :=*%@@@#=. :#@@% *@@@%=
// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%-
// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#.
// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+
// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%-
// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%:
// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#.
// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*.
// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+
// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@-
// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#:
// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#-
// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%-
// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@#
// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+-
// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=:
// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+:
// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+.
// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+.
// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=.
// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=.
// @@@@@@+. +@@*. .+@@@@@%=.
// -@@@@@= =@@%: -#@@@@%+.
// +@@@@@. =@@@= .+@@@@@*:
// #@@@@#:%@@#. :*@@@@#-
// @@@@@%@@@= :#@@@@+.
// :@@@@@@@#.:#@@@%-
// +@@@@@@-.*@@@*:
// #@@@@#.=@@@+.
// @@@@+-%@%=
// :@@@#%@%=
// +@@@@%-
// :#%%=
//
/**
* 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;
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 © 2023 DEFYCA Labs 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 DEFYCA LABS
* S.à.r.l 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;
/**
* @title IFrictionlessPermissionsManager - Manages the permission of participants in the Frictionless protocol
* @author DEFYCA Labs S.à.r.l
* @notice The IFrictionlessPermissionsManager is responsible for the management of permission of the various participants in
* the Frictionless protocol. The roles and responsibilities are defined in the public README for the Frictionless protocol at
* https://gitlab.com/dfyclabs/protocol/dfyclabs-tokens/-/blob/main/README.md?ref_type=heads#roles-responsibilities
*/
interface IFrictionlessPermissionsManager {
/// @dev Enum of the Frictionless protocol participants.
enum FrictionlessPermissionedUser {
PROTOCOL_TREASURY,
PERMISSIONED_CUSTODIAN,
PERMISSIONED_INVESTOR,
PERMISSIONED_MANAGER,
PERMISSIONED_CALCULATING_AGENT,
PERMISSIONED_TRANSFER_AGENT,
PERMISSIONED_FUND_ACCOUNTANT
}
/// @dev throws if specific address is zero.
error FrictionlessIsZeroAddress(string);
/// @dev throws if treasury tries to add or remove treasury.
error FrictionlessInvalidPermissionForTreasury();
/// @dev throws if user is not a permissioned investor
error FrictionlessUserIsNotPermssionedInvestor();
/**
* @dev Emitted when a user is added to the Frictionless protocol. This event is emitted by the `addUser` function.
* @param userIdentity the address of the user's OnChainId (Identity)
* @param userType the type of the user as per the enum
* @param claimURI the URI of the off-chain claim for the user. i.e. The Frictionless Markets graphQL endpoint
*/
event FrictionlessPermissionedUserAdded(address userIdentity, uint256 userType, string claimURI);
/**
* @dev Emitted when a user is registered in the Frictionless protocol. This event is emitted by the `registerIdentity` function.
* @param userAddress the address of the user's wallet to register
* @param userISOCountry the ISO 3166-1 numeric code of the user, can be the place of residence or the location KYC/AML onboarding was undertaken.
*/
event FrictionlessPermissionedUserRegistered(address userAddress, uint16 userISOCountry);
/**
* @dev Emitted when a user is removed in the Frictionless protocol. This event is emitted by the `removeUser` function.
* @param userAddress the address of the user's wallet to register
*/
event FrictionlessPermissionedUserRemoved(address userAddress);
/// @dev the internal struct defining a Claim for a PERMISSIONED_USER in the protocol. Used to submit claims for the OnChainId by the ClaimIssuer.
struct Claim {
address issuer;
uint256 topic;
uint8 scheme;
address identity;
bytes signature;
bytes data;
}
/**
* @dev Validates if a wallet address is permissioned in the Frictionless protocol
* @param userAddress the wallet address to verify
* @return true if the address is permissioned in the Frictionless Protocol.
*/
function isPermissioned(address userAddress) external view returns (bool);
/**
* @dev Registers a users wallet address as an OnChainId (Identity) to the Frictionless protocol.
* This Identity is used when permissioning a user to the protocol by invoking the addUser function later.
* @param userAddress the address of the user's wallet to register
* @param userISOCountry the ISO 3166-1 numeric code of the user, can be the place of residence or the location KYC/AML onboarding was undertaken.
* requires The msg.sender to have the TREX Agent permissions (PROTOCOL_TREASURY or PROTOCOL_ADMIN)
* @return address the address of the user's OnChainId (Identity) with the associated claims.
*/
function registerIdentity(address userAddress, uint16 userISOCountry) external returns (address);
/**
* @dev Gets a users OnChainId (Identity) in the Frictionless protocol.
* @param userAddress the address of the user's wallet to register
* requires The msg.sender to have the TREX Agent permissions (PROTOCOL_TREASURY or PROTOCOL_ADMIN)
* @return address the address of the user's OnChainId (Identity) with the associated claims.
*/
function getIdentity(address userAddress) external returns (address);
/**
* @dev Get the signed claimData message to be used in the addUser function.
* The message must be signed using the PK of the ClaimIssuer (PROTOCOL_ADMIN)
* @param userIdentity the address of the user's OnChainId (Identity)
* @param userType the type of the user as per the enum
* @return signed claimData message to be used in the addUser unction once signed by the ClaimIssuer PK.
*/
function getClaimMsgHash(
address userIdentity,
IFrictionlessPermissionsManager.FrictionlessPermissionedUser userType
) external view returns (bytes32);
/**
* @dev verify if the userAddress is permissioned in the Frictionless protocol and has a valid claim
* @param userAddress the address of the user's wallet to verify
* @param userType the type of the user as per the enum
* @return true if a valid permissioned user and has a valid claim, otherwise false.
*/
function hasClaim(address userAddress, FrictionlessPermissionedUser userType) external view returns (bool);
/**
* @dev Adds a user's OnChainId (Identity) to the Frictionless protocol along with its associated claim data.
* The Identity is created by invoking the registerIdentity function first.
* @param userIdentity the address of the user's OnChainId (Identity)
* @param userType the type of the user as per the enum
* @param claimSignature the signed claimData by the ClaimIssuer
* @param claimURI the URI of the off-chain claim for the user. i.e. The Frictionless Markets graphQL endpoint
* requires The msg.sender to be the Owner if the userType is the PROTOCOL_TREASURY
* requires The msg.sender to have the TREX Agent permissions (PROTOCOL_TREASURY or PROTOCOL_ADMIN) to add any user
* @return address the address of the user's OnChainId (Identity) with the associated claims.
*/
function addUser(
address userIdentity,
FrictionlessPermissionedUser userType,
bytes memory claimSignature,
string memory claimURI
) external returns (address);
/**
* @dev Removes a user from the Frictionless protocol along with its associated claim data.
* @param userAddress the address of the user's wallet
* requires The msg.sender to have the TREX Agent permissions (PROTOCOL_TREASURY or PROTOCOL_ADMIN) to remove any user
* @return true if the user is removed from the Frictionless protocol along with its associated claim data, otherwise false.
*/
function removeUser(address userAddress) external returns (bool);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
interface IImplementationAuthority {
// event emitted when the implementation contract is updated
event UpdatedImplementation(address newAddress);
/**
* @dev updates the address used as implementation by the proxies linked
* to this ImplementationAuthority contract
* @param _newImplementation the address of the new implementation contract
* only Owner can call
*/
function updateImplementation(address _newImplementation) external;
/**
* @dev returns the address of the implementation
*/
function getImplementation() external view returns(address);
}// 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);
}// 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: 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;
/**
* @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: 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: 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);
}
}
}{
"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/",
"@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",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"FrictionlessInvalidPermissionForTreasury","type":"error"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"FrictionlessIsZeroAddress","type":"error"},{"inputs":[],"name":"FrictionlessUserIsNotPermssionedInvestor","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_agent","type":"address"}],"name":"AgentAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_agent","type":"address"}],"name":"AgentRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userIdentity","type":"address"},{"indexed":false,"internalType":"uint256","name":"userType","type":"uint256"},{"indexed":false,"internalType":"string","name":"claimURI","type":"string"}],"name":"FrictionlessPermissionedUserAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"uint16","name":"userISOCountry","type":"uint16"}],"name":"FrictionlessPermissionedUserRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"}],"name":"FrictionlessPermissionedUserRemoved","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":"_agent","type":"address"}],"name":"addAgent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userIdentity_","type":"address"},{"internalType":"enum IFrictionlessPermissionsManager.FrictionlessPermissionedUser","name":"userType_","type":"uint8"},{"internalType":"bytes","name":"signature_","type":"bytes"},{"internalType":"string","name":"claimURI_","type":"string"}],"name":"addUser","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userIdentity_","type":"address"},{"internalType":"enum IFrictionlessPermissionsManager.FrictionlessPermissionedUser","name":"userType_","type":"uint8"}],"name":"getClaimMsgHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress_","type":"address"}],"name":"getIdentity","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress_","type":"address"},{"internalType":"enum IFrictionlessPermissionsManager.FrictionlessPermissionedUser","name":"userType_","type":"uint8"}],"name":"hasClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"implAuthority_","type":"address"},{"internalType":"address","name":"identityRegistry_","type":"address"},{"internalType":"address","name":"claimIssuer_","type":"address"},{"internalType":"uint256","name":"claimTopic_","type":"uint256"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_agent","type":"address"}],"name":"isAgent","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress_","type":"address"}],"name":"isPermissioned","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress_","type":"address"},{"internalType":"uint16","name":"userISOCountry_","type":"uint16"}],"name":"registerIdentity","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_agent","type":"address"}],"name":"removeAgent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress_","type":"address"}],"name":"removeUser","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50612765806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620000fd5760003560e01c80638da5cb5b116200009757806398575188116200006e578063985751881462000206578063bf68c953146200021d578063c5a80fa71462000243578063f2fde38b146200025a57600080fd5b80638da5cb5b14620001c657806393c81dd614620001d857806397a6278e14620001ef57600080fd5b80636ea3622e11620000d85780636ea3622e1462000177578063715018a6146200018e57806378d77ecb146200019857806384e7984214620001af57600080fd5b80631ffbb06414620001025780632fea7b81146200012e57806346639dba146200015e575b600080fd5b620001196200011336600462001ad3565b62000271565b60405190151581526020015b60405180910390f35b620001456200013f36600462001ad3565b62000286565b6040516001600160a01b03909116815260200162000125565b620001756200016f36600462001afa565b62000372565b005b620001456200018836600462001c1a565b620009cf565b6200017562000cb1565b62000119620001a936600462001ad3565b62000cc9565b62000175620001c036600462001ad3565b62000d54565b6033546001600160a01b031662000145565b62000119620001e936600462001cd9565b62000dfa565b620001756200020036600462001ad3565b62000fc8565b620001196200021736600462001ad3565b6200106e565b620002346200022e36600462001cd9565b620011c8565b60405190815260200162000125565b620001456200025436600462001d13565b62001280565b620001756200026b36600462001ad3565b620014f4565b6000620002806065836200158a565b92915050565b6000620002933362000271565b620002fc5760405162461bcd60e51b815260206004820152602e60248201527f4167656e74526f6c653a2063616c6c657220646f6573206e6f7420686176652060448201526d746865204167656e7420726f6c6560901b60648201526084015b60405180910390fd5b606754604051633c3ad79560e21b81526001600160a01b0384811660048301529091169063f0eb5e5490602401602060405180830381865afa15801562000347573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000280919062001d57565b919050565b600054610100900460ff1615808015620003935750600054600160ff909116105b80620003af5750303b158015620003af575060005460ff166001145b620004235760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401620002f3565b6000805460ff19166001179055801562000447576000805461ff0019166101001790555b6001600160a01b038516620004a057604051636cbb462960e01b815260206004820152600d60248201527f496d706c417574686f72697479000000000000000000000000000000000000006044820152606401620002f3565b6001600160a01b038416620004f957604051636cbb462960e01b815260206004820152601060248201527f4964656e746974795265676973747279000000000000000000000000000000006044820152606401620002f3565b6001600160a01b0383166200055257604051636cbb462960e01b815260206004820152600b60248201527f436c61696d4973737565720000000000000000000000000000000000000000006044820152606401620002f3565b606680546001600160a01b0387811673ffffffffffffffffffffffffffffffffffffffff1992831617909255606780548784169083161790556068805492861692909116919091179055606a829055604080517f4672696374696f6e6c657373204d61726b6574732054726561737572792e000060208201528151808203601e018152603e909101909152606980546001810182556000919091527f7fb4302e8e91f9110a6554c2c0a24601252c2a42c2220ca988efcfe39991430801906200061c908262001e06565b50606960405160200162000679907f4672696374696f6e6c657373204d61726b657473205175616c6966696564204381527f7573746f6469616e2e0000000000000000000000000000000000000000000000602082015260290190565b60408051601f1981840301815291905281546001810183556000928352602090922090910190620006ab908262001e06565b50606960405160200162000708907f4672696374696f6e6c657373204d61726b657473205065726d697373696f6e6581527f6420496e766573746f722e0000000000000000000000000000000000000000006020820152602b0190565b60408051601f19818403018152919052815460018101835560009283526020909220909101906200073a908262001e06565b50606960405160200162000797907f4672696374696f6e6c657373204d61726b657473205065726d697373696f6e6581527f64204d616e616765722e000000000000000000000000000000000000000000006020820152602a0190565b60408051601f1981840301815291905281546001810183556000928352602090922090910190620007c9908262001e06565b50606960405160200162000826907f4672696374696f6e6c657373204d61726b657473205065726d697373696f6e6581527f642043616c63756c6174696e67204167656e742e000000000000000000000000602082015260340190565b60408051601f198184030181529190528154600181018355600092835260209092209091019062000858908262001e06565b506069604051602001620008b5907f4672696374696f6e6c657373204d61726b657473205065726d697373696f6e6581527f64205472616e73666572204167656e742e000000000000000000000000000000602082015260310190565b60408051601f1981840301815291905281546001810183556000928352602090922090910190620008e7908262001e06565b50606960405160200162000944907f4672696374696f6e6c657373204d61726b657473205065726d697373696f6e6581527f642046756e64204163636f756e74616e742e0000000000000000000000000000602082015260320190565b60408051601f198184030181529190528154600181018355600092835260209092209091019062000976908262001e06565b50620009816200162a565b8015620009c8576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6000620009dc3362000271565b62000a415760405162461bcd60e51b815260206004820152602e60248201527f4167656e74526f6c653a2063616c6c657220646f6573206e6f7420686176652060448201526d746865204167656e7420726f6c6560901b6064820152608401620002f3565b600084600681111562000a585762000a5862001ed3565b14801562000a8157503362000a756033546001600160a01b031690565b6001600160a01b031614155b1562000aa05760405163032cc2c160e61b815260040160405180910390fd5b6040805160c0810182526068546001600160a01b039081168252606a54602083015260019282019290925290861660608201526080810184905260009060a08101606987600681111562000af85762000af862001ed3565b8154811062000b0b5762000b0b62001ee9565b90600052602060002001805462000b229062001d77565b80601f016020809104026020016040519081016040528092919081815260200182805462000b509062001d77565b801562000ba15780601f1062000b755761010080835404028352916020019162000ba1565b820191906000526020600020905b81548152906001019060200180831162000b8357829003601f168201915b50505091909252505060208101516040808301518351608085015160a086015193517fb1a34e0d0000000000000000000000000000000000000000000000000000000081529596506001600160a01b038c169563b1a34e0d9562000c0f9590949392918b9060040162001f53565b6020604051808303816000875af115801562000c2f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000c55919062001fbd565b507fade9e42fe0bd2abdc23cc41ed4133977fd4f72f4218628c8cc9fc25e881f5e578686600681111562000c8d5762000c8d62001ed3565b8560405162000c9f9392919062001fd7565b60405180910390a15093949350505050565b62000cbb620016a1565b62000cc76000620016fd565b565b6067546040517fb9209e330000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b9209e3390602401602060405180830381865afa15801562000d2e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200028091906200200a565b62000d5e620016a1565b6001600160a01b03811662000db65760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f2061646472657373006044820152606401620002f3565b62000dc36065826200175c565b6040516001600160a01b038216907ff68e73cec97f2d70aa641fb26e87a4383686e2efacb648f2165aeb02ac562ec590600090a250565b600062000e078362000cc9565b62000e155750600062000280565b606754604051633c3ad79560e21b81526001600160a01b038581166004830152600092169063f0eb5e5490602401602060405180830381865afa15801562000e61573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000e87919062001d57565b606854606a54604080516001600160a01b03909316602084015282015290915060009060600160408051601f198184030181529082905280516020909101207fc9100bcb0000000000000000000000000000000000000000000000000000000082526004820181905291506000906001600160a01b0384169063c9100bcb90602401600060405180830381865afa15801562000f27573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000f51919081019062002087565b509450505050508080519060200120606986600681111562000f775762000f7762001ed3565b8154811062000f8a5762000f8a62001ee9565b9060005260206000200160405160200162000fa6919062002156565b6040516020818303038152906040528051906020012014935050505092915050565b62000fd2620016a1565b6001600160a01b0381166200102a5760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f2061646472657373006044820152606401620002f3565b62001037606582620017dc565b6040516001600160a01b038216907fed9c8ad8d5a0a66898ea49d2956929c93ae2e8bd50281b2ed897c5d1a6737e0b90600090a250565b60006200107b3362000271565b620010e05760405162461bcd60e51b815260206004820152602e60248201527f4167656e74526f6c653a2063616c6c657220646f6573206e6f7420686176652060448201526d746865204167656e7420726f6c6560901b6064820152608401620002f3565b620010ed82600062000dfa565b801562001115575033620011096033546001600160a01b031690565b6001600160a01b031614155b15620011345760405163032cc2c160e61b815260040160405180910390fd5b6200113f8262000cc9565b62001176576040517fd11b153c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200118482606a546200187e565b6040516001600160a01b03831681527fff86f9eb6b23629527e566491f333a4b948736c784e372fc68e483de96d2dfb99060200160405180910390a1506001919050565b60008083606a546069856006811115620011e657620011e662001ed3565b81548110620011f957620011f962001ee9565b906000526020600020016040516020016200121793929190620021d4565b60408051601f198184030181529082905280516020918201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000091830191909152603c820152605c0160408051808303601f190181529190528051602090910120949350505050565b60006200128d3362000271565b620012f25760405162461bcd60e51b815260206004820152602e60248201527f4167656e74526f6c653a2063616c6c657220646f6573206e6f7420686176652060448201526d746865204167656e7420726f6c6560901b6064820152608401620002f3565b6066546040516000916001600160a01b0316903090620013129062001aaf565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562001346573d6000803e3d6000fd5b506040516bffffffffffffffffffffffff193060601b16602082015290915081906001600160a01b03821690631d3812409060340160408051601f198184030181529082905280516020909101207fffffffff0000000000000000000000000000000000000000000000000000000060e084901b168252600482015260016024820152600360448201526064016020604051808303816000875af1158015620013f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200141991906200200a565b506067546040517f454a03e00000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152838116602483015261ffff871660448301529091169063454a03e090606401600060405180830381600087803b1580156200148d57600080fd5b505af1158015620014a2573d6000803e3d6000fd5b5050604080516001600160a01b038916815261ffff881660208201527fed9309ce6f02df3e5693c33245e8baff8733f69708099c3c5943c13905aa92f4935001905060405180910390a1949350505050565b620014fe620016a1565b6001600160a01b0381166200157c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401620002f3565b6200158781620016fd565b50565b60006001600160a01b0382166200160a5760405162461bcd60e51b815260206004820152602260248201527f526f6c65733a206163636f756e7420697320746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401620002f3565b506001600160a01b03166000908152602091909152604090205460ff1690565b600054610100900460ff16620016975760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620002f3565b62000cc762001a37565b6033546001600160a01b0316331462000cc75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620002f3565b603380546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6200176882826200158a565b15620017b75760405162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c65006044820152606401620002f3565b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b620017e882826200158a565b6200185c5760405162461bcd60e51b815260206004820152602160248201527f526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c60448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401620002f3565b6001600160a01b0316600090815260209190915260409020805460ff19169055565b606854604080516001600160a01b039092166020830152810182905260009060600160408051808303601f19018152908290528051602090910120606754633c3ad79560e21b83526001600160a01b03868116600485015291935060009291169063f0eb5e5490602401602060405180830381865afa15801562001906573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200192c919062001d57565b6040517f4eee424a000000000000000000000000000000000000000000000000000000008152600481018490529091506001600160a01b03821690634eee424a906024016020604051808303816000875af115801562001990573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019b691906200200a565b506067546040517fa8d29d1d0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301529091169063a8d29d1d90602401600060405180830381600087803b15801562001a1857600080fd5b505af115801562001a2d573d6000803e3d6000fd5b5050505050505050565b600054610100900460ff1662001aa45760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620002f3565b62000cc733620016fd565b6104b0806200228083390190565b6001600160a01b03811681146200158757600080fd5b60006020828403121562001ae657600080fd5b813562001af38162001abd565b9392505050565b6000806000806080858703121562001b1157600080fd5b843562001b1e8162001abd565b9350602085013562001b308162001abd565b9250604085013562001b428162001abd565b9396929550929360600135925050565b8035600781106200036d57600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171562001ba45762001ba462001b62565b604052919050565b600067ffffffffffffffff82111562001bc95762001bc962001b62565b50601f01601f191660200190565b600062001bee62001be88462001bac565b62001b78565b905082815283838301111562001c0357600080fd5b828260208301376000602084830101529392505050565b6000806000806080858703121562001c3157600080fd5b843562001c3e8162001abd565b935062001c4e6020860162001b52565b9250604085013567ffffffffffffffff8082111562001c6c57600080fd5b818701915087601f83011262001c8157600080fd5b62001c928883356020850162001bd7565b9350606087013591508082111562001ca957600080fd5b508501601f8101871362001cbc57600080fd5b62001ccd8782356020840162001bd7565b91505092959194509250565b6000806040838503121562001ced57600080fd5b823562001cfa8162001abd565b915062001d0a6020840162001b52565b90509250929050565b6000806040838503121562001d2757600080fd5b823562001d348162001abd565b9150602083013561ffff8116811462001d4c57600080fd5b809150509250929050565b60006020828403121562001d6a57600080fd5b815162001af38162001abd565b600181811c9082168062001d8c57607f821691505b60208210810362001dad57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562001e0157600081815260208120601f850160051c8101602086101562001ddc5750805b601f850160051c820191505b8181101562001dfd5782815560010162001de8565b5050505b505050565b815167ffffffffffffffff81111562001e235762001e2362001b62565b62001e3b8162001e34845462001d77565b8462001db3565b602080601f83116001811462001e73576000841562001e5a5750858301515b600019600386901b1c1916600185901b17855562001dfd565b600085815260208120601f198616915b8281101562001ea45788860151825594840194600190910190840162001e83565b508582101562001ec35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60005b8381101562001f1c57818101518382015260200162001f02565b50506000910152565b6000815180845262001f3f81602086016020860162001eff565b601f01601f19169290920160200192915050565b86815260ff861660208201526001600160a01b038516604082015260c06060820152600062001f8660c083018662001f25565b828103608084015262001f9a818662001f25565b905082810360a084015262001fb0818562001f25565b9998505050505050505050565b60006020828403121562001fd057600080fd5b5051919050565b6001600160a01b038416815282602082015260606040820152600062002001606083018462001f25565b95945050505050565b6000602082840312156200201d57600080fd5b8151801515811462001af357600080fd5b60006200203f62001be88462001bac565b90508281528383830111156200205457600080fd5b62001af383602083018462001eff565b600082601f8301126200207657600080fd5b62001af3838351602085016200202e565b60008060008060008060c08789031215620020a157600080fd5b86519550602087015194506040870151620020bc8162001abd565b606088015190945067ffffffffffffffff80821115620020db57600080fd5b620020e98a838b0162002064565b945060808901519150808211156200210057600080fd5b6200210e8a838b0162002064565b935060a08901519150808211156200212557600080fd5b508701601f810189136200213857600080fd5b62002149898251602084016200202e565b9150509295509295509295565b6000808354620021668162001d77565b600182811680156200218157600181146200219757620021c8565b60ff1984168752821515830287019450620021c8565b8760005260208060002060005b85811015620021bf5781548a820152908401908201620021a4565b50505082870194505b50929695505050505050565b6001600160a01b03841681526000602084818401526060604084015260008454620021ff8162001d77565b80606087015260806001808416600081146200222457600181146200223f576200226f565b60ff1985168984015283151560051b8901830195506200226f565b896000528660002060005b85811015620022675781548b82018601529083019088016200224a565b8a0184019650505b50939a995050505050505050505056fe608060405234801561001057600080fd5b506040516104b03803806104b083398101604081905261002f91610271565b6001600160a01b03821661008a5760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f20616464726573730060448201526064015b60405180910390fd5b6001600160a01b0381166100e05760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f2061646472657373006044820152606401610081565b817fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7556000826001600160a01b031663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa158015610143573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061016791906102a4565b6040516001600160a01b03848116602483015291925060009183169060440160408051601f198184030181529181526020820180516001600160e01b031663189acdbd60e31b179052516101bb91906102c6565b600060405180830381855af49150503d80600081146101f6576040519150601f19603f3d011682016040523d82523d6000602084013e6101fb565b606091505b505090508061024c5760405162461bcd60e51b815260206004820152601660248201527f496e697469616c697a6174696f6e206661696c65642e000000000000000000006044820152606401610081565b505050506102f5565b80516001600160a01b038116811461026c57600080fd5b919050565b6000806040838503121561028457600080fd5b61028d83610255565b915061029b60208401610255565b90509250929050565b6000602082840312156102b657600080fd5b6102bf82610255565b9392505050565b6000825160005b818110156102e757602081860181015185830152016102cd565b506000920191825250919050565b6101ac806103046000396000f3fe60806040526004361061001e5760003560e01c80632307f882146100e1575b60006100487fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf75490565b73ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa158015610092573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100b69190610139565b90503660008037600080366000846127105a03f43d806000803e8180156100dc57816000f35b816000fd5b3480156100ed57600080fd5b507fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf75460405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b60006020828403121561014b57600080fd5b815173ffffffffffffffffffffffffffffffffffffffff8116811461016f57600080fd5b939250505056fea2646970667358221220d438696f94b17ea4e7f8e20058610a21ba12f3f9ba5db719d84db46450ee59e164736f6c63430008110033a2646970667358221220b61982bf231ea5e72fbc98ec86babd14bbd9c8e41fe8c767f5ee1729c7e3b8b264736f6c63430008110033
Deployed Bytecode
0x60806040523480156200001157600080fd5b5060043610620000fd5760003560e01c80638da5cb5b116200009757806398575188116200006e578063985751881462000206578063bf68c953146200021d578063c5a80fa71462000243578063f2fde38b146200025a57600080fd5b80638da5cb5b14620001c657806393c81dd614620001d857806397a6278e14620001ef57600080fd5b80636ea3622e11620000d85780636ea3622e1462000177578063715018a6146200018e57806378d77ecb146200019857806384e7984214620001af57600080fd5b80631ffbb06414620001025780632fea7b81146200012e57806346639dba146200015e575b600080fd5b620001196200011336600462001ad3565b62000271565b60405190151581526020015b60405180910390f35b620001456200013f36600462001ad3565b62000286565b6040516001600160a01b03909116815260200162000125565b620001756200016f36600462001afa565b62000372565b005b620001456200018836600462001c1a565b620009cf565b6200017562000cb1565b62000119620001a936600462001ad3565b62000cc9565b62000175620001c036600462001ad3565b62000d54565b6033546001600160a01b031662000145565b62000119620001e936600462001cd9565b62000dfa565b620001756200020036600462001ad3565b62000fc8565b620001196200021736600462001ad3565b6200106e565b620002346200022e36600462001cd9565b620011c8565b60405190815260200162000125565b620001456200025436600462001d13565b62001280565b620001756200026b36600462001ad3565b620014f4565b6000620002806065836200158a565b92915050565b6000620002933362000271565b620002fc5760405162461bcd60e51b815260206004820152602e60248201527f4167656e74526f6c653a2063616c6c657220646f6573206e6f7420686176652060448201526d746865204167656e7420726f6c6560901b60648201526084015b60405180910390fd5b606754604051633c3ad79560e21b81526001600160a01b0384811660048301529091169063f0eb5e5490602401602060405180830381865afa15801562000347573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000280919062001d57565b919050565b600054610100900460ff1615808015620003935750600054600160ff909116105b80620003af5750303b158015620003af575060005460ff166001145b620004235760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401620002f3565b6000805460ff19166001179055801562000447576000805461ff0019166101001790555b6001600160a01b038516620004a057604051636cbb462960e01b815260206004820152600d60248201527f496d706c417574686f72697479000000000000000000000000000000000000006044820152606401620002f3565b6001600160a01b038416620004f957604051636cbb462960e01b815260206004820152601060248201527f4964656e746974795265676973747279000000000000000000000000000000006044820152606401620002f3565b6001600160a01b0383166200055257604051636cbb462960e01b815260206004820152600b60248201527f436c61696d4973737565720000000000000000000000000000000000000000006044820152606401620002f3565b606680546001600160a01b0387811673ffffffffffffffffffffffffffffffffffffffff1992831617909255606780548784169083161790556068805492861692909116919091179055606a829055604080517f4672696374696f6e6c657373204d61726b6574732054726561737572792e000060208201528151808203601e018152603e909101909152606980546001810182556000919091527f7fb4302e8e91f9110a6554c2c0a24601252c2a42c2220ca988efcfe39991430801906200061c908262001e06565b50606960405160200162000679907f4672696374696f6e6c657373204d61726b657473205175616c6966696564204381527f7573746f6469616e2e0000000000000000000000000000000000000000000000602082015260290190565b60408051601f1981840301815291905281546001810183556000928352602090922090910190620006ab908262001e06565b50606960405160200162000708907f4672696374696f6e6c657373204d61726b657473205065726d697373696f6e6581527f6420496e766573746f722e0000000000000000000000000000000000000000006020820152602b0190565b60408051601f19818403018152919052815460018101835560009283526020909220909101906200073a908262001e06565b50606960405160200162000797907f4672696374696f6e6c657373204d61726b657473205065726d697373696f6e6581527f64204d616e616765722e000000000000000000000000000000000000000000006020820152602a0190565b60408051601f1981840301815291905281546001810183556000928352602090922090910190620007c9908262001e06565b50606960405160200162000826907f4672696374696f6e6c657373204d61726b657473205065726d697373696f6e6581527f642043616c63756c6174696e67204167656e742e000000000000000000000000602082015260340190565b60408051601f198184030181529190528154600181018355600092835260209092209091019062000858908262001e06565b506069604051602001620008b5907f4672696374696f6e6c657373204d61726b657473205065726d697373696f6e6581527f64205472616e73666572204167656e742e000000000000000000000000000000602082015260310190565b60408051601f1981840301815291905281546001810183556000928352602090922090910190620008e7908262001e06565b50606960405160200162000944907f4672696374696f6e6c657373204d61726b657473205065726d697373696f6e6581527f642046756e64204163636f756e74616e742e0000000000000000000000000000602082015260320190565b60408051601f198184030181529190528154600181018355600092835260209092209091019062000976908262001e06565b50620009816200162a565b8015620009c8576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6000620009dc3362000271565b62000a415760405162461bcd60e51b815260206004820152602e60248201527f4167656e74526f6c653a2063616c6c657220646f6573206e6f7420686176652060448201526d746865204167656e7420726f6c6560901b6064820152608401620002f3565b600084600681111562000a585762000a5862001ed3565b14801562000a8157503362000a756033546001600160a01b031690565b6001600160a01b031614155b1562000aa05760405163032cc2c160e61b815260040160405180910390fd5b6040805160c0810182526068546001600160a01b039081168252606a54602083015260019282019290925290861660608201526080810184905260009060a08101606987600681111562000af85762000af862001ed3565b8154811062000b0b5762000b0b62001ee9565b90600052602060002001805462000b229062001d77565b80601f016020809104026020016040519081016040528092919081815260200182805462000b509062001d77565b801562000ba15780601f1062000b755761010080835404028352916020019162000ba1565b820191906000526020600020905b81548152906001019060200180831162000b8357829003601f168201915b50505091909252505060208101516040808301518351608085015160a086015193517fb1a34e0d0000000000000000000000000000000000000000000000000000000081529596506001600160a01b038c169563b1a34e0d9562000c0f9590949392918b9060040162001f53565b6020604051808303816000875af115801562000c2f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000c55919062001fbd565b507fade9e42fe0bd2abdc23cc41ed4133977fd4f72f4218628c8cc9fc25e881f5e578686600681111562000c8d5762000c8d62001ed3565b8560405162000c9f9392919062001fd7565b60405180910390a15093949350505050565b62000cbb620016a1565b62000cc76000620016fd565b565b6067546040517fb9209e330000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152600092169063b9209e3390602401602060405180830381865afa15801562000d2e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200028091906200200a565b62000d5e620016a1565b6001600160a01b03811662000db65760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f2061646472657373006044820152606401620002f3565b62000dc36065826200175c565b6040516001600160a01b038216907ff68e73cec97f2d70aa641fb26e87a4383686e2efacb648f2165aeb02ac562ec590600090a250565b600062000e078362000cc9565b62000e155750600062000280565b606754604051633c3ad79560e21b81526001600160a01b038581166004830152600092169063f0eb5e5490602401602060405180830381865afa15801562000e61573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000e87919062001d57565b606854606a54604080516001600160a01b03909316602084015282015290915060009060600160408051601f198184030181529082905280516020909101207fc9100bcb0000000000000000000000000000000000000000000000000000000082526004820181905291506000906001600160a01b0384169063c9100bcb90602401600060405180830381865afa15801562000f27573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000f51919081019062002087565b509450505050508080519060200120606986600681111562000f775762000f7762001ed3565b8154811062000f8a5762000f8a62001ee9565b9060005260206000200160405160200162000fa6919062002156565b6040516020818303038152906040528051906020012014935050505092915050565b62000fd2620016a1565b6001600160a01b0381166200102a5760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f2061646472657373006044820152606401620002f3565b62001037606582620017dc565b6040516001600160a01b038216907fed9c8ad8d5a0a66898ea49d2956929c93ae2e8bd50281b2ed897c5d1a6737e0b90600090a250565b60006200107b3362000271565b620010e05760405162461bcd60e51b815260206004820152602e60248201527f4167656e74526f6c653a2063616c6c657220646f6573206e6f7420686176652060448201526d746865204167656e7420726f6c6560901b6064820152608401620002f3565b620010ed82600062000dfa565b801562001115575033620011096033546001600160a01b031690565b6001600160a01b031614155b15620011345760405163032cc2c160e61b815260040160405180910390fd5b6200113f8262000cc9565b62001176576040517fd11b153c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200118482606a546200187e565b6040516001600160a01b03831681527fff86f9eb6b23629527e566491f333a4b948736c784e372fc68e483de96d2dfb99060200160405180910390a1506001919050565b60008083606a546069856006811115620011e657620011e662001ed3565b81548110620011f957620011f962001ee9565b906000526020600020016040516020016200121793929190620021d4565b60408051601f198184030181529082905280516020918201207f19457468657265756d205369676e6564204d6573736167653a0a33320000000091830191909152603c820152605c0160408051808303601f190181529190528051602090910120949350505050565b60006200128d3362000271565b620012f25760405162461bcd60e51b815260206004820152602e60248201527f4167656e74526f6c653a2063616c6c657220646f6573206e6f7420686176652060448201526d746865204167656e7420726f6c6560901b6064820152608401620002f3565b6066546040516000916001600160a01b0316903090620013129062001aaf565b6001600160a01b03928316815291166020820152604001604051809103906000f08015801562001346573d6000803e3d6000fd5b506040516bffffffffffffffffffffffff193060601b16602082015290915081906001600160a01b03821690631d3812409060340160408051601f198184030181529082905280516020909101207fffffffff0000000000000000000000000000000000000000000000000000000060e084901b168252600482015260016024820152600360448201526064016020604051808303816000875af1158015620013f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200141991906200200a565b506067546040517f454a03e00000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152838116602483015261ffff871660448301529091169063454a03e090606401600060405180830381600087803b1580156200148d57600080fd5b505af1158015620014a2573d6000803e3d6000fd5b5050604080516001600160a01b038916815261ffff881660208201527fed9309ce6f02df3e5693c33245e8baff8733f69708099c3c5943c13905aa92f4935001905060405180910390a1949350505050565b620014fe620016a1565b6001600160a01b0381166200157c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401620002f3565b6200158781620016fd565b50565b60006001600160a01b0382166200160a5760405162461bcd60e51b815260206004820152602260248201527f526f6c65733a206163636f756e7420697320746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401620002f3565b506001600160a01b03166000908152602091909152604090205460ff1690565b600054610100900460ff16620016975760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620002f3565b62000cc762001a37565b6033546001600160a01b0316331462000cc75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620002f3565b603380546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6200176882826200158a565b15620017b75760405162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c65006044820152606401620002f3565b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b620017e882826200158a565b6200185c5760405162461bcd60e51b815260206004820152602160248201527f526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c60448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401620002f3565b6001600160a01b0316600090815260209190915260409020805460ff19169055565b606854604080516001600160a01b039092166020830152810182905260009060600160408051808303601f19018152908290528051602090910120606754633c3ad79560e21b83526001600160a01b03868116600485015291935060009291169063f0eb5e5490602401602060405180830381865afa15801562001906573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200192c919062001d57565b6040517f4eee424a000000000000000000000000000000000000000000000000000000008152600481018490529091506001600160a01b03821690634eee424a906024016020604051808303816000875af115801562001990573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019b691906200200a565b506067546040517fa8d29d1d0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811660048301529091169063a8d29d1d90602401600060405180830381600087803b15801562001a1857600080fd5b505af115801562001a2d573d6000803e3d6000fd5b5050505050505050565b600054610100900460ff1662001aa45760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620002f3565b62000cc733620016fd565b6104b0806200228083390190565b6001600160a01b03811681146200158757600080fd5b60006020828403121562001ae657600080fd5b813562001af38162001abd565b9392505050565b6000806000806080858703121562001b1157600080fd5b843562001b1e8162001abd565b9350602085013562001b308162001abd565b9250604085013562001b428162001abd565b9396929550929360600135925050565b8035600781106200036d57600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171562001ba45762001ba462001b62565b604052919050565b600067ffffffffffffffff82111562001bc95762001bc962001b62565b50601f01601f191660200190565b600062001bee62001be88462001bac565b62001b78565b905082815283838301111562001c0357600080fd5b828260208301376000602084830101529392505050565b6000806000806080858703121562001c3157600080fd5b843562001c3e8162001abd565b935062001c4e6020860162001b52565b9250604085013567ffffffffffffffff8082111562001c6c57600080fd5b818701915087601f83011262001c8157600080fd5b62001c928883356020850162001bd7565b9350606087013591508082111562001ca957600080fd5b508501601f8101871362001cbc57600080fd5b62001ccd8782356020840162001bd7565b91505092959194509250565b6000806040838503121562001ced57600080fd5b823562001cfa8162001abd565b915062001d0a6020840162001b52565b90509250929050565b6000806040838503121562001d2757600080fd5b823562001d348162001abd565b9150602083013561ffff8116811462001d4c57600080fd5b809150509250929050565b60006020828403121562001d6a57600080fd5b815162001af38162001abd565b600181811c9082168062001d8c57607f821691505b60208210810362001dad57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562001e0157600081815260208120601f850160051c8101602086101562001ddc5750805b601f850160051c820191505b8181101562001dfd5782815560010162001de8565b5050505b505050565b815167ffffffffffffffff81111562001e235762001e2362001b62565b62001e3b8162001e34845462001d77565b8462001db3565b602080601f83116001811462001e73576000841562001e5a5750858301515b600019600386901b1c1916600185901b17855562001dfd565b600085815260208120601f198616915b8281101562001ea45788860151825594840194600190910190840162001e83565b508582101562001ec35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60005b8381101562001f1c57818101518382015260200162001f02565b50506000910152565b6000815180845262001f3f81602086016020860162001eff565b601f01601f19169290920160200192915050565b86815260ff861660208201526001600160a01b038516604082015260c06060820152600062001f8660c083018662001f25565b828103608084015262001f9a818662001f25565b905082810360a084015262001fb0818562001f25565b9998505050505050505050565b60006020828403121562001fd057600080fd5b5051919050565b6001600160a01b038416815282602082015260606040820152600062002001606083018462001f25565b95945050505050565b6000602082840312156200201d57600080fd5b8151801515811462001af357600080fd5b60006200203f62001be88462001bac565b90508281528383830111156200205457600080fd5b62001af383602083018462001eff565b600082601f8301126200207657600080fd5b62001af3838351602085016200202e565b60008060008060008060c08789031215620020a157600080fd5b86519550602087015194506040870151620020bc8162001abd565b606088015190945067ffffffffffffffff80821115620020db57600080fd5b620020e98a838b0162002064565b945060808901519150808211156200210057600080fd5b6200210e8a838b0162002064565b935060a08901519150808211156200212557600080fd5b508701601f810189136200213857600080fd5b62002149898251602084016200202e565b9150509295509295509295565b6000808354620021668162001d77565b600182811680156200218157600181146200219757620021c8565b60ff1984168752821515830287019450620021c8565b8760005260208060002060005b85811015620021bf5781548a820152908401908201620021a4565b50505082870194505b50929695505050505050565b6001600160a01b03841681526000602084818401526060604084015260008454620021ff8162001d77565b80606087015260806001808416600081146200222457600181146200223f576200226f565b60ff1985168984015283151560051b8901830195506200226f565b896000528660002060005b85811015620022675781548b82018601529083019088016200224a565b8a0184019650505b50939a995050505050505050505056fe608060405234801561001057600080fd5b506040516104b03803806104b083398101604081905261002f91610271565b6001600160a01b03821661008a5760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f20616464726573730060448201526064015b60405180910390fd5b6001600160a01b0381166100e05760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420617267756d656e74202d207a65726f2061646472657373006044820152606401610081565b817fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7556000826001600160a01b031663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa158015610143573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061016791906102a4565b6040516001600160a01b03848116602483015291925060009183169060440160408051601f198184030181529181526020820180516001600160e01b031663189acdbd60e31b179052516101bb91906102c6565b600060405180830381855af49150503d80600081146101f6576040519150601f19603f3d011682016040523d82523d6000602084013e6101fb565b606091505b505090508061024c5760405162461bcd60e51b815260206004820152601660248201527f496e697469616c697a6174696f6e206661696c65642e000000000000000000006044820152606401610081565b505050506102f5565b80516001600160a01b038116811461026c57600080fd5b919050565b6000806040838503121561028457600080fd5b61028d83610255565b915061029b60208401610255565b90509250929050565b6000602082840312156102b657600080fd5b6102bf82610255565b9392505050565b6000825160005b818110156102e757602081860181015185830152016102cd565b506000920191825250919050565b6101ac806103046000396000f3fe60806040526004361061001e5760003560e01c80632307f882146100e1575b60006100487fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf75490565b73ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa158015610092573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100b69190610139565b90503660008037600080366000846127105a03f43d806000803e8180156100dc57816000f35b816000fd5b3480156100ed57600080fd5b507fc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf75460405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b60006020828403121561014b57600080fd5b815173ffffffffffffffffffffffffffffffffffffffff8116811461016f57600080fd5b939250505056fea2646970667358221220d438696f94b17ea4e7f8e20058610a21ba12f3f9ba5db719d84db46450ee59e164736f6c63430008110033a2646970667358221220b61982bf231ea5e72fbc98ec86babd14bbd9c8e41fe8c767f5ee1729c7e3b8b264736f6c63430008110033
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.