Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been partially verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- Member
- Optimization enabled
- true
- Compiler version
- v0.8.13+commit.abaa5c0e
- Optimization runs
- 200
- EVM Version
- london
- Verified at
- 2026-05-31T10:37:35.703366Z
contracts/Member.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./interfaces/IProtocolDirectory.sol";
import "./interfaces/IMember.sol";
import "./interfaces/IMembership.sol";
import "./interfaces/IMembershipFactory.sol";
import "./interfaces/IBlacklist.sol";
import "./libraries/Errors.sol";
import "./libraries/TokenActions.sol";
import "./structs/MemberStruct.sol";
import "./structs/BackupApprovalStruct.sol";
import "./structs/MembershipStruct.sol";
/**
* @title Member Contract
* @notice This contract contains logic for interacting with the
* ecosystem and verifying ownership as well as the panic button
* functionality and backup information (BackupPlan)
*
*/
contract Member is
IMember,
Initializable,
OwnableUpgradeable,
ReentrancyGuardUpgradeable
{
/**
* @notice memberCreated Event when creating member
* @param uid string of dApp identifier for a user
* @param dateCreated timestamp of event occurence
*
*/
event memberCreated(string uid, uint256 dateCreated);
/**
* @notice Event when updating primary wallet
* @param uid string string of dApp identifier for a user
* @param dateCreated uint256 timestamap of event occuring
* @param wallets address[] list of wallets for the user
* @param primaryWallet uint256 primary wallet for assets
*
*/
event walletUpdated(
string uid,
uint256 dateCreated,
address[] backUpWallets,
address[] wallets,
uint256 primaryWallet
);
/// @notice Mapping to return member when uid is passed
mapping(string => member) public members;
/// @notice Variable to store all member information
member[] public allMembers;
/// @notice UserMembershipAddress mapping for getting Membership contracts by user
mapping(string => address) private UserMembershipAddress;
/// @notice Storing ApprovalId for different approvals stored
uint256 private _approvalId;
/// @notice mapping for token backup Approvals for specific UID
mapping(string => BackUpApprovals[]) private MemberApprovals;
/**
* @notice Event for Querying Approvals
*
* @param uid string of dApp identifier for a user
* @param approvedWallet address of the wallet owning the asset
* @param backupaddress address[] list of addresses containing assets
* @param tokenId uint256 tokenId of asset being backed up
* @param tokenAddress address contract of the asset being protectd
* @param tokenType string i.e. ERC20 | ERC1155 | ERC721
* @param tokensAllocated uint256 number of tokens to be protected
* @param dateApproved uint256 timestamp of event happening
* @param claimed bool status of the backupApproval
* @param approvalId uint256 id of the approval being acted on
* @param claimedWallet address of receipient of assets
*
*
*/
event BackUpApprovalsEvent(
string uid,
address approvedWallet,
address[] backupaddress,
uint256 tokenId,
address tokenAddress,
string tokenType,
uint256 tokensAllocated,
uint256 dateApproved,
bool claimed,
uint256 approvalId,
address claimedWallet
);
/// @dev address of the ProtocolDirectory
address public directoryContract;
/**
* @dev initialize - Initializes the function for Ownable and Reentrancy.
* @param _directoryContract address of protocol directory contract
*/
function initialize(address _directoryContract) public initializer {
__Context_init_unchained();
__Ownable_init();
__ReentrancyGuard_init();
_approvalId = 0;
directoryContract = _directoryContract;
}
/**
* @notice Function to check if wallet exists in the UID
* @param _uid string of dApp identifier for a user
* @param _user address of the user checking exists
* Fails if not owner uid and user address do not return a wallet
*
*/
function checkUIDofSender(string memory _uid, address _user) public view {
address[] memory wallets = members[_uid].wallets;
bool walletExists = false;
for (uint256 i = 0; i < wallets.length; i++) {
if (wallets[i] == _user) {
walletExists = true;
}
}
if (walletExists == false) {
revert(Errors.M_NOT_OWNER);
}
}
/**
* @dev checkIfUIDExists
* Check if user exists for specific wallet address already internal function
* @param _walletAddress wallet address of the user
* @return _exists - A boolean if user exists or not
*
*/
function checkIfUIDExists(address _walletAddress)
public
view
returns (bool _exists)
{
address IBlacklistUsersAddress = IProtocolDirectory(directoryContract)
.getBlacklistContract();
IBlacklist(IBlacklistUsersAddress).checkIfAddressIsBlacklisted(
_walletAddress
);
for (uint256 i = 0; i < allMembers.length; i++) {
address[] memory _wallets = allMembers[i].wallets;
if (_wallets.length != 0) {
for (uint256 j = 0; j < _wallets.length; j++) {
if (_wallets[j] == _walletAddress) {
_exists = true;
}
}
}
}
}
/**
* @notice checkIfWalletHasNFT
* verify if the user has specific nft 1155 or 721
* @param _contractAddress address of asset contract
* @param _NFTType string i.e. ERC721 | ERC1155
* @param tokenId uint256 tokenId checking for ownership
* @param userAddress address address to verify ownership of
* Fails if not owner
*/
function checkIfWalletHasNFT(
address _contractAddress,
string memory _NFTType,
uint256 tokenId,
address userAddress
) public view {
// check if wallet has nft
bool status = false;
if (
keccak256(abi.encodePacked((_NFTType))) ==
keccak256(abi.encodePacked(("ERC721")))
) {
if (IERC721(_contractAddress).ownerOf(tokenId) == userAddress) {
status = true;
} else if (
IERC721Upgradeable(_contractAddress).ownerOf(tokenId) ==
userAddress
) {
status = true;
}
}
if (
keccak256(abi.encodePacked((_NFTType))) ==
keccak256(abi.encodePacked(("ERC1155")))
) {
if (
IERC1155(_contractAddress).balanceOf(userAddress, tokenId) != 0
) {
status = true;
} else if (
IERC1155Upgradeable(_contractAddress).balanceOf(
userAddress,
tokenId
) != 0
) {
status = true;
}
}
if (status == false) {
revert(Errors.M_NOT_HOLDER);
}
}
/**
* @dev createMember
* @param uid centrally stored id for user
* @param _walletAddress walletAddress to add wallet and check blacklist
*
* Allows to create a member onChain with a unique UID passed.
* Will revert if the _walletAddress passed in is blacklisted
*
*/
function createMember(string memory uid, address _walletAddress) public {
address IBlacklistUsersAddress = IProtocolDirectory(directoryContract)
.getBlacklistContract();
IBlacklist(IBlacklistUsersAddress).checkIfAddressIsBlacklisted(
_walletAddress
);
if (
(keccak256(abi.encodePacked((members[uid].uid))) !=
keccak256(abi.encodePacked((uid))) &&
(checkIfUIDExists(_walletAddress) == false))
) {
if (bytes(uid).length == 0) {
revert(Errors.M_EMPTY_UID);
}
address[] memory _wallets;
member memory _member = member(
uid,
block.timestamp,
_wallets,
_wallets,
0
);
members[uid] = _member;
allMembers.push(_member);
_addWallet(uid, _walletAddress, true);
emit memberCreated(_member.uid, _member.dateCreated);
} else {
revert(Errors.M_USER_EXISTS);
}
}
/**
* @dev getMember
* @param uid string for centrally located identifier
* Allows to get member information stored onChain with a unique UID passed.
* @return member struct for a given uid
*
*/
function getMember(string memory uid)
public
view
override
returns (member memory)
{
member memory currentMember = members[uid];
if (currentMember.dateCreated == 0) {
revert(Errors.M_USER_DNE);
}
return currentMember;
}
/**
* @dev getAllMembers
* Allows to get all member information stored onChain
* @return allMembers a list of member structs
*
*/
function getAllMembers() external view returns (member[] memory) {
return allMembers;
}
/**
* @dev addWallet - Allows to add Wallet to the user
* @param uid string for dApp user identifier
* @param _wallet address wallet being added for given user
* @param _primary bool whether or not this new wallet is the primary wallet
*
*
*/
function addWallet(
string memory uid,
address _wallet,
bool _primary
) public {
checkUIDofSender(uid, msg.sender);
_addWallet(uid, _wallet, _primary);
}
/**
* @dev addWallet - Allows to add Wallet to the user
* @param uid string for dApp user identifier
* @param _wallet address wallet being added for given user
* @param _primary bool whether or not this new wallet is the primary wallet
*
*
*/
function _addWallet(
string memory uid,
address _wallet,
bool _primary
) internal {
member storage _member = members[uid];
_member.wallets.push(_wallet);
if (_primary) {
_member.primaryWallet = _member.wallets.length - 1;
}
for (uint256 i = 0; i < allMembers.length; i++) {
member storage member_ = allMembers[i];
if (
keccak256(abi.encodePacked((member_.uid))) ==
keccak256(abi.encodePacked((uid)))
) {
member_.wallets.push(_wallet);
if (_primary) {
member_.primaryWallet = member_.wallets.length - 1;
}
}
}
emit walletUpdated(
_member.uid,
_member.dateCreated,
_member.backUpWallets,
_member.wallets,
_member.primaryWallet
);
}
/**
* @dev addBackUpWallet - Allows to add backUp Wallets to the user
* @param uid string for dApp user identifier
* @param _wallets addresses of wallets being added for given user
*
*
*/
function addBackupWallet(string calldata uid, address[] memory _wallets)
public
{
checkUIDofSender(uid, msg.sender);
_addBackupWallet(uid, _wallets, msg.sender);
}
/**
* @dev addBackUpWallet - Allows to add backUp Wallets to the user
* @param uid string for dApp user identifier
* @param _wallets addresses of wallets being added for given user
*
*
*/
function _addBackupWallet(
string calldata uid,
address[] memory _wallets,
address _user
) internal {
if ((checkIfUIDExists(_user) == false)) {
createMember(uid, _user);
}
member storage _member = members[uid];
if (_member.wallets.length == 0) {
revert(Errors.M_USER_MUST_WALLET);
}
for (uint256 i = 0; i < _wallets.length; i++) {
_member.backUpWallets.push(_wallets[i]);
}
for (uint256 i = 0; i < allMembers.length; i++) {
member storage member_ = allMembers[i];
if (
keccak256(abi.encodePacked((member_.uid))) ==
keccak256(abi.encodePacked((uid)))
) {
for (uint256 j = 0; j < _wallets.length; j++) {
member_.backUpWallets.push(_wallets[j]);
}
}
}
emit walletUpdated(
_member.uid,
_member.dateCreated,
_member.backUpWallets,
_member.wallets,
_member.primaryWallet
);
}
/**
* @dev getBackupWallets - Returns backup Wallets for the specific UID
* @param uid string for dApp user identifier
*
*/
function getBackupWallets(string calldata uid)
external
view
returns (address[] memory)
{
return members[uid].backUpWallets;
}
/**
* @dev deleteWallet - Allows to delete wallets of a specific user
* @param uid string for dApp user identifier
* @param _walletIndex uint256 which index does the wallet exist in the member wallet list
*
*/
function deleteWallet(string calldata uid, uint256 _walletIndex) external {
checkUIDofSender(uid, msg.sender);
member storage _member = members[uid];
if (_walletIndex == _member.primaryWallet) {
revert(Errors.M_PRIM_WALLET);
}
delete members[uid].wallets[_walletIndex];
address[] storage wallets = members[uid].wallets;
for (uint256 i = _walletIndex; i < wallets.length - 1; i++) {
wallets[i] = wallets[i + 1];
}
if (members[uid].primaryWallet >= _walletIndex) {
members[uid].primaryWallet--;
}
wallets.pop();
for (uint256 i = 0; i < allMembers.length; i++) {
member storage member_ = allMembers[i];
if (
keccak256(abi.encodePacked((member_.uid))) ==
keccak256(abi.encodePacked((uid)))
) {
address[] storage wallets_ = member_.wallets;
for (uint256 j = _walletIndex; j < wallets_.length - 1; j++) {
wallets_[j] = wallets_[j + 1];
}
wallets_.pop();
if (member_.primaryWallet >= _walletIndex) {
member_.primaryWallet--;
}
}
}
}
/**
* @dev setPrimaryWallet
* Allows to set a specific wallet as the primary wallet
* @param uid string for dApp user identifier
* @param _walletIndex uint256 which index does the wallet exist in the member wallet list
*
*/
function setPrimaryWallet(string calldata uid, uint256 _walletIndex)
external
override
{
checkUIDofSender(uid, msg.sender);
if (_walletIndex == members[uid].primaryWallet) {
revert(Errors.M_ALREADY_PRIM);
}
members[uid].primaryWallet = _walletIndex;
for (uint256 i = 0; i < allMembers.length; i++) {
member storage member_ = allMembers[i];
if (
keccak256(abi.encodePacked((member_.uid))) ==
keccak256(abi.encodePacked((uid)))
) {
member_.primaryWallet = _walletIndex;
}
}
}
/**
* @dev getWallets
* Allows to get all wallets of the user
* @param uid string for dApp user identifier
* @return address[] list of wallets
*
*/
function getWallets(string calldata uid)
external
view
override
returns (address[] memory)
{
return members[uid].wallets;
}
/**
* @dev getPrimaryWallets
* Allows to get primary wallet of the user
* @param uid string for dApp user identifier
* @return address of the primary wallet per user
*
*/
function getPrimaryWallet(string memory uid)
public
view
override
returns (address)
{
return members[uid].wallets[members[uid].primaryWallet];
}
/**
* @dev checkWallet
* Allows to check if a wallet is a Backup wallets of the user
* @param _Wallets list of addresses to check if wallet is present
* @param uid string for dApp user identifier
* @return boolean if the wallet exists
*
*/
function checkWallet(address[] calldata _Wallets, string memory uid)
internal
view
returns (bool)
{
address[] memory wallets = members[uid].wallets;
bool walletExists = false;
for (uint256 i = 0; i < wallets.length; i++) {
for (uint256 j = 0; j < _Wallets.length; j++) {
if (wallets[i] == _Wallets[j]) {
walletExists = true;
}
}
}
return walletExists;
}
/**
* @dev getUID
* Allows user to pass walletAddress and return UID
* @param _walletAddress get the UID of the user's if their wallet address is present
* @return string of the ID used in the dApp to identify they user
*
*/
function getUID(address _walletAddress)
public
view
override
returns (string memory)
{
string memory memberuid;
for (uint256 i = 0; i < allMembers.length; i++) {
address[] memory _wallets = allMembers[i].wallets;
if (_wallets.length != 0) {
for (uint256 j = 0; j < _wallets.length; j++) {
if (_wallets[j] == _walletAddress) {
memberuid = allMembers[i].uid;
}
}
}
}
if (bytes(memberuid).length == 0) {
revert(Errors.M_UID_DNE);
}
return memberuid;
}
/**
* @dev storeBackupAssetsApprovals - Function to store All Types Approvals by the user for backup
*
* @param _contractAddress address[] Ordered list of contract addresses for assets
* @param _tokenIds uint256[] Ordered list of tokenIds associated with contract addresses
* @param _backUpWallets address[] Ordered list of wallet addresses to backup assets
* @param _tokenAmount uint256[] Ordered list of amounts per asset contract and token id to protext
* @param _tokenTypes string[] Ordered list of strings i.e. ERC20 | ERC721 | ERC1155
* @param _memberUID string for dApp user identifier
* @param _userAddress address of the user
* @param _super bool true if function is being called from a parent function. false if directly
*
*/
function storeBackupAssetsApprovals(
address[] calldata _contractAddress,
uint256[] calldata _tokenIds,
address[] calldata _backUpWallets,
uint256[] calldata _tokenAmount,
string[] calldata _tokenTypes,
string calldata _memberUID,
address _userAddress,
bool _super
) public {
if (
_tokenIds.length != _contractAddress.length ||
_tokenAmount.length != _tokenTypes.length
) {
revert(Errors.M_DIFF_LENGTHS);
}
if (_super == false) {
checkUIDofSender(_memberUID, msg.sender);
}
if ((checkIfUIDExists(_userAddress) == false)) {
createMember(_memberUID, _userAddress);
}
member memory _member = getMember(_memberUID);
checkUserHasMembership(_memberUID, _userAddress);
_addBackupWallet(_memberUID, _backUpWallets, _userAddress);
for (uint256 i = 0; i < _tokenIds.length; i++) {
address contractAddress = _contractAddress[i];
uint256 tokenId_ = _tokenIds[i];
string memory tokenType = _tokenTypes[i];
uint256 tokenAmount = _tokenAmount[i];
TokenActions.checkAssetContract(contractAddress, tokenType);
Token memory _token = Token(
tokenId_,
contractAddress,
tokenType,
tokenAmount
);
_storeAssets(
_memberUID,
_member,
_userAddress,
_backUpWallets,
_token
);
}
IMembership(UserMembershipAddress[_memberUID]).redeemUpdate(_memberUID);
}
/**
* @dev _storeAssets - Internal function to store assets approvals for backup
* @param uid string identifier of user across dApp
* @param _member member struct of user storing assets for
* @param user address of the user of the dApp
* @param _backUpWallet address[] list of wallets protected
* @param _token Token struct containing token information
*
*/
function _storeAssets(
string calldata uid,
member memory _member,
address user,
address[] calldata _backUpWallet,
Token memory _token
) internal {
uint256 _dateApproved = block.timestamp;
BackUpApprovals memory approval = BackUpApprovals(
_member,
user,
_backUpWallet,
_token,
_dateApproved,
false,
++_approvalId
);
MemberApprovals[uid].push(approval);
emit BackUpApprovalsEvent(
_member.uid,
user,
_backUpWallet,
_token.tokenId,
_token.tokenAddress,
_token.tokenType,
_token.tokensAllocated,
_dateApproved,
false,
_approvalId,
address(0)
);
}
/**
* @dev executePanic - Public function to transfer assets from one user to another
* @param _backUpWallet wallet to panic send assets to
* @param _memberUID uid of the user's assets being moved
*
*/
function executePanic(address _backUpWallet, string memory _memberUID)
external
{
checkBackupandSenderofUID(_memberUID, msg.sender);
address IBlacklistUsersAddress = IProtocolDirectory(directoryContract)
.getBlacklistContract();
if (MemberApprovals[_memberUID].length <= 0) {
revert(Errors.M_BACKUP_FIRST);
}
IBlacklist(IBlacklistUsersAddress).checkIfAddressIsBlacklisted(
_backUpWallet
);
_panic(_memberUID, _backUpWallet);
}
/**
* @dev _checkBackUpExists - Internal function that checks backup approvals if the backup Wallet Exists
* @param _approvals BackUpApprovals struct with backup information
* @param _backUpWallet wallet to verify is inside of approval
*
*/
function _checkBackUpExists(
BackUpApprovals memory _approvals,
address _backUpWallet
) internal pure {
bool backUpExists = false;
for (uint256 j = 0; j < _approvals.backUpWallet.length; j++) {
if (_approvals.backUpWallet[j] == _backUpWallet) {
backUpExists = true;
}
}
if (!backUpExists) {
revert(Errors.M_INVALID_BACKUP);
}
}
/**
* @dev _panic - Private Function to test panic functionality in order to execute and transfer all assets from one user to another
* @param uid string of identifier for user in dApp
* @param _backUpWallet address where to send assets to
*
*/
function _panic(string memory uid, address _backUpWallet) internal {
BackUpApprovals[] storage _approvals = MemberApprovals[uid];
for (uint256 i = 0; i < _approvals.length; i++) {
if (_approvals[i].claimed == false) {
_checkBackUpExists(_approvals[i], _backUpWallet);
if (
keccak256(
abi.encodePacked((_approvals[i].token.tokenType))
) == keccak256(abi.encodePacked(("ERC20")))
) {
IERC20 ERC20 = IERC20(_approvals[i].token.tokenAddress);
uint256 tokenAllowance = ERC20.allowance(
_approvals[i].approvedWallet,
address(this)
);
uint256 tokenBalance = ERC20.balanceOf(
_approvals[i].approvedWallet
);
if (tokenBalance <= tokenAllowance) {
ERC20.transferFrom(
_approvals[i].approvedWallet,
_backUpWallet,
tokenBalance
);
} else {
ERC20.transferFrom(
_approvals[i].approvedWallet,
_backUpWallet,
tokenAllowance
);
}
_approvals[i].claimed = true;
emit BackUpApprovalsEvent(
_approvals[i].Member.uid,
_approvals[i].approvedWallet,
_approvals[i].backUpWallet,
_approvals[i].token.tokenId,
_approvals[i].token.tokenAddress,
_approvals[i].token.tokenType,
_approvals[i].token.tokensAllocated,
_approvals[i].dateApproved,
_approvals[i].claimed,
_approvals[i].approvalId,
_backUpWallet
);
}
if (
keccak256(
abi.encodePacked((_approvals[i].token.tokenType))
) == keccak256(abi.encodePacked(("ERC721")))
) {
IERC721 ERC721 = IERC721(_approvals[i].token.tokenAddress);
address _tokenAddress = ERC721.ownerOf(
_approvals[i].token.tokenId
);
if (_tokenAddress == _approvals[i].approvedWallet) {
ERC721.safeTransferFrom(
_approvals[i].approvedWallet,
_backUpWallet,
_approvals[i].token.tokenId
);
}
_approvals[i].claimed = true;
emit BackUpApprovalsEvent(
_approvals[i].Member.uid,
_approvals[i].approvedWallet,
_approvals[i].backUpWallet,
_approvals[i].token.tokenId,
_approvals[i].token.tokenAddress,
_approvals[i].token.tokenType,
_approvals[i].token.tokensAllocated,
_approvals[i].dateApproved,
_approvals[i].claimed,
_approvals[i].approvalId,
_backUpWallet
);
}
if (
keccak256(
abi.encodePacked((_approvals[i].token.tokenType))
) == keccak256(abi.encodePacked(("ERC1155")))
) {
IERC1155 ERC1155 = IERC1155(
_approvals[i].token.tokenAddress
);
uint256 _balance = ERC1155.balanceOf(
_approvals[i].approvedWallet,
_approvals[i].token.tokenId
);
bytes memory data;
if (_balance <= _approvals[i].token.tokensAllocated) {
ERC1155.safeTransferFrom(
_approvals[i].approvedWallet,
_backUpWallet,
_approvals[i].token.tokenId,
_balance,
data
);
} else {
ERC1155.safeTransferFrom(
_approvals[i].approvedWallet,
_backUpWallet,
_approvals[i].token.tokenId,
_approvals[i].token.tokensAllocated,
data
);
}
_approvals[i].claimed = true;
emit BackUpApprovalsEvent(
_approvals[i].Member.uid,
_approvals[i].approvedWallet,
_approvals[i].backUpWallet,
_approvals[i].token.tokenId,
_approvals[i].token.tokenAddress,
_approvals[i].token.tokenType,
_approvals[i].token.tokensAllocated,
_approvals[i].dateApproved,
_approvals[i].claimed,
_approvals[i].approvalId,
_backUpWallet
);
}
}
}
}
/**
* @dev getBackupApprovals - function to return all backupapprovals for a specific UID
* @param uid string of identifier for user in dApp
* @return BackUpApprovals[] list of BackUpApprovals struct
*
*/
function getBackupApprovals(string memory uid)
external
view
returns (BackUpApprovals[] memory)
{
return MemberApprovals[uid];
}
/**
* @dev editBackup - Function to edit individual backup approvals
* @param approvalId_ uint256 id to lookup Approval and edit
* @param _contractAddress address contractAddress of asset to save
* @param _tokenIds uint256 tokenId of asset
* @param _tokenAmount uint256 amount of specific token
* @param _tokenType string type of the token i.e. ERC20 | ERC721 | ERC1155
* @param _uid string of identifier for user in dApp
* @param _user address of the user of the dApp
*
*/
function editBackUp(
uint256 approvalId_,
address _contractAddress,
uint256 _tokenIds,
uint256 _tokenAmount,
string calldata _tokenType,
string memory _uid,
address _user
) external {
member memory _member = getMember(_uid);
checkUserHasMembership(_uid, _user);
BackUpApprovals[] storage _approvals = MemberApprovals[_member.uid];
for (uint256 i = 0; i < _approvals.length; i++) {
if (_approvals[i].approvalId == approvalId_) {
_approvals[i].token.tokenAddress = _contractAddress;
_approvals[i].token.tokenId = _tokenIds;
_approvals[i].token.tokensAllocated = _tokenAmount;
_approvals[i].token.tokenType = _tokenType;
}
}
IMembership(UserMembershipAddress[_uid]).redeemUpdate(_uid);
}
/**
* @dev editAllBackUp - Function to delete and add new approvals for backup
* @param _contractAddress address[] Ordered list of addresses for asset contracts
* @param _tokenIds uint256[] Ordered list of tokenIds to backup
* @param _backUpWallets address[] Ordered list of wallets that can be backups
* @param _tokenAmount uint256[] Ordered list of amounts of tokens to backup
* @param _tokenTypes string[] Ordered list of string tokenTypes i.e. ERC20 | ERC721 | ERC1155
* @param _memberUID string of identifier for user in dApp
* @param _user address of the user of the dApp
*
*
*/
function editAllBackUp(
address[] calldata _contractAddress,
uint256[] calldata _tokenIds,
address[] calldata _backUpWallets,
uint256[] calldata _tokenAmount,
string[] calldata _tokenTypes,
string calldata _memberUID,
address _user
) external {
checkUserHasMembership(_memberUID, _user);
deleteAllBackUp(_memberUID);
storeBackupAssetsApprovals(
_contractAddress,
_tokenIds,
_backUpWallets,
_tokenAmount,
_tokenTypes,
_memberUID,
_user,
true
);
}
/**
* @dev deleteAllBackUp - Function to delete all backup approvals
* @param _uid string of identifier for user in dApp
*
*/
function deleteAllBackUp(string memory _uid) public {
member memory _member = getMember(_uid);
delete MemberApprovals[_member.uid];
}
/**
* @notice checkUserHasMembership - Function to check if user has membership
* @param _uid string of identifier for user in dApp
* @param _user address of the user of the dApp
*
*/
function checkUserHasMembership(string memory _uid, address _user)
public
view
{
IBlacklist(IProtocolDirectory(directoryContract).getBlacklistContract())
.checkIfAddressIsBlacklisted(_user);
IMembership _membership = IMembership(UserMembershipAddress[_uid]);
bool _MembershipActive = _membership.checkIfMembershipActive(_uid);
if (_MembershipActive == false) {
revert(Errors.M_NOT_MEMBER);
} else {
MembershipStruct memory Membership = IMembership(
UserMembershipAddress[_uid]
).getMembership(_uid);
if (Membership.updatesPerYear <= 0) {
revert(Errors.M_NEED_TOP);
}
}
}
/**
* @dev Function set MembershipAddress for a Uid
* @param _uid string of identifier for user in dApp
* @param _Membership address of the user's associated membership contract
*
*/
function setIMembershipAddress(string memory _uid, address _Membership)
external
{
address factoryAddress = IProtocolDirectory(directoryContract)
.getMembershipFactory();
if (factoryAddress != msg.sender) {
revert(Errors.M_INVALID_ADDRESS);
}
UserMembershipAddress[_uid] = _Membership;
}
/**
* @dev Function to get MembershipAddress for a given Uid
* @param _uid string of identifier for user in dApp
*
*/
function getIMembershipAddress(string memory _uid)
external
view
returns (address)
{
return UserMembershipAddress[_uid];
}
/**
* @notice Function to check if backup wallet exists in the UID
* @param _uid string of dApp identifier for a user
* @param _backup address of the wallet checking exists
* Fails if not owner uid and backup address do not return a wallet
*
*/
function checkBackupandSenderofUID(string memory _uid, address _backup)
public
view
{
address[] memory wallets = members[_uid].wallets;
bool walletExists = false;
for (uint256 i = 0; i < wallets.length; i++) {
if (wallets[i] == _backup) {
walletExists = true;
}
}
address[] memory backupwallets = members[_uid].backUpWallets;
for (uint256 i = 0; i < backupwallets.length; i++) {
if (backupwallets[i] == _backup) {
walletExists = true;
}
}
if (walletExists == false) {
revert(Errors.M_NOT_OWNER);
}
}
}
/extensions/IERC1155MetadataURIUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)
pragma solidity ^0.8.0;
import "../IERC1155Upgradeable.sol";
/**
* @dev Interface of the optional ERC1155MetadataExtension interface, as defined
* in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].
*
* _Available since v3.1._
*/
interface IERC1155MetadataURIUpgradeable is IERC1155Upgradeable {
/**
* @dev Returns the URI for token type `id`.
*
* If the `\{id\}` substring is present in the URI, it must be replaced by
* clients with the actual token type ID.
*/
function uri(uint256 id) external view returns (string memory);
}
/IERC721Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165Upgradeable.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721Upgradeable is IERC165Upgradeable {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
/OwnableUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.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 anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing 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;
}
/ContextUpgradeable.sol
// 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;
}
/BeneficiaryStruct.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Structure to store different types of Beneficiary
* (ERC721, ERC1155, ERC20)
* @param beneficiaryAddress address for assets to go to
* @param beneficiaryName name of entity recieveing the assets
* @param isCharity boolean representing if Beneficiary is a charity
* because charities will be a recieve only address and cannot be
* expected to call a function to claim assets
*
*/
struct Beneficiary {
address beneficiaryAddress;
string beneficiaryName;
bool isCharity;
}
/IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
/IProtocolDirectory.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title Protocol Directory interface
*
* Use this interface in any contract that needs to find
* the contract location for commonly used Webacy contracts
*
*/
interface IProtocolDirectory {
/**
* @notice event for recording changes of contracts
*
*/
event AddressSet(bytes32 contractName, address indexed newContractAddress);
/**
* @notice get the address by a bytes32 location id
* @param _contractName a bytes32 string
*
*/
function getAddress(bytes32 _contractName) external returns (address);
/**
* @notice setAddress
* @param _contractName a bytes32 string
* @param _contractLocation an address of to entrypoint of protocol contract
*
*/
function setAddress(bytes32 _contractName, address _contractLocation)
external
returns (address);
/**
* @notice ssetStoreFactory
* @return address of protocol contract matching ASSET_STORE_FACTORY value
*
*/
function getAssetStoreFactory() external view returns (address);
/**
* @notice getMembershipFactory
* @return address of protocol contract matching MEMBERSHIP_FACTORY value
*
*/
function getMembershipFactory() external view returns (address);
/**
* @notice getRelayerContract
* @return address of protocol contract matching RELAYER_CONTRACT value
*
*/
function getRelayerContract() external view returns (address);
/**
* @notice getMemberContract
* @return address of protocol contract matching MEMBER_CONTRACT value
*
*/
function getMemberContract() external view returns (address);
/**
* @notice getBlacklistContract
* @return address of protocol contract matching BLACKLIST_CONTRACT value
*
*/
function getBlacklistContract() external view returns (address);
/**
* @notice getWhitelistContract
* @return address of protocol contract matching WHITELIST_CONTRACT value
*
*/
function getWhitelistContract() external view returns (address);
/**
* @notice getTransferPool
* @return address of protocol contract matching TRANSFER_POOL value
*
*/
function getTransferPool() external view returns (address);
/**
* @notice getChainlinkOperationsContract
* @return address of protocol contract matching CHAINLINK_OPERATIONS_CON value
*
*/
function getChainlinkOperationsContract() external view returns (address);
/**
* @dev setAssetStoreFactory
* @param _contractLocation address of the new contract location
* @return address of the updated item as a confirmation
*/
function setAssetStoreFactory(address _contractLocation)
external
returns (address);
/**
* @dev setMembershipFactory
* @param _contractLocation address of the new contract location
* @return address of the updated item as a confirmation
*/
function setMembershipFactory(address _contractLocation)
external
returns (address);
/**
* @dev setRelayerContract
* @param _contractLocation address of the new contract location
* @return address of the updated item as a confirmation
*/
function setRelayerContract(address _contractLocation)
external
returns (address);
/**
* @dev setMemberContract
* @param _contractLocation address of the new contract location
* @return address of the updated item as a confirmation
*/
function setMemberContract(address _contractLocation)
external
returns (address);
/**
* @dev setBlacklistContract
* @param _contractLocation address of the new contract location
* @return address of the updated item as a confirmation
*/
function setBlacklistContract(address _contractLocation)
external
returns (address);
/**
* @dev setWhitelistContract
* @param _contractLocation address of the new contract location
* @return address of the updated item as a confirmation
*/
function setWhitelistContract(address _contractLocation)
external
returns (address);
/**
* @dev setTransferPool
* @param _contractLocation address of the new contract location
* @return address of the updated item as a confirmation
*/
function setTransferPool(address _contractLocation)
external
returns (address);
/**
* @dev setChainlinkOperationsContract
* @param _contractLocation address of the new contract location
* @return address of the updated item as a confirmation
*/
function setChainlinkOperationsContract(address _contractLocation)
external
returns (address);
}
/IERC1155Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165Upgradeable.sol";
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*
* _Available since v3.1._
*/
interface IERC1155Upgradeable is IERC165Upgradeable {
/**
* @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the amount of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
external
view
returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}
/Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.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]
* ```
* 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. Equivalent to `reinitializer(1)`.
*/
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.
*
* `initializer` is equivalent to `reinitializer(1)`, so 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.
*
* 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.
*/
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.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
}
/TokenActions.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../structs/ApprovalsStruct.sol";
/**
* @title TokenActions Library
*
* Here contains the common functions for interacting with
* tokens for importing in different parts of the ecosystem
* to save space hopefully in other places
*/
library TokenActions {
/**
* @notice internal function for sending erc20s
*
* creating this function to save space while sending coins
* to charities and for beneficiaries
*
* @param _approval of the Approvals type in storage
*/
function sendERC20(Approvals storage _approval) internal {
IERC20 ERC20 = IERC20(_approval.token.tokenAddress);
/// @notice gather the preset approved token amount for this beneficiary
uint256 _tokenAmount = (_approval.approvedTokenAmount);
/// @notice If the allowance for the member by claimer is greater than the _tokenAmount
/// take the allowance for the beneficiary that called this function: why ?
if (
ERC20.allowance(_approval.approvedWallet, msg.sender) > _tokenAmount
) {
_tokenAmount = ERC20.allowance(
_approval.approvedWallet,
msg.sender
);
}
ERC20.transferFrom(
_approval.approvedWallet,
_approval.beneficiary.beneficiaryAddress,
_tokenAmount
);
_approval.claimed = true;
}
/**
*
* @dev checkAssetContract
* @param _contractAddress contract of the token we are checking
* @param _tokenType the given tokentype as a string ERC721 etc...
*
* Checks if the assets passed through are assets of the determined type or not.
* it can handle upgradable versions as well if needed
*
*/
function checkAssetContract(
address _contractAddress,
string memory _tokenType
) public view {
if (
(keccak256(abi.encodePacked((_tokenType))) ==
keccak256(abi.encodePacked(("ERC721"))))
) {
require(
(IERC721Upgradeable(_contractAddress).supportsInterface(
type(IERC721Upgradeable).interfaceId
) ||
IERC721(_contractAddress).supportsInterface(
type(IERC721).interfaceId
)),
"Does not support a Supported ERC721 Interface"
);
} else if (
keccak256(abi.encodePacked((_tokenType))) ==
keccak256(abi.encodePacked(("ERC20")))
) {
require(
(IERC20(_contractAddress).totalSupply() >= 0 ||
IERC20Upgradeable(_contractAddress).totalSupply() >= 0),
"Is not an ERC20 Contract Address"
);
} else if (
keccak256(abi.encodePacked((_tokenType))) ==
keccak256(abi.encodePacked(("ERC1155")))
) {
require(
(IERC1155Upgradeable(_contractAddress).supportsInterface(
type(IERC1155Upgradeable).interfaceId
) ||
IERC1155(_contractAddress).supportsInterface(
type(IERC1155).interfaceId
)),
"Does not support a Supported ERC1155 Interface"
);
} else {
revert("Invalid token type");
}
}
}
/ApprovalsStruct.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./MemberStruct.sol";
import "./TokenStruct.sol";
import "./BeneficiaryStruct.sol";
/**
* @dev Approvals Struct
* @param Member member struct with information on the user
* @param approvedWallet address of wallet approved
* @param beneficiary Beneficiary struct holding recipient info
* @param token Token struct holding specific info on the asset
* @param dateApproved uint256 timestamp of the approval creation
* @param claimed bool representing status if asset was claimed
* @param active bool representing if the claim period has begun
* @param approvalId uint256 id of the specific approval in the assetstore
* @param claimExpiryTime uint256 timestamp of when claim period ends
* @param approvedTokenAmount uint256 magnitude of tokens to claim by this approval
*
*/
struct Approvals {
member Member;
address approvedWallet;
Beneficiary beneficiary;
Token token;
uint256 dateApproved;
bool claimed;
bool active;
uint256 approvalId;
uint256 claimExpiryTime;
uint256 approvedTokenAmount;
}
/MembershipPlansStruct.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev membershipPlan struct
*
* @param membershipDuration uint256 length of time membership is good for
* @param costOfMembership uint256 cost in wei of gaining membership
* @param updatesPerYear uint256 how many updates can the membership be updated in a year by user
* @param nftCollection address pass as null address if it is not for creating specific
* membership plan for a specific NFT Collection
* @param membershipId uint256 id for the new membership to lookup by
* @param active bool status if the membership can be used to create new contracts
*/
struct membershipPlan {
uint256 membershipDuration;
uint256 costOfMembership;
uint256 updatesPerYear;
address nftCollection;
uint256 membershipId;
bool active;
}
/IMembership.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../structs/MembershipPlansStruct.sol";
import "../structs/MembershipStruct.sol";
/**
* @title Interface for IMembership
* @dev to interact with Membership
*/
interface IMembership {
/**
* @dev Function to check of membership is active for the user
* @param _uid string identifier of user across dApp
* @return bool boolean representing if the membership has expired
*
*/
function checkIfMembershipActive(string memory _uid)
external
view
returns (bool);
/**
* @dev renewmembership Function to renew membership of the user
* @param _uid string identifier of the user renewing membership
*
*
*/
function renewMembership(string memory _uid) external payable;
/**
* @dev renewmembershipNFT - Function to renew membership for users that have NFTs
* @param _contractAddress address of nft to approve renewing
* @param _NFTType string type of NFT i.e. ERC20 | ERC1155 | ERC721
* @param tokenId uint256 tokenId being protected
* @param _uid string identifier of the user renewing membership
*
*/
function renewMembershipNFT(
address _contractAddress,
string memory _NFTType,
uint256 tokenId,
string memory _uid
) external payable;
/**
* @dev Function to top up updates
* @param _uid string identifier of the user across the dApp
*
*/
function topUpUpdates(string memory _uid) external payable;
/**
* @notice changeMembershipPlan
* Ability to change membership plan for a member given a membership ID and member UID.
* It is a payable function given the membership cost for the membership plan.
*
* @param membershipId uint256 id of membership plan changing to
* @param _uid string identifier of the user
*/
function changeMembershipPlan(uint256 membershipId, string memory _uid)
external
payable;
/**
* @notice changeMembershipPlanNFT - Function to change membership plan to an NFT based plan
* @param membershipId uint256 id of the membershipPlan changing to
* @param _contractAddress address of the NFT granting the membership
* @param _NFTType string type of NFT i.e. ERC721 | ERC1155
* @param tokenId uint256 tokenId of the nft to verify ownership
* @param _uid string identifier of the user across the dApp
*
*/
function changeMembershipPlanNFT(
uint256 membershipId,
address _contractAddress,
string memory _NFTType,
uint256 tokenId,
string memory _uid
) external payable;
/**
* @notice redeemUpdate
* @param _uid string identifier of the user across the dApp
*
* Function to claim that a membership has been updated
*/
function redeemUpdate(string memory _uid) external;
/**
* @notice Function to return membership information of the user
* @param _uid string identifier of user across dApp
* @return MembershipStruct containing information of the specific user's membership
*
*/
function getMembership(string memory _uid)
external
view
returns (MembershipStruct memory);
}
/IMember.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../structs/MemberStruct.sol";
import "../structs/BackupApprovalStruct.sol";
/**
* @title Interface for IMember
* @dev to interact with Member Contracts
*
*/
interface IMember {
/**
* @dev createMember
* @param uid centrally stored id for user
* @param _walletAddress walletAddress to add wallet and check blacklist
*
* Allows to create a member onChain with a unique UID passed.
* Will revert if the _walletAddress passed in is blacklisted
*
*/
function createMember(string calldata uid, address _walletAddress) external;
/**
* @dev getMember
* @param uid string for centrally located identifier
* Allows to get member information stored onChain with a unique UID passed.
* @return member struct for a given uid
*
*/
function getMember(string memory uid) external view returns (member memory);
/**
* @dev getAllMembers
* Allows to get all member information stored onChain
* @return allMembers a list of member structs
*
*/
function getAllMembers() external view returns (member[] memory);
/**
* @dev addWallet - Allows to add Wallet to the user
* @param uid string for dApp user identifier
* @param _wallet address wallet being added for given user
* @param _primary bool whether or not this new wallet is the primary wallet
*
*
*/
function addWallet(
string calldata uid,
address _wallet,
bool _primary
) external;
/**
* @dev getWallets
* Allows to get all wallets of the user
* @param uid string for dApp user identifier
* @return address[] list of wallets
*
*/
function getWallets(string calldata uid)
external
view
returns (address[] memory);
/**
* @dev deleteWallet - Allows to delete wallets of a specific user
* @param uid string for dApp user identifier
* @param _walletIndex uint256 which index does the wallet exist in the member wallet list
*
*/
function deleteWallet(string calldata uid, uint256 _walletIndex) external;
/**
* @dev getPrimaryWallets
* Allows to get primary wallet of the user
* @param uid string for dApp user identifier
* @return address of the primary wallet per user
*
*/
function getPrimaryWallet(string memory uid)
external
view
returns (address);
/**
* @dev setPrimaryWallet
* Allows to set a specific wallet as the primary wallet
* @param uid string for dApp user identifier
* @param _walletIndex uint256 which index does the wallet exist in the member wallet list
*
*/
function setPrimaryWallet(string calldata uid, uint256 _walletIndex)
external;
/**
* @notice Function to check if wallet exists in the UID
* @param _uid string of dApp identifier for a user
* @param _user address of the user checking exists
* Fails if not owner uid and user address do not return a wallet
*
*/
function checkUIDofSender(string memory _uid, address _user) external view;
/**
* @dev checkIfUIDExists
* Check if user exists for specific wallet address already internal function
* @param _walletAddress wallet address of the user
* @return _exists - A boolean if user exists or not
*
*/
function checkIfUIDExists(address _walletAddress)
external
view
returns (bool _exists);
/**
* @dev getUID
* Allows user to pass walletAddress and return UID
* @param _walletAddress get the UID of the user's if their wallet address is present
* @return string of the ID used in the dApp to identify they user
*
*/
function getUID(address _walletAddress)
external
view
returns (string memory);
/**
* @dev getBackupApprovals - function to return all backupapprovals for a specific UID
* @param uid string of identifier for user in dApp
* @return BackUpApprovals[] list of BackUpApprovals struct
*
*/
function getBackupApprovals(string memory uid)
external
view
returns (BackUpApprovals[] memory);
/**
* @dev storeBackupAssetsApprovals - Function to store All Types Approvals by the user for backup
*
* @param _contractAddress address[] Ordered list of contract addresses for assets
* @param _tokenIds uint256[] Ordered list of tokenIds associated with contract addresses
* @param _backUpWallets address[] Ordered list of wallet addresses to backup assets
* @param _tokenAmount uint256[] Ordered list of amounts per asset contract and token id to protext
* @param _tokenTypes string[] Ordered list of strings i.e. ERC20 | ERC721 | ERC1155
* @param _memberUID string for dApp user identifier
* @param _userAddress address of the user
* @param _super bool true if function is being called from a parent function. false if directly
*
*/
function storeBackupAssetsApprovals(
address[] calldata _contractAddress,
uint256[] calldata _tokenIds,
address[] calldata _backUpWallets,
uint256[] calldata _tokenAmount,
string[] calldata _tokenTypes,
string calldata _memberUID,
address _userAddress,
bool _super
) external;
/**
* @dev executePanic - Public function to transfer assets from one user to another
* @param _backUpWallet wallet to panic send assets to
* @param _memberUID uid of the user's assets being moved
*
*/
function executePanic(address _backUpWallet, string memory _memberUID)
external;
/**
* @dev editBackup - Function to edit individual backup approvals
* @param approvalId_ uint256 id to lookup Approval and edit
* @param _contractAddress address contractAddress of asset to save
* @param _tokenIds uint256 tokenId of asset
* @param _tokenAmount uint256 amount of specific token
* @param _tokenType string type of the token i.e. ERC20 | ERC721 | ERC1155
* @param _uid string of identifier for user in dApp
* @param _user address of the user of the dApp
*
*/
function editBackUp(
uint256 approvalId_,
address _contractAddress,
uint256 _tokenIds,
uint256 _tokenAmount,
string calldata _tokenType,
string memory _uid,
address _user
) external;
/**
* @dev editAllBackUp - Function to delete and add new approvals for backup
* @param _contractAddress address[] Ordered list of addresses for asset contracts
* @param _tokenIds uint256[] Ordered list of tokenIds to backup
* @param _backUpWallets address[] Ordered list of wallets that can be backups
* @param _tokenAmount uint256[] Ordered list of amounts of tokens to backup
* @param _tokenTypes string[] Ordered list of string tokenTypes i.e. ERC20 | ERC721 | ERC1155
* @param _memberUID string of identifier for user in dApp
* @param _user address of the user of the dApp
*
*
*/
function editAllBackUp(
address[] calldata _contractAddress,
uint256[] calldata _tokenIds,
address[] calldata _backUpWallets,
uint256[] calldata _tokenAmount,
string[] calldata _tokenTypes,
string calldata _memberUID,
address _user
) external;
/**
* @dev deleteAllBackUp - Function to delete all backup approvals
* @param _uid string of identifier for user in dApp
*
*/
function deleteAllBackUp(string memory _uid) external;
/**
* @notice checkUserHasMembership - Function to check if user has membership
* @param _uid string of identifier for user in dApp
* @param _user address of the user of the dApp
*
*/
function checkUserHasMembership(string memory _uid, address _user)
external
view;
/**
* @dev Function set MembershipAddress for a Uid
* @param _uid string of identifier for user in dApp
* @param _Membership address of the user's associated membership contract
*
*/
function setIMembershipAddress(string memory _uid, address _Membership)
external;
/**
* @dev Function to get MembershipAddress for a given Uid
* @param _uid string of identifier for user in dApp
*
*/
function getIMembershipAddress(string memory _uid)
external
view
returns (address);
/**
* @notice checkIfWalletHasNFT
* verify if the user has specific nft 1155 or 721
* @param _contractAddress address of asset contract
* @param _NFTType string i.e. ERC721 | ERC1155
* @param tokenId uint256 tokenId checking for ownership
* @param userAddress address address to verify ownership of
* Fails if not owner
*/
function checkIfWalletHasNFT(
address _contractAddress,
string memory _NFTType,
uint256 tokenId,
address userAddress
) external view;
/**
* @dev addBackUpWallet - Allows to add backUp Wallets to the user
* @param uid string for dApp user identifier
* @param _wallets addresses of wallets being added for given user
*
*
*/
function addBackupWallet(string calldata uid, address[] memory _wallets)
external;
/**
* @dev getBackupWallets - Returns backup Wallets for the specific UID
* @param uid string for dApp user identifier
*
*/
function getBackupWallets(string calldata uid)
external
view
returns (address[] memory);
}
/IERC1155.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*
* _Available since v3.1._
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the amount of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
external
view
returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}
/ReentrancyGuardUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuardUpgradeable is Initializable {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @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;
}
/MemberStruct.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Member Structure stores all member information
* @param uid string For storing UID that cross references UID from DB for loading off-chain data
* @param dateCreated uint256 timestamp of creation of User
* @param wallets address[] Maintains an array of backUpWallets of the User
* @param primaryWallet uint256 index of where in the wallets array the primary wallet exists
*/
struct member {
string uid;
uint256 dateCreated;
address[] wallets;
address[] backUpWallets;
uint256 primaryWallet;
}
/IMembershipFactory.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../structs/MembershipPlansStruct.sol";
/**
* @title Interface for IMembershipFactory to interact with Membership Factory
*
*/
interface IMembershipFactory {
/**
* @dev Function to createMembership by deploying membership contract for a specific member
* @param uid string identifier of a user across the dApp
* @param _membershipId uint256 id of the chosen membership plan
* @param _walletAddress address of the user creating the membership
*
*/
function createMembership(
string calldata uid,
uint256 _membershipId,
address _walletAddress
) external payable;
/**
* @dev Function to create Membership for a member with supporting NFTs
* @param uid string identifier of the user across the dApp
* @param _contractAddress address of the NFT granting membership
* @param _NFTType string type of NFT for granting membership i.e. ERC721 | ERC1155
* @param tokenId uint256 tokenId of the owned nft to verify ownership
* @param _walletAddress address of the user creating a membership with their nft
* @param _membershipId membershipId of the plan
*
*/
function createMembershipSupportingNFT(
string calldata uid,
address _contractAddress,
string memory _NFTType,
uint256 tokenId,
address _walletAddress,
uint256 _membershipId
) external payable;
/**
* @dev function to get all membership plans
* @return membershipPlan[] a list of all membershipPlans on the contract
*
*/
function getAllMembershipPlans()
external
view
returns (membershipPlan[] memory);
/**
* @dev function to getCostOfMembershipPlan
* @param _membershipId uint256 id of specific plan to retrieve
* @return membershipPlan struct
*
*/
function getMembershipPlan(uint256 _membershipId)
external
view
returns (membershipPlan memory);
/**
* @dev Function to get updates per year cost
* @return uint256 cost of updating membership in wei
*
*/
function getUpdatesPerYearCost() external view returns (uint256);
/**
* @dev Function to set new membership plan for user
* @param _uid string identifing the user across the dApp
* @param _membershipId uint256 id of the membership for the user
*
*/
function setUserForMembershipPlan(string memory _uid, uint256 _membershipId)
external;
/**
* @dev Function to transfer eth to specific pool
*
*/
function transferToPool() external payable;
/**
* @dev Function to return users membership contract address
* @param _uid string identifier of a user across the dApp
* @return address of the membership contract if exists for the _uid
*
*/
function getUserMembershipAddress(string memory _uid)
external
view
returns (address);
}
/IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
/TokenStruct.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Token struct
*
* @param tokenId uint256 specific tokenId for the asset
* @param tokenAddress address of the contract for this asset
* @param tokenType string representing asset type i.e. ERC721 | ERC20 | ERC1155
* @param tokensAllocated uint256 number representing how many tokens as a %'s to
* attach to a given approval or other directive
*/
struct Token {
uint256 tokenId;
address tokenAddress;
string tokenType;
uint256 tokensAllocated;
}
/IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
/ERC1155Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/ERC1155.sol)
pragma solidity ^0.8.0;
import "./IERC1155Upgradeable.sol";
import "./IERC1155ReceiverUpgradeable.sol";
import "./extensions/IERC1155MetadataURIUpgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../utils/ContextUpgradeable.sol";
import "../../utils/introspection/ERC165Upgradeable.sol";
import "../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the basic standard multi-token.
* See https://eips.ethereum.org/EIPS/eip-1155
* Originally based on code by Enjin: https://github.com/enjin/erc-1155
*
* _Available since v3.1._
*/
contract ERC1155Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC1155Upgradeable, IERC1155MetadataURIUpgradeable {
using AddressUpgradeable for address;
// Mapping from token ID to account balances
mapping(uint256 => mapping(address => uint256)) private _balances;
// Mapping from account to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
// Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json
string private _uri;
/**
* @dev See {_setURI}.
*/
function __ERC1155_init(string memory uri_) internal onlyInitializing {
__ERC1155_init_unchained(uri_);
}
function __ERC1155_init_unchained(string memory uri_) internal onlyInitializing {
_setURI(uri_);
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {
return
interfaceId == type(IERC1155Upgradeable).interfaceId ||
interfaceId == type(IERC1155MetadataURIUpgradeable).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC1155MetadataURI-uri}.
*
* This implementation returns the same URI for *all* token types. It relies
* on the token type ID substitution mechanism
* https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
*
* Clients calling this function must replace the `\{id\}` substring with the
* actual token type ID.
*/
function uri(uint256) public view virtual override returns (string memory) {
return _uri;
}
/**
* @dev See {IERC1155-balanceOf}.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {
require(account != address(0), "ERC1155: address zero is not a valid owner");
return _balances[id][account];
}
/**
* @dev See {IERC1155-balanceOfBatch}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(address[] memory accounts, uint256[] memory ids)
public
view
virtual
override
returns (uint256[] memory)
{
require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");
uint256[] memory batchBalances = new uint256[](accounts.length);
for (uint256 i = 0; i < accounts.length; ++i) {
batchBalances[i] = balanceOf(accounts[i], ids[i]);
}
return batchBalances;
}
/**
* @dev See {IERC1155-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC1155-isApprovedForAll}.
*/
function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {
return _operatorApprovals[account][operator];
}
/**
* @dev See {IERC1155-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) public virtual override {
require(
from == _msgSender() || isApprovedForAll(from, _msgSender()),
"ERC1155: caller is not token owner nor approved"
);
_safeTransferFrom(from, to, id, amount, data);
}
/**
* @dev See {IERC1155-safeBatchTransferFrom}.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) public virtual override {
require(
from == _msgSender() || isApprovedForAll(from, _msgSender()),
"ERC1155: caller is not token owner nor approved"
);
_safeBatchTransferFrom(from, to, ids, amounts, data);
}
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function _safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: transfer to the zero address");
address operator = _msgSender();
uint256[] memory ids = _asSingletonArray(id);
uint256[] memory amounts = _asSingletonArray(amount);
_beforeTokenTransfer(operator, from, to, ids, amounts, data);
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
unchecked {
_balances[id][from] = fromBalance - amount;
}
_balances[id][to] += amount;
emit TransferSingle(operator, from, to, id, amount);
_afterTokenTransfer(operator, from, to, ids, amounts, data);
_doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
}
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function _safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
require(to != address(0), "ERC1155: transfer to the zero address");
address operator = _msgSender();
_beforeTokenTransfer(operator, from, to, ids, amounts, data);
for (uint256 i = 0; i < ids.length; ++i) {
uint256 id = ids[i];
uint256 amount = amounts[i];
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
unchecked {
_balances[id][from] = fromBalance - amount;
}
_balances[id][to] += amount;
}
emit TransferBatch(operator, from, to, ids, amounts);
_afterTokenTransfer(operator, from, to, ids, amounts, data);
_doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
}
/**
* @dev Sets a new URI for all token types, by relying on the token type ID
* substitution mechanism
* https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
*
* By this mechanism, any occurrence of the `\{id\}` substring in either the
* URI or any of the amounts in the JSON file at said URI will be replaced by
* clients with the token type ID.
*
* For example, the `https://token-cdn-domain/\{id\}.json` URI would be
* interpreted by clients as
* `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`
* for token type ID 0x4cce0.
*
* See {uri}.
*
* Because these URIs cannot be meaningfully represented by the {URI} event,
* this function emits no events.
*/
function _setURI(string memory newuri) internal virtual {
_uri = newuri;
}
/**
* @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function _mint(
address to,
uint256 id,
uint256 amount,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: mint to the zero address");
address operator = _msgSender();
uint256[] memory ids = _asSingletonArray(id);
uint256[] memory amounts = _asSingletonArray(amount);
_beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
_balances[id][to] += amount;
emit TransferSingle(operator, address(0), to, id, amount);
_afterTokenTransfer(operator, address(0), to, ids, amounts, data);
_doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);
}
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function _mintBatch(
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {
require(to != address(0), "ERC1155: mint to the zero address");
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
address operator = _msgSender();
_beforeTokenTransfer(operator, address(0), to, ids, amounts, data);
for (uint256 i = 0; i < ids.length; i++) {
_balances[ids[i]][to] += amounts[i];
}
emit TransferBatch(operator, address(0), to, ids, amounts);
_afterTokenTransfer(operator, address(0), to, ids, amounts, data);
_doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
}
/**
* @dev Destroys `amount` tokens of token type `id` from `from`
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `from` must have at least `amount` tokens of token type `id`.
*/
function _burn(
address from,
uint256 id,
uint256 amount
) internal virtual {
require(from != address(0), "ERC1155: burn from the zero address");
address operator = _msgSender();
uint256[] memory ids = _asSingletonArray(id);
uint256[] memory amounts = _asSingletonArray(amount);
_beforeTokenTransfer(operator, from, address(0), ids, amounts, "");
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
unchecked {
_balances[id][from] = fromBalance - amount;
}
emit TransferSingle(operator, from, address(0), id, amount);
_afterTokenTransfer(operator, from, address(0), ids, amounts, "");
}
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
*/
function _burnBatch(
address from,
uint256[] memory ids,
uint256[] memory amounts
) internal virtual {
require(from != address(0), "ERC1155: burn from the zero address");
require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
address operator = _msgSender();
_beforeTokenTransfer(operator, from, address(0), ids, amounts, "");
for (uint256 i = 0; i < ids.length; i++) {
uint256 id = ids[i];
uint256 amount = amounts[i];
uint256 fromBalance = _balances[id][from];
require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
unchecked {
_balances[id][from] = fromBalance - amount;
}
}
emit TransferBatch(operator, from, address(0), ids, amounts);
_afterTokenTransfer(operator, from, address(0), ids, amounts, "");
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC1155: setting approval status for self");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning, as well as batched variants.
*
* The same hook is called on both single and batched variants. For single
* transfers, the length of the `ids` and `amounts` arrays will be 1.
*
* Calling conditions (for each `id` and `amount` pair):
*
* - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* of token type `id` will be transferred to `to`.
* - When `from` is zero, `amount` tokens of token type `id` will be minted
* for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
* will be burned.
* - `from` and `to` are never both zero.
* - `ids` and `amounts` have the same, non-zero length.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {}
/**
* @dev Hook that is called after any token transfer. This includes minting
* and burning, as well as batched variants.
*
* The same hook is called on both single and batched variants. For single
* transfers, the length of the `id` and `amount` arrays will be 1.
*
* Calling conditions (for each `id` and `amount` pair):
*
* - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* of token type `id` will be transferred to `to`.
* - When `from` is zero, `amount` tokens of token type `id` will be minted
* for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
* will be burned.
* - `from` and `to` are never both zero.
* - `ids` and `amounts` have the same, non-zero length.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal virtual {}
function _doSafeTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) private {
if (to.isContract()) {
try IERC1155ReceiverUpgradeable(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
if (response != IERC1155ReceiverUpgradeable.onERC1155Received.selector) {
revert("ERC1155: ERC1155Receiver rejected tokens");
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC1155: transfer to non ERC1155Receiver implementer");
}
}
}
function _doSafeBatchTransferAcceptanceCheck(
address operator,
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) private {
if (to.isContract()) {
try IERC1155ReceiverUpgradeable(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (
bytes4 response
) {
if (response != IERC1155ReceiverUpgradeable.onERC1155BatchReceived.selector) {
revert("ERC1155: ERC1155Receiver rejected tokens");
}
} catch Error(string memory reason) {
revert(reason);
} catch {
revert("ERC1155: transfer to non ERC1155Receiver implementer");
}
}
}
function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {
uint256[] memory array = new uint256[](1);
array[0] = element;
return array;
}
/**
* @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[47] private __gap;
}
/MembershipStruct.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Membership Structure stores membership data of a member
* @param user address of the user who has a membership
* @param membershipStarted uint256 timestamp of when the membership began
* @param membershipEnded uint256 timestamp of when membership expires
* @param payedAmount uint256 amount in wei paid for the membership
* @param active bool status of the user's membership
* @param membershipId uint256 id of the membershipPlan this was created for
* @param updatesPerYear uint256 how many updates per year left for the user
* @param nftCollection address of the nft collection granting a membership or address(0)
* @param uid string of the identifier of the user across the dApp
*
*/
struct MembershipStruct {
address user;
uint256 membershipStarted;
uint256 membershipEnded;
uint256 payedAmount;
bool active;
uint256 membershipId;
uint256 updatesPerYear;
address nftCollection;
string uid;
}
/Errors.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title Errors library
* @notice Defines the error messages emitted by the different contracts of the Webacy
* @dev inspired by Aave's https://github.com/aave/protocol-v2/blob/master/contracts/protocol/libraries/helpers/Errors.sol
* @dev Error messages prefix glossary:
* - ASF = AssetStoreFactory
* - MF = MembershipFactory
* - BL = Blacklist
* - WL = Whitelist
* - AS = AssetStore
* - CO = ChainlinkOperations
* - M = Member
* - MS = Membership
* - PD = ProtocolDirectory
* - RC = RelayerContract
*/
library Errors {
// AssetStoreFactory Errors
string public constant ASF_NO_MEMBERSHIP_CONTRACT = "1"; // "User does not have a membership contract deployed"
string public constant ASF_HAS_AS = "2"; // "User has an AssetStore"
// MembershipFactory Errors
string public constant MF_HAS_MEMBERSHIP_CONTRACT = "3"; // "User already has a membership contract"
string public constant MF_INACTIVE_PLAN = "4"; // "Membership plan is no longer active"
string public constant MF_NEED_MORE_DOUGH = "5"; // "Membership cost send is not sufficient"
// Blacklist Errors
string public constant BL_BLACKLISTED = "6"; // "Address is blacklisted"
// AssetStore Errors
string public constant AS_NO_MEMBERSHIP = "7"; // "AssetsStore: User does not have a membership"
string public constant AS_USER_DNE = "8"; // "User does not exist"
string public constant AS_ONLY_RELAY = "9"; // "Only relayer contract can call this"
string public constant AS_ONLY_CHAINLINK_OPS = "10"; // "Only chainlink operations contract can call this"
string public constant AS_DIFF_LENGTHS = "11"; // "Lengths of parameters need to be equal"
string public constant AS_ONLY_PRIMARY_WALLET = "12"; // "Only the primary wallet can approve to store assets"
string public constant AS_INVALID_TOKEN_RANGE = "13"; // "tokenAmount can only range from 0-100 percentage"
string public constant AS_ONLY_BENEFICIARY = "14"; // "Only the designated beneficiary can claim assets"
string public constant AS_NO_APPROVALS = "15"; // "No Approvals found"
string public constant AS_NOT_CHARITY = "16"; // "is not charity"
string public constant AS_INVALID_APPROVAL = "17"; // "Approval should not be active and should not be claimed in order to make changes"
string public constant AS_NEED_TOP = "18"; // "User does not have sufficient topUp Updates in order to store approvals"
// Member Errors
string public constant M_NOT_OWNER = "19"; // "Member UID does not own this wallet Address"
string public constant M_NOT_HOLDER = "20"; // "The user does not own a token of the supporting NFT Collection"
string public constant M_USER_DNE = "21"; // "No user exists"
string public constant M_UID_DNE = "22"; // "No UID found"
string public constant M_INVALID_BACKUP = "23"; // "BackUp Wallet specified is not the users backup Wallet"
string public constant M_NOT_MEMBER = "24"; // "Member: User does not have a membership"
string public constant M_EMPTY_UID = "25"; // "UID is empty"
string public constant M_PRIM_WALLET = "26"; // "You cannot delete your primary wallet"
string public constant M_ALREADY_PRIM = "27"; // "Current Wallet is already the primary Wallet"
string public constant M_DIFF_LENGTHS = "28"; // "Lengths of parameters need to be equal"
string public constant M_BACKUP_FIRST = "29"; // "User should backup assets prior to executing panic button"
string public constant M_NEED_TOP = "30"; // "User does not have sufficient topUp Updates in order to store approvals"
string public constant M_INVALID_ADDRESS = "31"; // "Membership Error: User should have its deployed Membership Address"
string public constant M_USER_MUST_WALLET = "32"; //"User should have a primary wallet prior to adding a backup wallet"
string public constant M_USER_EXISTS = "33"; // User with UID already exists
// Membership Errors
string public constant MS_NEED_MORE_DOUGH = "34"; // "User needs to send sufficient amount to topUp"
string public constant MS_INACTIVE = "35"; // "Membership inactive"
// RelayerContract Errors
string public constant RC_UNAUTHORIZED = "36"; // "Only relayer can invoke this function"
}
/ERC165Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165Upgradeable.sol";
import "../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {
function __ERC165_init() internal onlyInitializing {
}
function __ERC165_init_unchained() internal onlyInitializing {
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165Upgradeable).interfaceId;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
/AddressUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.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
* ====
*
* [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://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
/IERC1155ReceiverUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165Upgradeable.sol";
/**
* @dev _Available since v3.1._
*/
interface IERC1155ReceiverUpgradeable is IERC165Upgradeable {
/**
* @dev Handles the receipt of a single ERC1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param operator The address which initiated the transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param id The ID of the token being transferred
* @param value The amount of tokens being transferred
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
/**
* @dev Handles the receipt of a multiple ERC1155 token types. This function
* is called at the end of a `safeBatchTransferFrom` after the balances have
* been updated.
*
* NOTE: To accept the transfer(s), this must return
* `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
* (i.e. 0xbc197c81, or its own function selector).
*
* @param operator The address which initiated the batch transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param ids An array containing ids of each token being transferred (order and length must match values array)
* @param values An array containing amounts of each token being transferred (order and length must match ids array)
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}
/IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
/IERC165Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165Upgradeable {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
/BackupApprovalStruct.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./MemberStruct.sol";
import "./TokenStruct.sol";
import "./BeneficiaryStruct.sol";
/**
* @dev BackUpApprovals struct
*
* @param Member member struct of information for the user
* @param approvedWallet address wallet approving the assets
* @param backUpWallet address[] wallet approved to recieve assets
* @param token Token struct with information about the asset backed up
* @param dateApproved uint256 timestamp of when the approval came in
* @param claimed bool status of the approval if it was claimed
* @param approvalId uint256 id of the specific approval for this asset
*/
struct BackUpApprovals {
member Member;
address approvedWallet;
address[] backUpWallet;
Token token;
uint256 dateApproved;
bool claimed;
uint256 approvalId;
}
/IBlacklist.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title IBlacklist
* @dev To interact with Blacklist Users Contracts
*/
interface IBlacklist {
/**
* @dev checkIfAddressIsBlacklisted
* @param _user address of wallet to check is blacklisted
*
*/
function checkIfAddressIsBlacklisted(address _user) external view;
/**
* @dev Function to get blacklisted addresses
* @return blackListAddresses address[]
*
*/
function getBlacklistedAddresses() external view returns (address[] memory);
}
Compiler Settings
{"viaIR":true,"remappings":[],"optimizer":{"runs":200,"enabled":true},"metadata":{"bytecodeHash":"ipfs"},"libraries":{"contracts/libraries/TokenActions.sol:TokenActions":"0xf5a5b6a677ff77c22c856a2b794bdc5534806c97"},"evmVersion":"london","compilationTarget":{"contracts/Member.sol":"Member"}}
Contract ABI
[{"type":"event","name":"BackUpApprovalsEvent","inputs":[{"type":"string","name":"uid","internalType":"string","indexed":false},{"type":"address","name":"approvedWallet","internalType":"address","indexed":false},{"type":"address[]","name":"backupaddress","internalType":"address[]","indexed":false},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":false},{"type":"address","name":"tokenAddress","internalType":"address","indexed":false},{"type":"string","name":"tokenType","internalType":"string","indexed":false},{"type":"uint256","name":"tokensAllocated","internalType":"uint256","indexed":false},{"type":"uint256","name":"dateApproved","internalType":"uint256","indexed":false},{"type":"bool","name":"claimed","internalType":"bool","indexed":false},{"type":"uint256","name":"approvalId","internalType":"uint256","indexed":false},{"type":"address","name":"claimedWallet","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"type":"uint8","name":"version","internalType":"uint8","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"memberCreated","inputs":[{"type":"string","name":"uid","internalType":"string","indexed":false},{"type":"uint256","name":"dateCreated","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"walletUpdated","inputs":[{"type":"string","name":"uid","internalType":"string","indexed":false},{"type":"uint256","name":"dateCreated","internalType":"uint256","indexed":false},{"type":"address[]","name":"backUpWallets","internalType":"address[]","indexed":false},{"type":"address[]","name":"wallets","internalType":"address[]","indexed":false},{"type":"uint256","name":"primaryWallet","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addBackupWallet","inputs":[{"type":"string","name":"uid","internalType":"string"},{"type":"address[]","name":"_wallets","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addWallet","inputs":[{"type":"string","name":"uid","internalType":"string"},{"type":"address","name":"_wallet","internalType":"address"},{"type":"bool","name":"_primary","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"uid","internalType":"string"},{"type":"uint256","name":"dateCreated","internalType":"uint256"},{"type":"uint256","name":"primaryWallet","internalType":"uint256"}],"name":"allMembers","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[],"name":"checkBackupandSenderofUID","inputs":[{"type":"string","name":"_uid","internalType":"string"},{"type":"address","name":"_backup","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"_exists","internalType":"bool"}],"name":"checkIfUIDExists","inputs":[{"type":"address","name":"_walletAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[],"name":"checkIfWalletHasNFT","inputs":[{"type":"address","name":"_contractAddress","internalType":"address"},{"type":"string","name":"_NFTType","internalType":"string"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"address","name":"userAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[],"name":"checkUIDofSender","inputs":[{"type":"string","name":"_uid","internalType":"string"},{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[],"name":"checkUserHasMembership","inputs":[{"type":"string","name":"_uid","internalType":"string"},{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"createMember","inputs":[{"type":"string","name":"uid","internalType":"string"},{"type":"address","name":"_walletAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deleteAllBackUp","inputs":[{"type":"string","name":"_uid","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deleteWallet","inputs":[{"type":"string","name":"uid","internalType":"string"},{"type":"uint256","name":"_walletIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"directoryContract","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"editAllBackUp","inputs":[{"type":"address[]","name":"_contractAddress","internalType":"address[]"},{"type":"uint256[]","name":"_tokenIds","internalType":"uint256[]"},{"type":"address[]","name":"_backUpWallets","internalType":"address[]"},{"type":"uint256[]","name":"_tokenAmount","internalType":"uint256[]"},{"type":"string[]","name":"_tokenTypes","internalType":"string[]"},{"type":"string","name":"_memberUID","internalType":"string"},{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"editBackUp","inputs":[{"type":"uint256","name":"approvalId_","internalType":"uint256"},{"type":"address","name":"_contractAddress","internalType":"address"},{"type":"uint256","name":"_tokenIds","internalType":"uint256"},{"type":"uint256","name":"_tokenAmount","internalType":"uint256"},{"type":"string","name":"_tokenType","internalType":"string"},{"type":"string","name":"_uid","internalType":"string"},{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executePanic","inputs":[{"type":"address","name":"_backUpWallet","internalType":"address"},{"type":"string","name":"_memberUID","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct member[]","components":[{"type":"string","name":"uid","internalType":"string"},{"type":"uint256","name":"dateCreated","internalType":"uint256"},{"type":"address[]","name":"wallets","internalType":"address[]"},{"type":"address[]","name":"backUpWallets","internalType":"address[]"},{"type":"uint256","name":"primaryWallet","internalType":"uint256"}]}],"name":"getAllMembers","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct BackUpApprovals[]","components":[{"type":"tuple","name":"Member","internalType":"struct member","components":[{"type":"string","name":"uid","internalType":"string"},{"type":"uint256","name":"dateCreated","internalType":"uint256"},{"type":"address[]","name":"wallets","internalType":"address[]"},{"type":"address[]","name":"backUpWallets","internalType":"address[]"},{"type":"uint256","name":"primaryWallet","internalType":"uint256"}]},{"type":"address","name":"approvedWallet","internalType":"address"},{"type":"address[]","name":"backUpWallet","internalType":"address[]"},{"type":"tuple","name":"token","internalType":"struct Token","components":[{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"string","name":"tokenType","internalType":"string"},{"type":"uint256","name":"tokensAllocated","internalType":"uint256"}]},{"type":"uint256","name":"dateApproved","internalType":"uint256"},{"type":"bool","name":"claimed","internalType":"bool"},{"type":"uint256","name":"approvalId","internalType":"uint256"}]}],"name":"getBackupApprovals","inputs":[{"type":"string","name":"uid","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getBackupWallets","inputs":[{"type":"string","name":"uid","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getIMembershipAddress","inputs":[{"type":"string","name":"_uid","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct member","components":[{"type":"string","name":"uid","internalType":"string"},{"type":"uint256","name":"dateCreated","internalType":"uint256"},{"type":"address[]","name":"wallets","internalType":"address[]"},{"type":"address[]","name":"backUpWallets","internalType":"address[]"},{"type":"uint256","name":"primaryWallet","internalType":"uint256"}]}],"name":"getMember","inputs":[{"type":"string","name":"uid","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getPrimaryWallet","inputs":[{"type":"string","name":"uid","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"getUID","inputs":[{"type":"address","name":"_walletAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getWallets","inputs":[{"type":"string","name":"uid","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"_directoryContract","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"uid","internalType":"string"},{"type":"uint256","name":"dateCreated","internalType":"uint256"},{"type":"uint256","name":"primaryWallet","internalType":"uint256"}],"name":"members","inputs":[{"type":"string","name":"","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setIMembershipAddress","inputs":[{"type":"string","name":"_uid","internalType":"string"},{"type":"address","name":"_Membership","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setPrimaryWallet","inputs":[{"type":"string","name":"uid","internalType":"string"},{"type":"uint256","name":"_walletIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"storeBackupAssetsApprovals","inputs":[{"type":"address[]","name":"_contractAddress","internalType":"address[]"},{"type":"uint256[]","name":"_tokenIds","internalType":"uint256[]"},{"type":"address[]","name":"_backUpWallets","internalType":"address[]"},{"type":"uint256[]","name":"_tokenAmount","internalType":"uint256[]"},{"type":"string[]","name":"_tokenTypes","internalType":"string[]"},{"type":"string","name":"_memberUID","internalType":"string"},{"type":"address","name":"_userAddress","internalType":"address"},{"type":"bool","name":"_super","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]}]
Contract Creation Code
0x6080806040523461001657614954908161001c8239f35b600080fdfe60806040526004361015610013575b600080fd5b60003560e01c806302dc63241461027f57806312e6e7b3146102765780631ecc00411461026d57806320b2d880146102645780633b81a76b1461025b5780633ba14f591461025257806343e2758b14610249578063474b0fec146102405780636957a0b2146102375780636b42cf4d1461022e578063715018a61461022557806372ebc7101461021c5780637c0f6b35146102135780637deaf2fe1461020a57806382685dc6146102015780638da5cb5b146101f8578063a53f723e146101ef578063b0e857c7146101e6578063c1cd0960146101dd578063c4d66de8146101d4578063c78233f8146101cb578063cbecb3f9146101c2578063cee174cd146101b9578063d1283b13146101b0578063d9ca567c146101a7578063e04179f31461019e578063f2fde38b14610195578063f6b2c0c91461018c578063f9c20b1b14610183578063fd0717bd1461017a5763ff9d494f1461017257600080fd5b61000e611b0b565b5061000e611a6b565b5061000e6119d1565b5061000e611867565b5061000e6117d5565b5061000e6117a3565b5061000e61178c565b5061000e611774565b5061000e611574565b5061000e611557565b5061000e611492565b5061000e61139f565b5061000e611387565b5061000e6111db565b5061000e6111b0565b5061000e611186565b5061000e6110c3565b5061000e610f68565b5061000e610e91565b5061000e610e67565b5061000e610e02565b5061000e610ddf565b5061000e610d84565b5061000e610b06565b5061000e610a5a565b5061000e61090f565b5061000e610769565b5061000e610650565b5061000e6105f4565b5061000e610567565b5061000e610438565b50634e487b7160e01b600052604160045260246000fd5b6001600160401b0381116102b257604052565b6102ba610288565b604052565b60a081019081106001600160401b038211176102b257604052565b604081019081106001600160401b038211176102b257604052565b90601f801991011681019081106001600160401b038211176102b257604052565b60405190610323826102bf565b565b60405190608082018281106001600160401b038211176102b257604052565b6040519061012082018281106001600160401b038211176102b257604052565b6020906001600160401b038111610381575b601f01601f19160190565b610389610288565b610376565b92919261039a82610364565b916103a860405193846102f5565b82948184528183011161000e578281602093846000960137010152565b9080601f8301121561000e578160206103e09335910161038e565b90565b6001600160a01b0381160361000e57565b60c43590610323826103e3565b604060031982011261000e57600435906001600160401b03821161000e5761042b916004016103c5565b906024356103e0816103e3565b503461000e5761045061044a36610401565b90614817565b005b602060031982011261000e57600435906001600160401b03821161000e576103e0916004016103c5565b918091926000905b82821061049c575011610495575050565b6000910152565b91508060209183015181860152018291610484565b906020916104ca8151809281855285808601910161047c565b601f01601f1916010190565b90815180825260208080930193019160005b8281106104f6575050505090565b83516001600160a01b0316855293810193928101926001016104e8565b9060808061055e61054c610530865160a0875260a08701906104b1565b60208701516020870152604087015186820360408801526104d6565b606086015185820360608701526104d6565b93015191015290565b503461000e5761059561058161057c36610452565b61290f565b604051918291602083526020830190610513565b0390f35b9181601f8401121561000e578235916001600160401b03831161000e576020838186019501011161000e57565b602060031982011261000e57600435906001600160401b03821161000e576105f091600401610599565b9091565b503461000e5761059561062461062b6002610617610611366105c6565b90612b31565b016040519283809261200e565b03826102f5565b6040519182916020835260208301906104d6565b9060206103e09281815201906104b1565b503461000e57602036600319011261000e5760043561066e816103e3565b6060906000609854905b8181106106be578380511561069757610595906040519182918261063f565b6106ba6106a2612d88565b60405162461bcd60e51b81529182916004830161063f565b0390fd5b6106d360026106cc83611a34565b5001612054565b80516106e9575b506106e49061207f565b610678565b936001600160a01b039391928285169290919060005b8751811015610758578487610724610717848c612097565b516001600160a01b031690565b1614610739575b6107349061207f565b6106ff565b915061073461075061074a87611a34565b50610d47565b92905061072b565b5094509450916106e49150906106da565b503461000e57604036600319011261000e57600435610787816103e3565b6024356001600160401b03811161000e576107a69036906004016103c5565b906107b13383614817565b609c546004906020906107da906107ce906001600160a01b031681565b6001600160a01b031690565b604051630110a66560e51b815292839182905afa9081156108bb575b60009161088d575b5061080883610c0b565b5415610882576001600160a01b031691823b1561000e5760405162fa7f2760e71b81526001600160a01b038316600482015261045093600090829060249082905afa8015610875575b61085c575b5061370c565b8061086961086f9261029f565b80610df7565b38610856565b61087d612197565b610851565b6106ba6106a26134cf565b6108ae915060203d81116108b4575b6108a681836102f5565b810190612182565b386107fe565b503d61089c565b6108c3612197565b6107f6565b9181601f8401121561000e578235916001600160401b03831161000e576020808501948460051b01011161000e57565b8015150361000e57565b60e43590610323826108f8565b503461000e5761010036600319011261000e5760046001600160401b03813581811161000e5761094290369084016108c8565b909160243581811161000e5761095b90369086016108c8565b9160443581811161000e5761097390369088016108c8565b60649291923582811161000e5761098d9036908a016108c8565b9160843584811161000e576109a59036908c016108c8565b95909460a43590811161000e576104509b6109c291369101610599565b9890976109cd6103f4565b9a6109d6610902565b9c612e7f565b6020906001600160401b0381116109f5575b60051b0190565b6109fd610288565b6109ee565b9291610a0d826109dc565b91610a1b60405193846102f5565b829481845260208094019160051b810192831161000e57905b828210610a415750505050565b8380918335610a4f816103e3565b815201910190610a34565b503461000e57604036600319011261000e576001600160401b0360043581811161000e57610a8c903690600401610599565b60243592831161000e573660238401121561000e57610ab8610450933690602481600401359101610a02565b90610acd33610ac836848761038e565b6120d7565b3392612b9a565b604060031982011261000e57600435906001600160401b03821161000e57610afe91600401610599565b909160243590565b503461000e57610b1536610ad4565b610b2433610ac836858761038e565b600480610b318486612b31565b01548214610bd2578181610b458587612b31565b015560005b60985481101561045057808383610b63610bc394611a34565b506040888a610bb283516020610ba681830183610b80828b612338565b0393610b94601f19958681018352826102f5565b51902096519485928301968791612b23565b039081018352826102f5565b51902014610bc8575b50505061207f565b610b4a565b0155838338610bbb565b610bda612d6a565b60405162461bcd60e51b81529182916106ba91830161063f565b90610c076020928281519485920161047c565b0190565b6020610c2491816040519382858094519384920161047c565b8101609b81520301902090565b6020610c4a91816040519382858094519384920161047c565b8101609981520301902090565b6020610c7091816040519382858094519384920161047c565b8101609781520301902090565b90600182811c92168015610cad575b6020831014610c9757565b634e487b7160e01b600052602260045260246000fd5b91607f1691610c8c565b9060009291805491610cc883610c7d565b918282526001938481169081600014610d2a5750600114610cea575b50505050565b90919394506000526020928360002092846000945b838610610d16575050505001019038808080610ce4565b805485870183015294019385908201610cff565b60ff19166020840152505060400193503891508190508080610ce4565b90610323610d5b9260405193848092610cb7565b03836102f5565b610d7a604092959493956060835260608301906104b1565b9460208201520152565b503461000e57610dab6020610d9836610452565b816040519382858094519384920161047c565b81016097815203019020604051610dc6816106248185610cb7565b6105956004600184015493015460405193849384610d62565b503461000e57610450610df136610401565b906126b6565b600091031261000e57565b503461000e57600080600319360112610e6457610e1d611e36565b603380546001600160a01b031981169091556040519082906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08284a3f35b80fd5b503461000e57600036600319011261000e57609c546040516001600160a01b039091168152602090f35b503461000e57600080600319360112610e6457609854610eb0816109dc565b90610ebe60405192836102f5565b8082526098835260209283830191816000805160206148ff833981519152845b838310610f435750505050604051928484019085855251809152604084019460408260051b8601019392955b828710610f175785850386f35b909192938280610f33600193603f198a82030186528851610513565b9601920196019592919092610f0a565b600588600192610f56859b9a989b6128a6565b81520192019201919096939596610ede565b503461000e57610f7f610f7a36610452565b610c0b565b805490610f8b826109dc565b90604092610f9b845193846102f5565b8083526020908184018093600052826000206000915b8383106110a05750505050835192818401908285525180915284840191858260051b86010193926000965b838810610fe95786860387f35b90919293948380600192603f198a8203018652885190611011825160e0808452830190610513565b91611036868060a01b039384868401511686850152888301518482038a8601526104d6565b6060908183015194848203838601528551825286860151168682015288850151918061106c608094858d860152858501906104b1565b960151910152818101519083015260a08082015115159083015260c080910151910152970193019701969093929193610fdc565b600e856001926110b2859a989a613554565b815201920192019190959395610fb1565b503461000e576110d236610401565b609c546004906020906110ef906107ce906001600160a01b031681565b60405163615b56c960e01b815292839182905afa908115611179575b60009161115b575b50336001600160a01b03909116036111505761113161045092610c31565b80546001600160a01b0319166001600160a01b03909216919091179055565b6106ba6106a26147f9565b611173915060203d81116108b4576108a681836102f5565b38611113565b611181612197565b61110b565b503461000e57600036600319011261000e576033546040516001600160a01b039091168152602090f35b503461000e5760206001600160a01b036111d16111cc36610452565b610c31565b5416604051908152f35b503461000e5760e036600319011261000e576004356024356111fc816103e3565b6064356044356001600160401b0360843581811161000e57611222903690600401610599565b92909160a43590811161000e5761123d9036906004016103c5565b9461126660c43561124d816103e3565b6112606112598961290f565b9189614610565b51610c0b565b9660005b885481101561131257808087878c8b87600d61128961129c99856130d2565b500154146112a1575b505050505061207f565b61126a565b8482611301926112dd8c60086112bc6113089b6009996130d2565b500180546001600160a01b0319166001600160a01b03909216919091179055565b8c60076112ea85856130d2565b500155600a6112f984846130d2565b5001556130d2565b500161417c565b8087878c8b611292565b876113326107ce6107ce61132584610c31565b546001600160a01b031690565b803b1561000e57604051637df8d05560e11b815290600090829081838161135c886004830161063f565b03925af1801561137a575b61136d57005b806108696104509261029f565b611382612197565b611367565b503461000e5761045061139936610401565b906120d7565b503461000e57602036600319011261000e576004356113bd816103e3565b611401600054916113e560ff8460081c161580948195611484575b8115611464575b50611ede565b826113f8600160ff196000541617600055565b61144b57611f41565b61140757005b61141761ff001960005416600055565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989080602081015b0390a1005b61145f61010061ff00196000541617600055565b611f41565b303b15915081611476575b50386113df565b6001915060ff16143861146f565b600160ff82161091506113d8565b503461000e5760e036600319011261000e5760046001600160401b03813581811161000e576114c490369084016108c8565b60249291923582811161000e576114de90369086016108c8565b909260443581811161000e576114f790369088016108c8565b9060643583811161000e5761150f9036908a016108c8565b92909160843585811161000e576115299036908c016108c8565b96909560a43590811161000e576104509b61154691369101610599565b9990986115516103f4565b9b614251565b503461000e5761059561062461062b6003610617610611366105c6565b503461000e5761158336610ad4565b9161159333610ac836858561038e565b600490816115a18483612b31565b0154841461176b576002926115d96115c486866115be8587612b31565b01612994565b81549060018060a01b039060031b1b19169055565b836115e48284612b31565b0194805b6115f287546129ea565b811015611662578061165861162a61161561160f61165d95612d1a565b8b612994565b905460039190911b1c6001600160a01b031690565b611634838b612994565b90919082549060031b9160018060a01b039283811b93849216901b16911916179055565b61207f565b6115e8565b50846116818783876116748789612b31565b0154101561174e57612d37565b60005b6098548110156104505761169781611a34565b50604085876116b483516020610ba681830183610b80828b612338565b519020146116cc575b506116c79061207f565b611684565b94828697939295970196845b6116e289546129ea565b81101561171457806116586117056116156116ff61170f95612d1a565b8d612994565b611634838d612994565b6116d8565b50949095926116c792936117288299612d37565b0180548581101561173c575b5050906116bd565b61174590612d2a565b90558780611734565b866117598688612b31565b016117648154612d2a565b9055612d37565b50610bda612cfc565b503461000e5761045061178636610401565b90614610565b503461000e5761045061179e36610452565b614408565b503461000e57602036600319011261000e5760206117cb6004356117c6816103e3565b6121a4565b6040519015158152f35b503461000e57602036600319011261000e576004356117f3816103e3565b6117fb611e36565b6001600160a01b038116156118135761045090611e8e565b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b503461000e57606036600319011261000e57600480356001600160401b03811161000e5761189890369083016103c5565b602435906118a5826103e3565b604435926118b2846108f8565b6118bc33836120d7565b6118c582610c57565b9260029485850195816118d884896129ba565b6119be575b60005b60985481101561197c57806118f761194792611a34565b50604088610ba66119388351602080820182611913828a612338565b0392611927601f19948581018352826102f5565b519020955193849182018096610bf4565b5190201461194c575b5061207f565b6118e0565b868482018661195b89836129ba565b611967575b5050611941565b61197190546129ea565b910155388681611960565b7f587d7f822a3f2af25ebf13a25de91348c0af2174890d25670cd88a4d559f288387866114468b60018401549284015490604051948594600382019186612a07565b6119c887546129ea565b848701556118dd565b503461000e576020611a046119e536610452565b60046119fc60026119f584610c57565b0192610c57565b015490612994565b905460405160039290921b1c6001600160a01b03168152f35b50634e487b7160e01b600052603260045260246000fd5b600590609854811015611a5e575b6098600052026000805160206148ff8339815191520190600090565b611a66611a1d565b611a42565b503461000e57602036600319011261000e5760043560985481101561000e57600590609860005202604051611ab48161062481856000805160206148ff83398151915201610cb7565b6105957f2237a976fa961f5921fd19f2b03c925c725d77b20ce8f790c19709c03de4d8187f2237a976fa961f5921fd19f2b03c925c725d77b20ce8f790c19709c03de4d81584015493015460405193849384610d62565b503461000e57608036600319011261000e576004803590611b2b826103e3565b6024356001600160401b03811161000e57611b4990369083016103c5565b60443590606435611b59816103e3565b600092604095865160209485820182611b728284610bf4565b0392611b86601f19948581018352826102f5565b51902089516545524337323160d01b88820190815290611bb08160068401038681018352826102f5565b51902014611d45575b8851611bd881611bcc8982018095610bf4565b038481018352826102f5565b519020908851611bfe8782019282610ba685600790664552433131353560c81b81520190565b51902014611c32575b5050505015611c1257005b6106ba611c1d61231a565b925162461bcd60e51b8152928392830161063f565b8651627eeac760e11b8082526001600160a01b03858116898401908152602081018690529194931691908690829081906040010381855afa908115611d38575b600091611d1b575b5015611c925750505050505060015b38808080611c07565b87519283526001600160a01b039093168683019081526020810191909152909183918391908290819060400103915afa918215611d0e575b600092611ce1575b505015611c8957506001611c89565b611d009250803d10611d07575b611cf881836102f5565b81019061230b565b3880611cd2565b503d611cee565b611d16612197565b611cca565b611d329150863d8811611d0757611cf881836102f5565b38611c7a565b611d40612197565b611c72565b9560018060a01b03808085168a878d80518c8180611d756331a9108f60e11b968783528883019190602083019252565b0381885afa908115611e29575b8891611e0c575b508b861696168603611da45750505050505050600195611bb9565b51908152908101888152949a9490918a918391908290819060200103915afa908115611dff575b8a91611de2575b501603611bb95760019650611bb9565b611df99150893d8b116108b4576108a681836102f5565b38611dd2565b611e07612197565b611dcb565b611e2391508d803d106108b4576108a681836102f5565b38611d89565b611e31612197565b611d82565b6033546001600160a01b03163303611e4a57565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b6033549060018060a01b0380911691826bffffffffffffffffffffffff60a01b821617603355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e06000604051a3565b15611ee557565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b611f6460ff60005460081c16611f5681611fae565b611f5f81611fae565b611fae565b611f6d33611e8e565b611f8260ff60005460081c16611f5f81611fae565b60016065556000609a5560018060a01b03166bffffffffffffffffffffffff60a01b609c541617609c55565b15611fb557565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b90815480825260208092019260005281600020916000905b828210612034575050505090565b83546001600160a01b031685529384019360019384019390910190612026565b90610323610d5b926040519384809261200e565b50634e487b7160e01b600052601160045260246000fd5b600190600019811461208f570190565b610c07612068565b60209181518110156120ac575b60051b010190565b6120b4611a1d565b6120a4565b604051906120c6826102da565b6002825261313960f01b6020830152565b906120fe60026120ea6120f79594610c57565b016040519485809261200e565b03846102f5565b600091825b8451811015612141576001600160a01b038061211f8388612097565b511690841614612138575b6121339061207f565b612103565b6001935061212a565b509250501561214c57565b6106ba6121576120b9565b60405162461bcd60e51b81526020600482015291829160248301906104b1565b5190610323826103e3565b9081602091031261000e57516103e0816103e3565b506040513d6000823e3d90fd5b90600091600460009160206121c66107ce6107ce609c5460018060a01b031690565b604051630110a66560e51b815293849182905afa9182156122fe575b83926122de575b506001600160a01b03918216803b156122da5760405162fa7f2760e71b81526001600160a01b0383166004820152908490829060249082905afa80156122cd575b6122ba575b5060985491835b838110612244575050505050565b61225260026106cc83611a34565b8051612268575b506122639061207f565b612236565b9691939294809691965b88518110156122aa57612288610717828b612097565b8616878716146122a1575b61229c9061207f565b612272565b60019350612293565b5094929391965094612263612259565b806108696122c79261029f565b3861222f565b6122d5612197565b61222a565b8380fd5b6122f791925060203d81116108b4576108a681836102f5565b90386121e9565b612306612197565b6121e2565b9081602091031261000e575190565b60405190612327826102da565b6002825261032360f41b6020830152565b60009291815461234781610c7d565b9260019180831690811561239f57506001146123635750505050565b90919293945060005260209081600020906000915b85831061238e5750505050019038808080610ce4565b805485840152918301918101612378565b60ff1916845250505001915038808080610ce4565b604051906123c1826102da565b6002825261333360f01b6020830152565b604051906123df826102da565b6002825261323560f01b6020830152565b50634e487b7160e01b600052600060045260246000fd5b818110612412575050565b60008155600101612407565b9190601f811161242d57505050565b610323926000526020600020906020601f840160051c83019310612459575b601f0160051c0190612407565b909150819061244c565b80546000825580612472575050565b61032391600052602060002090810190612407565b90600160401b81116124bc575b8154908083558181106124a657505050565b6103239260005260206000209182019101612407565b6124c4610288565b612494565b8151916124d68383612487565b602080910191600052806000206000925b8484106124f5575050505050565b805182546001600160a01b0319166001600160a01b0391909116178255600190819084019201930192906124e7565b90805180516001600160401b038111612632575b61254c816125468654610c7d565b8661241e565b6020918290601f83116001146125bf57918060809492600496946000926125b4575b50508160011b916000199060031b1c19161785555b810151600185015561259c6040820151600286016124c9565b6125ad6060820151600386016124c9565b0151910155565b01519050388061256e565b90601f198316916125d587600052602060002090565b9260005b81811061261b5750926001928592600498966080989610612602575b505050811b018555612583565b015160001960f88460031b161c191690553880806125f5565b9293866001819287860151815501950193016125d9565b61263a610288565b612538565b610323906005609854600160401b81101561268d575b6001810180609855811015612680575b6098600052026000805160206148ff83398151915201612524565b612688611a1d565b612665565b612695610288565b612655565b9291906126b16020916040865260408601906104b1565b930152565b609c546126cd906107ce906001600160a01b031681565b60409283518092630110a66560e51b825281600460209586935afa908115612899575b60009161287c575b506001600160a01b0316803b1561000e57845162fa7f2760e71b81526001600160a01b038316600482015290600090829060249082905afa801561286f575b61285c575b5061274683610c57565b845190816127578582018093612338565b039161276b601f19938481018352826102f5565b5190209085516127838582019282610ba6858a610bf4565b51902014158061284c575b156128405782511561281d577fb29bf840679333bfbac98f5b6db267f89ef32b09f1371605e68c3f423210b1b493929161280a612818926127cd610316565b92858452830194428652606087850152606080850152600060808501526127fc846127f783610c57565b612524565b6128058461263f565b612a48565b51915192519283928361269a565b0390a1565b6106ba846128296123d2565b905162461bcd60e51b81529182916004830161063f565b6106ba846128296123b4565b50612856816121a4565b1561278e565b806108696128699261029f565b3861273c565b612877612197565b612737565b6128939150833d85116108b4576108a681836102f5565b386126f8565b6128a1612197565b6126f0565b906040516128b3816102bf565b6080600482946040516128ca816106248185610cb7565b8452600181015460208501526040516128ea81610624816002860161200e565b604085015260405161290381610624816003860161200e565b60608501520154910152565b6129446129499160006080604051612926816102bf565b60608152826020820152606060408201526060808201520152610c57565b6128a6565b6020810151156129565790565b6106ba604051612965816102da565b6002815261323160f01b602082015260405191829162461bcd60e51b83526020600484015260248301906104b1565b80548210156129ad575b60005260206000200190600090565b6129b5611a1d565b61299e565b9061163461032392805490600160401b8210156129dd575b600182018155612994565b6129e5610288565b6129d2565b600181106129fa575b6000190190565b612a02612068565b6129f3565b959493906126b192608094612a27612a3a9360a08b5260a08b0190610cb7565b9160208a015288820360408a015261200e565b90868203606088015261200e565b612a5181610c57565b600280820193612a6181866129ba565b612a6b85546129ea565b9260049384820190815560005b609854811015612ade5780612a8f612ab992611a34565b50604089610ba6612aab8351602080820182611913828a612338565b51902014612abe575061207f565b612a78565b87612ad5888301612acf89826129ba565b546129ea565b91015538611941565b509350935050506128187f587d7f822a3f2af25ebf13a25de91348c0af2174890d25670cd88a4d559f2883936001840154925490604051948594600382019186612a07565b908092918237016000815290565b6020908260405193849283378101609781520301902090565b6020908260405193849283378101609981520301902090565b6020908260405193849283378101609b81520301902090565b60405190612b89826102da565b6002825261199960f11b6020830152565b9392612ba5816121a4565b15612ce2575b50612bb68185612b31565b936002850190815415612cd75760009594600392838701975b8651811015612bf75780611658612bec610717612bf2948b612097565b8b6129ba565b612bcf565b50909192939560005b609854811015612c9157612c1381611a34565b5060408987612c3083516020610ba681830183610b80828b612338565b51902014612c48575b50612c439061207f565b612c00565b9894919592836000999592999a01995b8851811015612c805780611658612c75610717612c7b948d612097565b8d6129ba565b612c58565b509295919498509296612c43612c39565b5093509350947f587d7f822a3f2af25ebf13a25de91348c0af2174890d25670cd88a4d559f28839450612818915060018301549360048401549160405195869586612a07565b6106ba6106a2612b7c565b612cf690612cf136848861038e565b6126b6565b38612bab565b60405190612d09826102da565b6002825261191b60f11b6020830152565b600190600119811161208f570190565b80156129fa576000190190565b80548015612d54576000190190612d516115c48383612994565b55565b634e487b7160e01b600052603160045260246000fd5b60405190612d77826102da565b6002825261323760f01b6020830152565b60405190612d95826102da565b6002825261191960f11b6020830152565b60405190612db3826102da565b6002825261064760f31b6020830152565b9190811015612dd45760051b0190565b6109fd611a1d565b356103e0816103e3565b9190811015612e28575b60051b81013590601e198136030182121561000e5701908135916001600160401b03831161000e57602001823603811361000e579190565b612e30611a1d565b612df0565b6001600160a01b0390911681526040602082018190526103e0929101906104b1565b90918060409360208452816020850152848401376000828201840152601f01601f1916010190565b999b94969a9c93959298979190808a148015906130c8575b6130bd57612efc868f968f90156130a9575b612eba612eb5836121a4565b151590565b15613095575b915050612ed161057c36888461038e565b95612ee688612ee136848661038e565b614610565b612efc88612ef5368d8d610a02565b8385612b9a565b6000905b8c8210612f83579950509650505050505050612f2b95506107ce94506107ce93506113259250612b4a565b91823b1561000e57612f579260009283604051809681958294637df8d05560e11b845260048401612e57565b03925af18015612f76575b612f695750565b806108696103239261029f565b612f7e612197565b612f62565b858f938f948f8f612fc5612fbe888093612fb7828f9d978f612fac83612fb192612fcc9c612dc4565b612ddc565b9e612dc4565b3598612de6565b369161038e565b928c612dc4565b359073f5a5b6a677ff77c22c856a2b794bdc5534806c973b1561000e578b8f93958f93968f93976116589861306d9b613060604091825163ff7b96a960e01b81526000818061301f888660048401612e35565b038173f5a5b6a677ff77c22c856a2b794bdc5534806c975af48015613088575b613075575b5061304d610325565b9b8c526001600160a01b031660208c0152565b89015260608801526133ff565b8d908f612f00565b806108696130829261029f565b38613044565b613090612197565b61303f565b6130a482612cf1368b8561038e565b612ec0565b6130b833610ac8368b8561038e565b612ea9565b6106ba6106a2612da6565b50888c1415612e97565b80548210156130ef575b600052600e602060002091020190600090565b6130f7611a1d565b6130dc565b81518155602080830151600180840180546001600160a01b0319166001600160a01b03939093169290921790915591929060028401906040830151938451916001600160401b038311613210575b613158836125468654610c7d565b80601f841160011461319b5750918080926060969594600398600094613190575b50501b9160001990871b1c19161790550151910155565b015192503880613179565b91939495601f1984166131b387600052602060002090565b936000905b8282106131f957505091600397959391856060989694106131e1575b505050811b0190556125ad565b015160001983891b60f8161c191690553880806131d4565b8088869782949787015181550196019401906131b8565b613218610288565b61314a565b9061323d8254600160401b81101561332a575b60019384820181556130d2565b92909261331d575b613250825184612524565b6020828101516005850180546001600160a01b0319166001600160a01b039283161790559060068501906040850151928184519461328e8686612487565b019260005281600020906000935b8585106132ef575050505050505060c0816132c06060600d940151600786016130fc565b6080810151600b8501556125ad6132da60a0830151151590565b600c86019060ff801983541691151516179055565b805183549083166001600160a01b03166001600160a01b03199091161783559386019391860191830161329c565b6133256123f0565b613245565b613332610288565b613230565b98969492959390613354909b9a989b610160808c528b01906104b1565b6001600160a01b0392831660208b8101919091528a820360408c015282825290810196926000905b8382106133d9575050505050928694926133b06133bd936101409896606060009b0152608088019060018060a01b03169052565b85820360a08701526104b1565b9660c084015260e0830152836101008301526101208201520152565b90919293978380600192848c356133ef816103e3565b168152019901949392019061337c565b916134906128189495969361348b6000805160206148df8339815191529994613429609a5461207f565b9283609a556040519360e085018581106001600160401b038211176134c2575b6040528685526001600160a01b038b166020860152613469368a8e610a02565b6040860152876060860152426080860152600060a086015260c0850152612b63565b61321d565b5181516020830151919290916001600160a01b03166060604083015192015192609a5495604051998a9942978b613337565b6134ca610288565b613449565b604051906134dc826102da565b6002825261323960f01b6020830152565b90604051608081018181106001600160401b03821117613547575b6040526060600382948054845260018060a01b03600182015416602085015260405161353b816106248160028601610cb7565b60408501520154910152565b61354f610288565b613508565b9060405160e081018181106001600160401b038211176135e3575b60405260c0600d8294613581816128a6565b845260058101546001600160a01b031660208501526135a260068201612054565b60408501526135b3600782016134ed565b6060850152600b81015460808501526135dc6135d3600c83015460ff1690565b151560a0860152565b0154910152565b6135eb610288565b61356f565b5190610323826108f8565b9081602091031261000e57516103e0816108f8565b99959091610140999561365961367295999e9d9961363a8e9c98968d610160908181520190610cb7565b9060018060a01b039c8d8096166020820152604081840391015261200e565b9360608d01521660808b015289820360a08b0152610cb7565b9860c088015260e0870152151561010086015261012085015216910152565b92909493919460018060a01b03809116845260209516858401526040830152606082015260809260a084830152606051908160a08401526000945b8286106136f85750508060c09394116136eb57601f01601f1916010190565b60008382840101526104ca565b8581015184870160c00152948101946136cc565b61371590610c0b565b60005b81548110156140dc5761372b81836130d2565b5061373e612eb5600c8093015460ff1690565b15613753575b5061374e9061207f565b613718565b61376f8461376a61376485876130d2565b50613554565b6140e1565b8261377a83826130d2565b5091604080519060209182810181613796826009809a01612338565b03916137aa601f19938481018352826102f5565b519020825164045524332360dc1b858201908152906137d481600584015b038581018352826102f5565b51902014613d91575b85611bcc6138006137ee8a896130d2565b50855192839188830195869101612338565b51902082516545524337323160d01b8582019081529061382381600684016137c8565b51902014613b44575b85611bcc61383d6137ee8a896130d2565b5190209082516138638582019282610ba685600790664552433131353560c81b81520190565b51902014613875575b50505050613744565b61387f86856130d2565b5060089081015461389a906107ce906001600160a01b031681565b936138a588876130d2565b506005908101549092906001600160a01b0316946138c38a896130d2565b506007908101548651627eeac760e11b81526001600160a01b03989098166004808a019190915260248901919091529690919081816044818c5afa918215613b37575b600092613b1a575b505061391a8b8a6130d2565b50908b600a80930154821115600014613aab5761395681613950896139418f9589966130d2565b5001546001600160a01b031690565b9c6130d2565b50015495893b1561000e57858f998f8f9d908e9d9a60008f9c8f908f958f9a6139af9861399986928e9a5198899788968795637921219560e11b87528601613691565b03925af18015613a9e575b613a8b575b506130d2565b5001805460ff191660011790558d6139c783826130d2565b509a6139d2916130d2565b5001546001600160a01b0316938d6139ea83826130d2565b50946139f684836130d2565b50015492613a03916130d2565b5001546001600160a01b0316918d613a1b88826130d2565b509b613a26916130d2565b500154938d613a3588826130d2565b50600b015496613a4589836130d2565b50015460ff1697613a55916130d2565b50600d015497519b8c9b019360060190613a6f9a8c613610565b036000805160206148df83398151915291a1388281808061386c565b80610869613a989261029f565b386139a9565b613aa6612197565b6139a4565b613abd9150956139418b97829c6130d2565b9881613ad78d85613ace828b6130d2565b500154986130d2565b50015490893b1561000e57858f998f8f9d908e9d9a60008f9c8f908f958f9a6139af9861399986928e9a5198899788968795637921219560e11b87528601613691565b613b309250803d10611d0757611cf881836102f5565b388061390e565b613b3f612197565b613906565b85613b4f88876130d2565b50600890810154613b6a906107ce906001600160a01b031681565b8b613b758b8a6130d2565b5060079081015487516331a9108f60e11b8152600480820192909252938985602481845afa948515613d84575b600095613d65575b508d8c613bb782826130d2565b50600590810154909790613bd3906001600160a01b03166107ce565b6001600160a01b0390911614613ccc575b8c9350613bf192506130d2565b5001805460ff191660011790558b898b613c0b83826130d2565b5095613c1784836130d2565b5001546001600160a01b031693613c2e84836130d2565b5090613c3a85846130d2565b50015497613c4885846130d2565b5001546001600160a01b0316613c5e85846130d2565b5098613c6a86856130d2565b50600a015493613c7a87826130d2565b50600b015495613c8a88836130d2565b50015460ff1696613c9a916130d2565b50600d0154968d519b8c9b019360060190613cb59a8c613610565b036000805160206148df83398151915291a161382c565b84939850613ce49295508661394183613950936130d2565b500154823b1561000e578751632142170760e11b81526001600160a01b039b8c169681019687529a8f16602087015260408601528c998b958f9360009183919082908490829060600103925af18015613d58575b613d45575b808d8c613be4565b80610869613d529261029f565b38613d3d565b613d60612197565b613d38565b613d7d9195508a3d8c116108b4576108a681836102f5565b9338613baa565b613d8c612197565b613ba2565b85613d9c88876130d2565b50613de4613e61868d8c8b613dc16107ce6107ce6008809a015460018060a01b031690565b91613dcc81836130d2565b5060059081015490978892916001600160a01b031690565b8c51636eb1769f60e11b81526001600160a01b03919091166004808301919091523060248301529390878e81836044818b5afa9283156140cf575b6000936140b0575b50613e368661394187876130d2565b90516370a0823160e01b81526001600160a01b03909116878201908152909a8b918291602090910190565b0381895afa9889156140a3575b600099614084575b50808911613ffa575091613941613e8f926000946130d2565b8b516323b872dd60e01b81526001600160a01b0391821693810193845294166020830152604082019590955291938492839190829060600103925af18015613fed575b613fc0575b505b86613ee48b8a6130d2565b5001805460ff191660011790558b613efc8b8a6130d2565b5091613f088c8b6130d2565b5001546001600160a01b03168b898b613f2183826130d2565b50613f2c84836130d2565b506007015497613f3c85846130d2565b5001546001600160a01b0316613f5285846130d2565b5098613f5e86856130d2565b50600a015493613f6e87826130d2565b50600b015495613f7e88836130d2565b50015460ff1696613f8e916130d2565b50600d0154968d519b8c9b019360060190613fa99a8c613610565b036000805160206148df83398151915291a16137dd565b613fdf90873d8911613fe6575b613fd781836102f5565b8101906135fb565b5038613ed7565b503d613fcd565b613ff5612197565b613ed2565b97509161394161400c926000946130d2565b8b516323b872dd60e01b81526001600160a01b0391821693810193845294166020830152604082019590955291938492839190829060600103925af18015614077575b61405a575b50613ed9565b61407090873d8911613fe657613fd781836102f5565b5038614054565b61407f612197565b61404f565b61409c919950883d8a11611d0757611cf881836102f5565b9738613e76565b6140ab612197565b613e6e565b6140c8919350823d8411611d0757611cf881836102f5565b9138613e27565b6140d7612197565b613e1f565b505050565b90600092835b60408401518051821015614131576001600160a01b0390819061410b908490612097565b511690841614614128575b61412160409161207f565b90506140e7565b60019450614116565b5050929150501561413e57565b6106ba60405161414d816102da565b6002815261323360f01b602082015260405191829162461bcd60e51b83526020600484015260248301906104b1565b9092916001600160401b038111614244575b6141a28161419c8454610c7d565b8461241e565b6000601f82116001146141dc57819293946000926141d1575b50508160011b916000199060031b1c1916179055565b0135905038806141bb565b601f198216946141f184600052602060002090565b91805b87811061422c575083600195969710614212575b505050811b019055565b0135600019600384901b60f8161c19169055388080614208565b909260206001819286860135815501940191016141f4565b61424c610288565b61418e565b9896999a9b9394959161427561179e8d8f9b94969b612fbe89612ee136848661038e565b838914801590614394575b6130bd578c936142cd868e614297612eb5836121a4565b15614380575b9150506142ae61057c36888461038e565b956142be88612ee136848661038e565b6142cd88612ef5368d8d610a02565b6000905b8c82106142fc579950509650505050505050612f2b95506107ce94506107ce93506113259250612b4a565b858f938f948f8f612fc5612fbe888093612fb7828f9d978f612fac83612fb1926143259c612dc4565b359073f5a5b6a677ff77c22c856a2b794bdc5534806c973b1561000e578b8f93958f93968f9397611658986143789b613060604091825163ff7b96a960e01b81526000818061301f888660048401612e35565b8d908f6142d1565b61438f82612cf1368b8561038e565b61429d565b50878b1415614280565b6143a88154610c7d565b90816143b2575050565b81601f600093116001146143c4575055565b818352602083206143e091601f0160051c810190600101612407565b8160208120915555565b60036000918281558260018201556144046002820161439e565b0155565b6112606144149161290f565b80549060008082558261442657505050565b6001917f1249249249249249249249249249249249249249249249249249249249249249841183166144d5575b81526020812091600e9384028301925b838110614471575050505050565b8061447c869261439e565b838382015561448d60028201612463565b61449960038201612463565b8360048201558360058201556144b160068201612463565b6144bd600782016143ea565b83600b82015583600c82015583600d82015501614463565b6144dd612068565b614453565b81601f8201121561000e5780516144f881610364565b9261450660405194856102f5565b8184526020828401011161000e576103e0916020808501910161047c565b60208183031261000e5780516001600160401b039182821161000e57016101208184031261000e57614554610344565b9261455e82612177565b845260208201516020850152604082015160408501526060820151606085015261458a608083016135f0565b608085015260a082015160a085015260c082015160c08501526145af60e08301612177565b60e0850152610100928383015190811161000e576145cd92016144e2565b9082015290565b604051906145e1826102da565b6002825261033360f41b6020830152565b604051906145ff826102da565b60028252610c8d60f21b6020830152565b609c5490919061462a906107ce906001600160a01b031681565b91604092835192838092630110a66560e51b8252602093849160049788915afa9081156147ec575b6000916147cf575b506001600160a01b0316803b1561000e57855162fa7f2760e71b81526001600160a01b0390921685830190815260009183918290819060200103915afa80156147c2575b6147af575b506146b66107ce6107ce61132585610c31565b818551809263317c557160e01b825281806146d3888a830161063f565b03915afa9182156147a2575b600092614785575b50506146f957506106ba611c1d6145f2565b61472c6000826147136107ce6107ce61132560c097610c31565b8651808095819463198cb35b60e01b835289830161063f565b03915afa908115614778575b600091614757575b5001511561474c575050565b6106ba611c1d6145d4565b614772913d8091833e61476a81836102f5565b810190614524565b38614740565b614780612197565b614738565b61479b9250803d10613fe657613fd781836102f5565b38806146e7565b6147aa612197565b6146df565b806108696147bc9261029f565b386146a3565b6147ca612197565b61469e565b6147e69150833d85116108b4576108a681836102f5565b3861465a565b6147f4612197565b614652565b60405190614806826102da565b6002825261333160f01b6020830152565b9061482c600261482684610c57565b01612054565b926000805b8551811015614871576148476107178288612097565b6001600160a01b03858116911614614868575b6148639061207f565b614831565b6001915061485a565b5092614884919450614826600391610c57565b9260005b84518110156148c85761489e6107178287612097565b6001600160a01b038481169116146148bf575b6148ba9061207f565b614888565b600193506148b1565b50925050156148d357565b6106ba6106a26120b956fecca517edfbfb04bc5c7b43f59f9f561e3d007cc4c80a5542cb59c1efe93b40652237a976fa961f5921fd19f2b03c925c725d77b20ce8f790c19709c03de4d814a2646970667358221220bd40a70cccd251a38912ebeb91f2da57d8db9b9cb42653d83d202d65b0d693e264736f6c634300080d0033
Deployed ByteCode
0x60806040526004361015610013575b600080fd5b60003560e01c806302dc63241461027f57806312e6e7b3146102765780631ecc00411461026d57806320b2d880146102645780633b81a76b1461025b5780633ba14f591461025257806343e2758b14610249578063474b0fec146102405780636957a0b2146102375780636b42cf4d1461022e578063715018a61461022557806372ebc7101461021c5780637c0f6b35146102135780637deaf2fe1461020a57806382685dc6146102015780638da5cb5b146101f8578063a53f723e146101ef578063b0e857c7146101e6578063c1cd0960146101dd578063c4d66de8146101d4578063c78233f8146101cb578063cbecb3f9146101c2578063cee174cd146101b9578063d1283b13146101b0578063d9ca567c146101a7578063e04179f31461019e578063f2fde38b14610195578063f6b2c0c91461018c578063f9c20b1b14610183578063fd0717bd1461017a5763ff9d494f1461017257600080fd5b61000e611b0b565b5061000e611a6b565b5061000e6119d1565b5061000e611867565b5061000e6117d5565b5061000e6117a3565b5061000e61178c565b5061000e611774565b5061000e611574565b5061000e611557565b5061000e611492565b5061000e61139f565b5061000e611387565b5061000e6111db565b5061000e6111b0565b5061000e611186565b5061000e6110c3565b5061000e610f68565b5061000e610e91565b5061000e610e67565b5061000e610e02565b5061000e610ddf565b5061000e610d84565b5061000e610b06565b5061000e610a5a565b5061000e61090f565b5061000e610769565b5061000e610650565b5061000e6105f4565b5061000e610567565b5061000e610438565b50634e487b7160e01b600052604160045260246000fd5b6001600160401b0381116102b257604052565b6102ba610288565b604052565b60a081019081106001600160401b038211176102b257604052565b604081019081106001600160401b038211176102b257604052565b90601f801991011681019081106001600160401b038211176102b257604052565b60405190610323826102bf565b565b60405190608082018281106001600160401b038211176102b257604052565b6040519061012082018281106001600160401b038211176102b257604052565b6020906001600160401b038111610381575b601f01601f19160190565b610389610288565b610376565b92919261039a82610364565b916103a860405193846102f5565b82948184528183011161000e578281602093846000960137010152565b9080601f8301121561000e578160206103e09335910161038e565b90565b6001600160a01b0381160361000e57565b60c43590610323826103e3565b604060031982011261000e57600435906001600160401b03821161000e5761042b916004016103c5565b906024356103e0816103e3565b503461000e5761045061044a36610401565b90614817565b005b602060031982011261000e57600435906001600160401b03821161000e576103e0916004016103c5565b918091926000905b82821061049c575011610495575050565b6000910152565b91508060209183015181860152018291610484565b906020916104ca8151809281855285808601910161047c565b601f01601f1916010190565b90815180825260208080930193019160005b8281106104f6575050505090565b83516001600160a01b0316855293810193928101926001016104e8565b9060808061055e61054c610530865160a0875260a08701906104b1565b60208701516020870152604087015186820360408801526104d6565b606086015185820360608701526104d6565b93015191015290565b503461000e5761059561058161057c36610452565b61290f565b604051918291602083526020830190610513565b0390f35b9181601f8401121561000e578235916001600160401b03831161000e576020838186019501011161000e57565b602060031982011261000e57600435906001600160401b03821161000e576105f091600401610599565b9091565b503461000e5761059561062461062b6002610617610611366105c6565b90612b31565b016040519283809261200e565b03826102f5565b6040519182916020835260208301906104d6565b9060206103e09281815201906104b1565b503461000e57602036600319011261000e5760043561066e816103e3565b6060906000609854905b8181106106be578380511561069757610595906040519182918261063f565b6106ba6106a2612d88565b60405162461bcd60e51b81529182916004830161063f565b0390fd5b6106d360026106cc83611a34565b5001612054565b80516106e9575b506106e49061207f565b610678565b936001600160a01b039391928285169290919060005b8751811015610758578487610724610717848c612097565b516001600160a01b031690565b1614610739575b6107349061207f565b6106ff565b915061073461075061074a87611a34565b50610d47565b92905061072b565b5094509450916106e49150906106da565b503461000e57604036600319011261000e57600435610787816103e3565b6024356001600160401b03811161000e576107a69036906004016103c5565b906107b13383614817565b609c546004906020906107da906107ce906001600160a01b031681565b6001600160a01b031690565b604051630110a66560e51b815292839182905afa9081156108bb575b60009161088d575b5061080883610c0b565b5415610882576001600160a01b031691823b1561000e5760405162fa7f2760e71b81526001600160a01b038316600482015261045093600090829060249082905afa8015610875575b61085c575b5061370c565b8061086961086f9261029f565b80610df7565b38610856565b61087d612197565b610851565b6106ba6106a26134cf565b6108ae915060203d81116108b4575b6108a681836102f5565b810190612182565b386107fe565b503d61089c565b6108c3612197565b6107f6565b9181601f8401121561000e578235916001600160401b03831161000e576020808501948460051b01011161000e57565b8015150361000e57565b60e43590610323826108f8565b503461000e5761010036600319011261000e5760046001600160401b03813581811161000e5761094290369084016108c8565b909160243581811161000e5761095b90369086016108c8565b9160443581811161000e5761097390369088016108c8565b60649291923582811161000e5761098d9036908a016108c8565b9160843584811161000e576109a59036908c016108c8565b95909460a43590811161000e576104509b6109c291369101610599565b9890976109cd6103f4565b9a6109d6610902565b9c612e7f565b6020906001600160401b0381116109f5575b60051b0190565b6109fd610288565b6109ee565b9291610a0d826109dc565b91610a1b60405193846102f5565b829481845260208094019160051b810192831161000e57905b828210610a415750505050565b8380918335610a4f816103e3565b815201910190610a34565b503461000e57604036600319011261000e576001600160401b0360043581811161000e57610a8c903690600401610599565b60243592831161000e573660238401121561000e57610ab8610450933690602481600401359101610a02565b90610acd33610ac836848761038e565b6120d7565b3392612b9a565b604060031982011261000e57600435906001600160401b03821161000e57610afe91600401610599565b909160243590565b503461000e57610b1536610ad4565b610b2433610ac836858761038e565b600480610b318486612b31565b01548214610bd2578181610b458587612b31565b015560005b60985481101561045057808383610b63610bc394611a34565b506040888a610bb283516020610ba681830183610b80828b612338565b0393610b94601f19958681018352826102f5565b51902096519485928301968791612b23565b039081018352826102f5565b51902014610bc8575b50505061207f565b610b4a565b0155838338610bbb565b610bda612d6a565b60405162461bcd60e51b81529182916106ba91830161063f565b90610c076020928281519485920161047c565b0190565b6020610c2491816040519382858094519384920161047c565b8101609b81520301902090565b6020610c4a91816040519382858094519384920161047c565b8101609981520301902090565b6020610c7091816040519382858094519384920161047c565b8101609781520301902090565b90600182811c92168015610cad575b6020831014610c9757565b634e487b7160e01b600052602260045260246000fd5b91607f1691610c8c565b9060009291805491610cc883610c7d565b918282526001938481169081600014610d2a5750600114610cea575b50505050565b90919394506000526020928360002092846000945b838610610d16575050505001019038808080610ce4565b805485870183015294019385908201610cff565b60ff19166020840152505060400193503891508190508080610ce4565b90610323610d5b9260405193848092610cb7565b03836102f5565b610d7a604092959493956060835260608301906104b1565b9460208201520152565b503461000e57610dab6020610d9836610452565b816040519382858094519384920161047c565b81016097815203019020604051610dc6816106248185610cb7565b6105956004600184015493015460405193849384610d62565b503461000e57610450610df136610401565b906126b6565b600091031261000e57565b503461000e57600080600319360112610e6457610e1d611e36565b603380546001600160a01b031981169091556040519082906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08284a3f35b80fd5b503461000e57600036600319011261000e57609c546040516001600160a01b039091168152602090f35b503461000e57600080600319360112610e6457609854610eb0816109dc565b90610ebe60405192836102f5565b8082526098835260209283830191816000805160206148ff833981519152845b838310610f435750505050604051928484019085855251809152604084019460408260051b8601019392955b828710610f175785850386f35b909192938280610f33600193603f198a82030186528851610513565b9601920196019592919092610f0a565b600588600192610f56859b9a989b6128a6565b81520192019201919096939596610ede565b503461000e57610f7f610f7a36610452565b610c0b565b805490610f8b826109dc565b90604092610f9b845193846102f5565b8083526020908184018093600052826000206000915b8383106110a05750505050835192818401908285525180915284840191858260051b86010193926000965b838810610fe95786860387f35b90919293948380600192603f198a8203018652885190611011825160e0808452830190610513565b91611036868060a01b039384868401511686850152888301518482038a8601526104d6565b6060908183015194848203838601528551825286860151168682015288850151918061106c608094858d860152858501906104b1565b960151910152818101519083015260a08082015115159083015260c080910151910152970193019701969093929193610fdc565b600e856001926110b2859a989a613554565b815201920192019190959395610fb1565b503461000e576110d236610401565b609c546004906020906110ef906107ce906001600160a01b031681565b60405163615b56c960e01b815292839182905afa908115611179575b60009161115b575b50336001600160a01b03909116036111505761113161045092610c31565b80546001600160a01b0319166001600160a01b03909216919091179055565b6106ba6106a26147f9565b611173915060203d81116108b4576108a681836102f5565b38611113565b611181612197565b61110b565b503461000e57600036600319011261000e576033546040516001600160a01b039091168152602090f35b503461000e5760206001600160a01b036111d16111cc36610452565b610c31565b5416604051908152f35b503461000e5760e036600319011261000e576004356024356111fc816103e3565b6064356044356001600160401b0360843581811161000e57611222903690600401610599565b92909160a43590811161000e5761123d9036906004016103c5565b9461126660c43561124d816103e3565b6112606112598961290f565b9189614610565b51610c0b565b9660005b885481101561131257808087878c8b87600d61128961129c99856130d2565b500154146112a1575b505050505061207f565b61126a565b8482611301926112dd8c60086112bc6113089b6009996130d2565b500180546001600160a01b0319166001600160a01b03909216919091179055565b8c60076112ea85856130d2565b500155600a6112f984846130d2565b5001556130d2565b500161417c565b8087878c8b611292565b876113326107ce6107ce61132584610c31565b546001600160a01b031690565b803b1561000e57604051637df8d05560e11b815290600090829081838161135c886004830161063f565b03925af1801561137a575b61136d57005b806108696104509261029f565b611382612197565b611367565b503461000e5761045061139936610401565b906120d7565b503461000e57602036600319011261000e576004356113bd816103e3565b611401600054916113e560ff8460081c161580948195611484575b8115611464575b50611ede565b826113f8600160ff196000541617600055565b61144b57611f41565b61140757005b61141761ff001960005416600055565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989080602081015b0390a1005b61145f61010061ff00196000541617600055565b611f41565b303b15915081611476575b50386113df565b6001915060ff16143861146f565b600160ff82161091506113d8565b503461000e5760e036600319011261000e5760046001600160401b03813581811161000e576114c490369084016108c8565b60249291923582811161000e576114de90369086016108c8565b909260443581811161000e576114f790369088016108c8565b9060643583811161000e5761150f9036908a016108c8565b92909160843585811161000e576115299036908c016108c8565b96909560a43590811161000e576104509b61154691369101610599565b9990986115516103f4565b9b614251565b503461000e5761059561062461062b6003610617610611366105c6565b503461000e5761158336610ad4565b9161159333610ac836858561038e565b600490816115a18483612b31565b0154841461176b576002926115d96115c486866115be8587612b31565b01612994565b81549060018060a01b039060031b1b19169055565b836115e48284612b31565b0194805b6115f287546129ea565b811015611662578061165861162a61161561160f61165d95612d1a565b8b612994565b905460039190911b1c6001600160a01b031690565b611634838b612994565b90919082549060031b9160018060a01b039283811b93849216901b16911916179055565b61207f565b6115e8565b50846116818783876116748789612b31565b0154101561174e57612d37565b60005b6098548110156104505761169781611a34565b50604085876116b483516020610ba681830183610b80828b612338565b519020146116cc575b506116c79061207f565b611684565b94828697939295970196845b6116e289546129ea565b81101561171457806116586117056116156116ff61170f95612d1a565b8d612994565b611634838d612994565b6116d8565b50949095926116c792936117288299612d37565b0180548581101561173c575b5050906116bd565b61174590612d2a565b90558780611734565b866117598688612b31565b016117648154612d2a565b9055612d37565b50610bda612cfc565b503461000e5761045061178636610401565b90614610565b503461000e5761045061179e36610452565b614408565b503461000e57602036600319011261000e5760206117cb6004356117c6816103e3565b6121a4565b6040519015158152f35b503461000e57602036600319011261000e576004356117f3816103e3565b6117fb611e36565b6001600160a01b038116156118135761045090611e8e565b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b503461000e57606036600319011261000e57600480356001600160401b03811161000e5761189890369083016103c5565b602435906118a5826103e3565b604435926118b2846108f8565b6118bc33836120d7565b6118c582610c57565b9260029485850195816118d884896129ba565b6119be575b60005b60985481101561197c57806118f761194792611a34565b50604088610ba66119388351602080820182611913828a612338565b0392611927601f19948581018352826102f5565b519020955193849182018096610bf4565b5190201461194c575b5061207f565b6118e0565b868482018661195b89836129ba565b611967575b5050611941565b61197190546129ea565b910155388681611960565b7f587d7f822a3f2af25ebf13a25de91348c0af2174890d25670cd88a4d559f288387866114468b60018401549284015490604051948594600382019186612a07565b6119c887546129ea565b848701556118dd565b503461000e576020611a046119e536610452565b60046119fc60026119f584610c57565b0192610c57565b015490612994565b905460405160039290921b1c6001600160a01b03168152f35b50634e487b7160e01b600052603260045260246000fd5b600590609854811015611a5e575b6098600052026000805160206148ff8339815191520190600090565b611a66611a1d565b611a42565b503461000e57602036600319011261000e5760043560985481101561000e57600590609860005202604051611ab48161062481856000805160206148ff83398151915201610cb7565b6105957f2237a976fa961f5921fd19f2b03c925c725d77b20ce8f790c19709c03de4d8187f2237a976fa961f5921fd19f2b03c925c725d77b20ce8f790c19709c03de4d81584015493015460405193849384610d62565b503461000e57608036600319011261000e576004803590611b2b826103e3565b6024356001600160401b03811161000e57611b4990369083016103c5565b60443590606435611b59816103e3565b600092604095865160209485820182611b728284610bf4565b0392611b86601f19948581018352826102f5565b51902089516545524337323160d01b88820190815290611bb08160068401038681018352826102f5565b51902014611d45575b8851611bd881611bcc8982018095610bf4565b038481018352826102f5565b519020908851611bfe8782019282610ba685600790664552433131353560c81b81520190565b51902014611c32575b5050505015611c1257005b6106ba611c1d61231a565b925162461bcd60e51b8152928392830161063f565b8651627eeac760e11b8082526001600160a01b03858116898401908152602081018690529194931691908690829081906040010381855afa908115611d38575b600091611d1b575b5015611c925750505050505060015b38808080611c07565b87519283526001600160a01b039093168683019081526020810191909152909183918391908290819060400103915afa918215611d0e575b600092611ce1575b505015611c8957506001611c89565b611d009250803d10611d07575b611cf881836102f5565b81019061230b565b3880611cd2565b503d611cee565b611d16612197565b611cca565b611d329150863d8811611d0757611cf881836102f5565b38611c7a565b611d40612197565b611c72565b9560018060a01b03808085168a878d80518c8180611d756331a9108f60e11b968783528883019190602083019252565b0381885afa908115611e29575b8891611e0c575b508b861696168603611da45750505050505050600195611bb9565b51908152908101888152949a9490918a918391908290819060200103915afa908115611dff575b8a91611de2575b501603611bb95760019650611bb9565b611df99150893d8b116108b4576108a681836102f5565b38611dd2565b611e07612197565b611dcb565b611e2391508d803d106108b4576108a681836102f5565b38611d89565b611e31612197565b611d82565b6033546001600160a01b03163303611e4a57565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b6033549060018060a01b0380911691826bffffffffffffffffffffffff60a01b821617603355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e06000604051a3565b15611ee557565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b611f6460ff60005460081c16611f5681611fae565b611f5f81611fae565b611fae565b611f6d33611e8e565b611f8260ff60005460081c16611f5f81611fae565b60016065556000609a5560018060a01b03166bffffffffffffffffffffffff60a01b609c541617609c55565b15611fb557565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b90815480825260208092019260005281600020916000905b828210612034575050505090565b83546001600160a01b031685529384019360019384019390910190612026565b90610323610d5b926040519384809261200e565b50634e487b7160e01b600052601160045260246000fd5b600190600019811461208f570190565b610c07612068565b60209181518110156120ac575b60051b010190565b6120b4611a1d565b6120a4565b604051906120c6826102da565b6002825261313960f01b6020830152565b906120fe60026120ea6120f79594610c57565b016040519485809261200e565b03846102f5565b600091825b8451811015612141576001600160a01b038061211f8388612097565b511690841614612138575b6121339061207f565b612103565b6001935061212a565b509250501561214c57565b6106ba6121576120b9565b60405162461bcd60e51b81526020600482015291829160248301906104b1565b5190610323826103e3565b9081602091031261000e57516103e0816103e3565b506040513d6000823e3d90fd5b90600091600460009160206121c66107ce6107ce609c5460018060a01b031690565b604051630110a66560e51b815293849182905afa9182156122fe575b83926122de575b506001600160a01b03918216803b156122da5760405162fa7f2760e71b81526001600160a01b0383166004820152908490829060249082905afa80156122cd575b6122ba575b5060985491835b838110612244575050505050565b61225260026106cc83611a34565b8051612268575b506122639061207f565b612236565b9691939294809691965b88518110156122aa57612288610717828b612097565b8616878716146122a1575b61229c9061207f565b612272565b60019350612293565b5094929391965094612263612259565b806108696122c79261029f565b3861222f565b6122d5612197565b61222a565b8380fd5b6122f791925060203d81116108b4576108a681836102f5565b90386121e9565b612306612197565b6121e2565b9081602091031261000e575190565b60405190612327826102da565b6002825261032360f41b6020830152565b60009291815461234781610c7d565b9260019180831690811561239f57506001146123635750505050565b90919293945060005260209081600020906000915b85831061238e5750505050019038808080610ce4565b805485840152918301918101612378565b60ff1916845250505001915038808080610ce4565b604051906123c1826102da565b6002825261333360f01b6020830152565b604051906123df826102da565b6002825261323560f01b6020830152565b50634e487b7160e01b600052600060045260246000fd5b818110612412575050565b60008155600101612407565b9190601f811161242d57505050565b610323926000526020600020906020601f840160051c83019310612459575b601f0160051c0190612407565b909150819061244c565b80546000825580612472575050565b61032391600052602060002090810190612407565b90600160401b81116124bc575b8154908083558181106124a657505050565b6103239260005260206000209182019101612407565b6124c4610288565b612494565b8151916124d68383612487565b602080910191600052806000206000925b8484106124f5575050505050565b805182546001600160a01b0319166001600160a01b0391909116178255600190819084019201930192906124e7565b90805180516001600160401b038111612632575b61254c816125468654610c7d565b8661241e565b6020918290601f83116001146125bf57918060809492600496946000926125b4575b50508160011b916000199060031b1c19161785555b810151600185015561259c6040820151600286016124c9565b6125ad6060820151600386016124c9565b0151910155565b01519050388061256e565b90601f198316916125d587600052602060002090565b9260005b81811061261b5750926001928592600498966080989610612602575b505050811b018555612583565b015160001960f88460031b161c191690553880806125f5565b9293866001819287860151815501950193016125d9565b61263a610288565b612538565b610323906005609854600160401b81101561268d575b6001810180609855811015612680575b6098600052026000805160206148ff83398151915201612524565b612688611a1d565b612665565b612695610288565b612655565b9291906126b16020916040865260408601906104b1565b930152565b609c546126cd906107ce906001600160a01b031681565b60409283518092630110a66560e51b825281600460209586935afa908115612899575b60009161287c575b506001600160a01b0316803b1561000e57845162fa7f2760e71b81526001600160a01b038316600482015290600090829060249082905afa801561286f575b61285c575b5061274683610c57565b845190816127578582018093612338565b039161276b601f19938481018352826102f5565b5190209085516127838582019282610ba6858a610bf4565b51902014158061284c575b156128405782511561281d577fb29bf840679333bfbac98f5b6db267f89ef32b09f1371605e68c3f423210b1b493929161280a612818926127cd610316565b92858452830194428652606087850152606080850152600060808501526127fc846127f783610c57565b612524565b6128058461263f565b612a48565b51915192519283928361269a565b0390a1565b6106ba846128296123d2565b905162461bcd60e51b81529182916004830161063f565b6106ba846128296123b4565b50612856816121a4565b1561278e565b806108696128699261029f565b3861273c565b612877612197565b612737565b6128939150833d85116108b4576108a681836102f5565b386126f8565b6128a1612197565b6126f0565b906040516128b3816102bf565b6080600482946040516128ca816106248185610cb7565b8452600181015460208501526040516128ea81610624816002860161200e565b604085015260405161290381610624816003860161200e565b60608501520154910152565b6129446129499160006080604051612926816102bf565b60608152826020820152606060408201526060808201520152610c57565b6128a6565b6020810151156129565790565b6106ba604051612965816102da565b6002815261323160f01b602082015260405191829162461bcd60e51b83526020600484015260248301906104b1565b80548210156129ad575b60005260206000200190600090565b6129b5611a1d565b61299e565b9061163461032392805490600160401b8210156129dd575b600182018155612994565b6129e5610288565b6129d2565b600181106129fa575b6000190190565b612a02612068565b6129f3565b959493906126b192608094612a27612a3a9360a08b5260a08b0190610cb7565b9160208a015288820360408a015261200e565b90868203606088015261200e565b612a5181610c57565b600280820193612a6181866129ba565b612a6b85546129ea565b9260049384820190815560005b609854811015612ade5780612a8f612ab992611a34565b50604089610ba6612aab8351602080820182611913828a612338565b51902014612abe575061207f565b612a78565b87612ad5888301612acf89826129ba565b546129ea565b91015538611941565b509350935050506128187f587d7f822a3f2af25ebf13a25de91348c0af2174890d25670cd88a4d559f2883936001840154925490604051948594600382019186612a07565b908092918237016000815290565b6020908260405193849283378101609781520301902090565b6020908260405193849283378101609981520301902090565b6020908260405193849283378101609b81520301902090565b60405190612b89826102da565b6002825261199960f11b6020830152565b9392612ba5816121a4565b15612ce2575b50612bb68185612b31565b936002850190815415612cd75760009594600392838701975b8651811015612bf75780611658612bec610717612bf2948b612097565b8b6129ba565b612bcf565b50909192939560005b609854811015612c9157612c1381611a34565b5060408987612c3083516020610ba681830183610b80828b612338565b51902014612c48575b50612c439061207f565b612c00565b9894919592836000999592999a01995b8851811015612c805780611658612c75610717612c7b948d612097565b8d6129ba565b612c58565b509295919498509296612c43612c39565b5093509350947f587d7f822a3f2af25ebf13a25de91348c0af2174890d25670cd88a4d559f28839450612818915060018301549360048401549160405195869586612a07565b6106ba6106a2612b7c565b612cf690612cf136848861038e565b6126b6565b38612bab565b60405190612d09826102da565b6002825261191b60f11b6020830152565b600190600119811161208f570190565b80156129fa576000190190565b80548015612d54576000190190612d516115c48383612994565b55565b634e487b7160e01b600052603160045260246000fd5b60405190612d77826102da565b6002825261323760f01b6020830152565b60405190612d95826102da565b6002825261191960f11b6020830152565b60405190612db3826102da565b6002825261064760f31b6020830152565b9190811015612dd45760051b0190565b6109fd611a1d565b356103e0816103e3565b9190811015612e28575b60051b81013590601e198136030182121561000e5701908135916001600160401b03831161000e57602001823603811361000e579190565b612e30611a1d565b612df0565b6001600160a01b0390911681526040602082018190526103e0929101906104b1565b90918060409360208452816020850152848401376000828201840152601f01601f1916010190565b999b94969a9c93959298979190808a148015906130c8575b6130bd57612efc868f968f90156130a9575b612eba612eb5836121a4565b151590565b15613095575b915050612ed161057c36888461038e565b95612ee688612ee136848661038e565b614610565b612efc88612ef5368d8d610a02565b8385612b9a565b6000905b8c8210612f83579950509650505050505050612f2b95506107ce94506107ce93506113259250612b4a565b91823b1561000e57612f579260009283604051809681958294637df8d05560e11b845260048401612e57565b03925af18015612f76575b612f695750565b806108696103239261029f565b612f7e612197565b612f62565b858f938f948f8f612fc5612fbe888093612fb7828f9d978f612fac83612fb192612fcc9c612dc4565b612ddc565b9e612dc4565b3598612de6565b369161038e565b928c612dc4565b359073f5a5b6a677ff77c22c856a2b794bdc5534806c973b1561000e578b8f93958f93968f93976116589861306d9b613060604091825163ff7b96a960e01b81526000818061301f888660048401612e35565b038173f5a5b6a677ff77c22c856a2b794bdc5534806c975af48015613088575b613075575b5061304d610325565b9b8c526001600160a01b031660208c0152565b89015260608801526133ff565b8d908f612f00565b806108696130829261029f565b38613044565b613090612197565b61303f565b6130a482612cf1368b8561038e565b612ec0565b6130b833610ac8368b8561038e565b612ea9565b6106ba6106a2612da6565b50888c1415612e97565b80548210156130ef575b600052600e602060002091020190600090565b6130f7611a1d565b6130dc565b81518155602080830151600180840180546001600160a01b0319166001600160a01b03939093169290921790915591929060028401906040830151938451916001600160401b038311613210575b613158836125468654610c7d565b80601f841160011461319b5750918080926060969594600398600094613190575b50501b9160001990871b1c19161790550151910155565b015192503880613179565b91939495601f1984166131b387600052602060002090565b936000905b8282106131f957505091600397959391856060989694106131e1575b505050811b0190556125ad565b015160001983891b60f8161c191690553880806131d4565b8088869782949787015181550196019401906131b8565b613218610288565b61314a565b9061323d8254600160401b81101561332a575b60019384820181556130d2565b92909261331d575b613250825184612524565b6020828101516005850180546001600160a01b0319166001600160a01b039283161790559060068501906040850151928184519461328e8686612487565b019260005281600020906000935b8585106132ef575050505050505060c0816132c06060600d940151600786016130fc565b6080810151600b8501556125ad6132da60a0830151151590565b600c86019060ff801983541691151516179055565b805183549083166001600160a01b03166001600160a01b03199091161783559386019391860191830161329c565b6133256123f0565b613245565b613332610288565b613230565b98969492959390613354909b9a989b610160808c528b01906104b1565b6001600160a01b0392831660208b8101919091528a820360408c015282825290810196926000905b8382106133d9575050505050928694926133b06133bd936101409896606060009b0152608088019060018060a01b03169052565b85820360a08701526104b1565b9660c084015260e0830152836101008301526101208201520152565b90919293978380600192848c356133ef816103e3565b168152019901949392019061337c565b916134906128189495969361348b6000805160206148df8339815191529994613429609a5461207f565b9283609a556040519360e085018581106001600160401b038211176134c2575b6040528685526001600160a01b038b166020860152613469368a8e610a02565b6040860152876060860152426080860152600060a086015260c0850152612b63565b61321d565b5181516020830151919290916001600160a01b03166060604083015192015192609a5495604051998a9942978b613337565b6134ca610288565b613449565b604051906134dc826102da565b6002825261323960f01b6020830152565b90604051608081018181106001600160401b03821117613547575b6040526060600382948054845260018060a01b03600182015416602085015260405161353b816106248160028601610cb7565b60408501520154910152565b61354f610288565b613508565b9060405160e081018181106001600160401b038211176135e3575b60405260c0600d8294613581816128a6565b845260058101546001600160a01b031660208501526135a260068201612054565b60408501526135b3600782016134ed565b6060850152600b81015460808501526135dc6135d3600c83015460ff1690565b151560a0860152565b0154910152565b6135eb610288565b61356f565b5190610323826108f8565b9081602091031261000e57516103e0816108f8565b99959091610140999561365961367295999e9d9961363a8e9c98968d610160908181520190610cb7565b9060018060a01b039c8d8096166020820152604081840391015261200e565b9360608d01521660808b015289820360a08b0152610cb7565b9860c088015260e0870152151561010086015261012085015216910152565b92909493919460018060a01b03809116845260209516858401526040830152606082015260809260a084830152606051908160a08401526000945b8286106136f85750508060c09394116136eb57601f01601f1916010190565b60008382840101526104ca565b8581015184870160c00152948101946136cc565b61371590610c0b565b60005b81548110156140dc5761372b81836130d2565b5061373e612eb5600c8093015460ff1690565b15613753575b5061374e9061207f565b613718565b61376f8461376a61376485876130d2565b50613554565b6140e1565b8261377a83826130d2565b5091604080519060209182810181613796826009809a01612338565b03916137aa601f19938481018352826102f5565b519020825164045524332360dc1b858201908152906137d481600584015b038581018352826102f5565b51902014613d91575b85611bcc6138006137ee8a896130d2565b50855192839188830195869101612338565b51902082516545524337323160d01b8582019081529061382381600684016137c8565b51902014613b44575b85611bcc61383d6137ee8a896130d2565b5190209082516138638582019282610ba685600790664552433131353560c81b81520190565b51902014613875575b50505050613744565b61387f86856130d2565b5060089081015461389a906107ce906001600160a01b031681565b936138a588876130d2565b506005908101549092906001600160a01b0316946138c38a896130d2565b506007908101548651627eeac760e11b81526001600160a01b03989098166004808a019190915260248901919091529690919081816044818c5afa918215613b37575b600092613b1a575b505061391a8b8a6130d2565b50908b600a80930154821115600014613aab5761395681613950896139418f9589966130d2565b5001546001600160a01b031690565b9c6130d2565b50015495893b1561000e57858f998f8f9d908e9d9a60008f9c8f908f958f9a6139af9861399986928e9a5198899788968795637921219560e11b87528601613691565b03925af18015613a9e575b613a8b575b506130d2565b5001805460ff191660011790558d6139c783826130d2565b509a6139d2916130d2565b5001546001600160a01b0316938d6139ea83826130d2565b50946139f684836130d2565b50015492613a03916130d2565b5001546001600160a01b0316918d613a1b88826130d2565b509b613a26916130d2565b500154938d613a3588826130d2565b50600b015496613a4589836130d2565b50015460ff1697613a55916130d2565b50600d015497519b8c9b019360060190613a6f9a8c613610565b036000805160206148df83398151915291a1388281808061386c565b80610869613a989261029f565b386139a9565b613aa6612197565b6139a4565b613abd9150956139418b97829c6130d2565b9881613ad78d85613ace828b6130d2565b500154986130d2565b50015490893b1561000e57858f998f8f9d908e9d9a60008f9c8f908f958f9a6139af9861399986928e9a5198899788968795637921219560e11b87528601613691565b613b309250803d10611d0757611cf881836102f5565b388061390e565b613b3f612197565b613906565b85613b4f88876130d2565b50600890810154613b6a906107ce906001600160a01b031681565b8b613b758b8a6130d2565b5060079081015487516331a9108f60e11b8152600480820192909252938985602481845afa948515613d84575b600095613d65575b508d8c613bb782826130d2565b50600590810154909790613bd3906001600160a01b03166107ce565b6001600160a01b0390911614613ccc575b8c9350613bf192506130d2565b5001805460ff191660011790558b898b613c0b83826130d2565b5095613c1784836130d2565b5001546001600160a01b031693613c2e84836130d2565b5090613c3a85846130d2565b50015497613c4885846130d2565b5001546001600160a01b0316613c5e85846130d2565b5098613c6a86856130d2565b50600a015493613c7a87826130d2565b50600b015495613c8a88836130d2565b50015460ff1696613c9a916130d2565b50600d0154968d519b8c9b019360060190613cb59a8c613610565b036000805160206148df83398151915291a161382c565b84939850613ce49295508661394183613950936130d2565b500154823b1561000e578751632142170760e11b81526001600160a01b039b8c169681019687529a8f16602087015260408601528c998b958f9360009183919082908490829060600103925af18015613d58575b613d45575b808d8c613be4565b80610869613d529261029f565b38613d3d565b613d60612197565b613d38565b613d7d9195508a3d8c116108b4576108a681836102f5565b9338613baa565b613d8c612197565b613ba2565b85613d9c88876130d2565b50613de4613e61868d8c8b613dc16107ce6107ce6008809a015460018060a01b031690565b91613dcc81836130d2565b5060059081015490978892916001600160a01b031690565b8c51636eb1769f60e11b81526001600160a01b03919091166004808301919091523060248301529390878e81836044818b5afa9283156140cf575b6000936140b0575b50613e368661394187876130d2565b90516370a0823160e01b81526001600160a01b03909116878201908152909a8b918291602090910190565b0381895afa9889156140a3575b600099614084575b50808911613ffa575091613941613e8f926000946130d2565b8b516323b872dd60e01b81526001600160a01b0391821693810193845294166020830152604082019590955291938492839190829060600103925af18015613fed575b613fc0575b505b86613ee48b8a6130d2565b5001805460ff191660011790558b613efc8b8a6130d2565b5091613f088c8b6130d2565b5001546001600160a01b03168b898b613f2183826130d2565b50613f2c84836130d2565b506007015497613f3c85846130d2565b5001546001600160a01b0316613f5285846130d2565b5098613f5e86856130d2565b50600a015493613f6e87826130d2565b50600b015495613f7e88836130d2565b50015460ff1696613f8e916130d2565b50600d0154968d519b8c9b019360060190613fa99a8c613610565b036000805160206148df83398151915291a16137dd565b613fdf90873d8911613fe6575b613fd781836102f5565b8101906135fb565b5038613ed7565b503d613fcd565b613ff5612197565b613ed2565b97509161394161400c926000946130d2565b8b516323b872dd60e01b81526001600160a01b0391821693810193845294166020830152604082019590955291938492839190829060600103925af18015614077575b61405a575b50613ed9565b61407090873d8911613fe657613fd781836102f5565b5038614054565b61407f612197565b61404f565b61409c919950883d8a11611d0757611cf881836102f5565b9738613e76565b6140ab612197565b613e6e565b6140c8919350823d8411611d0757611cf881836102f5565b9138613e27565b6140d7612197565b613e1f565b505050565b90600092835b60408401518051821015614131576001600160a01b0390819061410b908490612097565b511690841614614128575b61412160409161207f565b90506140e7565b60019450614116565b5050929150501561413e57565b6106ba60405161414d816102da565b6002815261323360f01b602082015260405191829162461bcd60e51b83526020600484015260248301906104b1565b9092916001600160401b038111614244575b6141a28161419c8454610c7d565b8461241e565b6000601f82116001146141dc57819293946000926141d1575b50508160011b916000199060031b1c1916179055565b0135905038806141bb565b601f198216946141f184600052602060002090565b91805b87811061422c575083600195969710614212575b505050811b019055565b0135600019600384901b60f8161c19169055388080614208565b909260206001819286860135815501940191016141f4565b61424c610288565b61418e565b9896999a9b9394959161427561179e8d8f9b94969b612fbe89612ee136848661038e565b838914801590614394575b6130bd578c936142cd868e614297612eb5836121a4565b15614380575b9150506142ae61057c36888461038e565b956142be88612ee136848661038e565b6142cd88612ef5368d8d610a02565b6000905b8c82106142fc579950509650505050505050612f2b95506107ce94506107ce93506113259250612b4a565b858f938f948f8f612fc5612fbe888093612fb7828f9d978f612fac83612fb1926143259c612dc4565b359073f5a5b6a677ff77c22c856a2b794bdc5534806c973b1561000e578b8f93958f93968f9397611658986143789b613060604091825163ff7b96a960e01b81526000818061301f888660048401612e35565b8d908f6142d1565b61438f82612cf1368b8561038e565b61429d565b50878b1415614280565b6143a88154610c7d565b90816143b2575050565b81601f600093116001146143c4575055565b818352602083206143e091601f0160051c810190600101612407565b8160208120915555565b60036000918281558260018201556144046002820161439e565b0155565b6112606144149161290f565b80549060008082558261442657505050565b6001917f1249249249249249249249249249249249249249249249249249249249249249841183166144d5575b81526020812091600e9384028301925b838110614471575050505050565b8061447c869261439e565b838382015561448d60028201612463565b61449960038201612463565b8360048201558360058201556144b160068201612463565b6144bd600782016143ea565b83600b82015583600c82015583600d82015501614463565b6144dd612068565b614453565b81601f8201121561000e5780516144f881610364565b9261450660405194856102f5565b8184526020828401011161000e576103e0916020808501910161047c565b60208183031261000e5780516001600160401b039182821161000e57016101208184031261000e57614554610344565b9261455e82612177565b845260208201516020850152604082015160408501526060820151606085015261458a608083016135f0565b608085015260a082015160a085015260c082015160c08501526145af60e08301612177565b60e0850152610100928383015190811161000e576145cd92016144e2565b9082015290565b604051906145e1826102da565b6002825261033360f41b6020830152565b604051906145ff826102da565b60028252610c8d60f21b6020830152565b609c5490919061462a906107ce906001600160a01b031681565b91604092835192838092630110a66560e51b8252602093849160049788915afa9081156147ec575b6000916147cf575b506001600160a01b0316803b1561000e57855162fa7f2760e71b81526001600160a01b0390921685830190815260009183918290819060200103915afa80156147c2575b6147af575b506146b66107ce6107ce61132585610c31565b818551809263317c557160e01b825281806146d3888a830161063f565b03915afa9182156147a2575b600092614785575b50506146f957506106ba611c1d6145f2565b61472c6000826147136107ce6107ce61132560c097610c31565b8651808095819463198cb35b60e01b835289830161063f565b03915afa908115614778575b600091614757575b5001511561474c575050565b6106ba611c1d6145d4565b614772913d8091833e61476a81836102f5565b810190614524565b38614740565b614780612197565b614738565b61479b9250803d10613fe657613fd781836102f5565b38806146e7565b6147aa612197565b6146df565b806108696147bc9261029f565b386146a3565b6147ca612197565b61469e565b6147e69150833d85116108b4576108a681836102f5565b3861465a565b6147f4612197565b614652565b60405190614806826102da565b6002825261333160f01b6020830152565b9061482c600261482684610c57565b01612054565b926000805b8551811015614871576148476107178288612097565b6001600160a01b03858116911614614868575b6148639061207f565b614831565b6001915061485a565b5092614884919450614826600391610c57565b9260005b84518110156148c85761489e6107178287612097565b6001600160a01b038481169116146148bf575b6148ba9061207f565b614888565b600193506148b1565b50925050156148d357565b6106ba6106a26120b956fecca517edfbfb04bc5c7b43f59f9f561e3d007cc4c80a5542cb59c1efe93b40652237a976fa961f5921fd19f2b03c925c725d77b20ce8f790c19709c03de4d814a2646970667358221220bd40a70cccd251a38912ebeb91f2da57d8db9b9cb42653d83d202d65b0d693e264736f6c634300080d0033
External libraries
contracts/libraries/TokenActions.sol:TokenActions : 0xf5a5b6a677ff77c22c856a2b794bdc5534806c97