Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 18 from a total of 18 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Confirm Payment ... | 18685331 | 368 days ago | IN | 0 ETH | 0.00311784 | ||||
Confirm Payment ... | 18685330 | 368 days ago | IN | 0 ETH | 0.00842127 | ||||
Confirm Payment ... | 18685329 | 368 days ago | IN | 0 ETH | 0.00314076 | ||||
Confirm Payment ... | 18685328 | 368 days ago | IN | 0 ETH | 0.00928974 | ||||
Confirm Payment ... | 18685326 | 368 days ago | IN | 0 ETH | 0.00328469 | ||||
Confirm Payment ... | 18685325 | 368 days ago | IN | 0 ETH | 0.00906183 | ||||
Confirm Payment ... | 18685324 | 368 days ago | IN | 0 ETH | 0.00315977 | ||||
Confirm Payment ... | 18685322 | 368 days ago | IN | 0 ETH | 0.00919218 | ||||
Confirm Payment ... | 18685321 | 368 days ago | IN | 0 ETH | 0.00321608 | ||||
Confirm Payment ... | 18685320 | 368 days ago | IN | 0 ETH | 0.00905823 | ||||
Initiate Trade | 18685295 | 368 days ago | IN | 0 ETH | 0.01596464 | ||||
Initiate Trade | 18685291 | 368 days ago | IN | 0 ETH | 0.01650287 | ||||
Initiate Trade | 18685287 | 368 days ago | IN | 0 ETH | 0.01581964 | ||||
Initiate Trade | 18685283 | 368 days ago | IN | 0 ETH | 0.01456318 | ||||
Initiate Trade | 18685279 | 368 days ago | IN | 0 ETH | 0.01523378 | ||||
Confirm Payment ... | 18685242 | 368 days ago | IN | 0 ETH | 0.00284259 | ||||
Confirm Payment ... | 18685239 | 368 days ago | IN | 0 ETH | 0.00768353 | ||||
Initiate Subscri... | 18685234 | 368 days ago | IN | 0 ETH | 0.0147281 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
18685137 | 368 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract contains unverified libraries: ApproveAdapterLibrary, SecurityTokenBalancesLibrary, SettlementRepositoryLibrary, SettlementWorkflowLibrary, TransferAdapterLibrary
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Product
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 1000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity 0.8.17; import "./libraries/SecurityTokenBalancesLibrary.sol"; import "./libraries/IterableBalances.sol"; import "./libraries/SettlementRepositoryLibrary.sol"; import "./libraries/SettlementWorkflowLibrary.sol"; import "./libraries/TransferAdapterLibrary.sol"; import "./libraries/ApproveAdapterLibrary.sol"; import "./interfaces/IProduct.sol"; import "./interfaces/ISettlement.sol"; import "./interfaces/IERC20Adapter.sol"; import "../registry/interfaces/IProductRegistry.sol"; import "../utils/Ownable.sol"; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import "../utils/ProductErrorReporter.sol"; error InvalidRegistryAddress(); /** * @dev This contract represents a CAST-compatible financial product * It includes a number of basic financial information about the product (common to all products) * It also contains extended information specific to this product, as a JSON string in field extendedDataJson * It also includes the methods needed to handle Settlement Transactions on this instrument(subscriptions on primary market, secondary * market trades as well as coupons and redemption) -> see ISettlement interface * It also includes the methods needed to interact (almost) as an ERC20 token, enable to interact with DeFi protocols. -> see IERC20Adapter * interface * Supports ERC165 */ contract Product is ISettlement, IProduct, IERC20Adapter, ERC165, Ownable { using SecurityTokenBalancesLibrary for SecurityTokenBalancesLibrary.SecurityTokenBalances; using SettlementRepositoryLibrary for SettlementRepositoryLibrary.SettlementTransactionRepository; using TransferAdapterLibrary for TransferAdapterLibrary.OngoingTransfers; using ApproveAdapterLibrary for ApproveAdapterLibrary.OngoingApproves; // Basic Informations /** * @dev The product's currency */ string public currency; /** * @dev The product's denomination in cents */ uint256 public denominationCent; /** * @dev The product's maturity date (unix timestamp) */ uint256 public maturityDate; /** * @dev The product's governing law */ string public governingLaw; /** * @dev The product's guarantor legal entity */ LegalEntity public guarantor; /** * @dev The product's isin code */ string public isinCode; /** * @dev The product's issuer legal entity */ LegalEntity public issuer; /** * @dev The product's quotation market */ string public listing; /** * @dev The product's name */ string public name; /** * @dev The product's paying agent legal entity */ LegalEntity public payingAgent; /** * @dev The product's type code (e.g. sgforge.com/bond/V1) */ string public productType; /** * @dev The product's registrar legal entity */ LegalEntity public registrar; /** * @dev The product's settlement agent legal entity */ LegalEntity public settlementAgent; /** * @dev The product's symbol */ string public symbol; /** * @dev The product's state */ ProductState public state; /** * @dev This URL where the Settlement Transaction Repository can be reached * The STR can provided the confidential part of the Settlement Transactions to the counterparts (authentication with ethereum private key) */ string public strUrl; /** * @dev The issuer's issuance program this product is part of */ string public program; /** * @dev This product's series number */ string public series; /** * @dev This product's note status */ string public noteStatus; /** * @dev JSON string of extended information about the product. Can be roughly anything. * Will be used to hold financial information specific to a some products. */ string public extendedDataJson; /** * @dev String holding ESG information about the product (JSON format) */ string public esg; /** * @dev This product's form of the node (e.g. Registered) */ string public formOfNote; /** * @dev This product's FIGI code */ string public figi; /** * @dev The address of a previous contract that is replaced with this one (allows to keep track of successive contract migrations) */ address public previousContract; /** * @dev Extended data(JSON string) associated with specific business operations */ mapping(uint256 => string) public operationExtendedDataJson; /** * @dev The product's balances. Handles total and locked balance. */ SecurityTokenBalancesLibrary.SecurityTokenBalances private securityTokenBalances; /** * @dev The product's settlement transaction repository * Contains all Settlement Transactions involving this product. */ SettlementRepositoryLibrary.SettlementTransactionRepository private settlementTransactionRepository; /** * @dev Ongoing two-steps transfers. * See IERC20Adapter */ TransferAdapterLibrary.OngoingTransfers private ongoingTransfers; /** * @dev Ongoing two-steps approves * See IERC20Adapter */ ApproveAdapterLibrary.OngoingApproves private ongoingApproves; /** * @dev The version number of this smart contract. */ string public constant version = "1.1"; // Tranches related informations Tranche[] public tranches; /** * @dev The product total issued nominal amount(includes all tranches) */ uint256 public seriesNominalAmountCent; /** * @dev The product outstanding nominal amount(includes all not-burnt tokens) */ uint256 public seriesOutstandingNominalAmountCent; /** * @dev The product redeemed amount(i.e. burnt tokens) */ uint256 public seriesRedeemedAmountCent; /** * @dev The total number of (not burnt) tokens */ uint256 public totalSupply; /** * @dev The different states a product can have * Product are initially in the `Created` state. * Once at list one subscription operation has been initiated, they move to the `Running` state. * Once a redemption operation has been initiated, they move to the `Redeemed` state, which is the product's final state. * Once a product is in the `Redeemed` state, no more Settlement Transaction may be initiated on this product. * */ enum ProductState { Undefined, Created, Running, Redeemed } constructor(BasicProductInput memory basicProductInput) Ownable(basicProductInput.registrar.account){ isinCode = basicProductInput.isinCode; name = basicProductInput.name; symbol = basicProductInput.symbol; denominationCent = basicProductInput.denominationCent; maturityDate = basicProductInput.maturityDate; governingLaw = basicProductInput.governingLaw; listing = basicProductInput.listing; state = ProductState.Created; currency = basicProductInput.currency; registrar = LegalEntity( basicProductInput.registrar.lei, basicProductInput.registrar.account ); if(basicProductInput.settlementAgent.account == address(0)) revert ZeroAddressCheck(); settlementAgent = LegalEntity( basicProductInput.settlementAgent.lei, basicProductInput.settlementAgent.account ); payingAgent = LegalEntity( basicProductInput.payingAgent.lei, basicProductInput.payingAgent.account ); issuer = LegalEntity( basicProductInput.issuer.lei, basicProductInput.issuer.account ); securityTokenBalances.setIssuer(issuer.account); guarantor = LegalEntity( basicProductInput.guarantor.lei, basicProductInput.guarantor.account ); strUrl = basicProductInput.strUrl; productType = basicProductInput.productType; program = basicProductInput.program; series = basicProductInput.series; noteStatus = basicProductInput.noteStatus; formOfNote = basicProductInput.formOfNote; extendedDataJson = basicProductInput.extendedDataJson; esg = basicProductInput.esg; figi = basicProductInput.figi; previousContract = basicProductInput.previousContract; for (uint256 i = 0; i < basicProductInput.initialTranches.length; i++) { internalCreateTranche(basicProductInput.initialTranches[i]); } if (basicProductInput.initialBalances.length > 0) { uint256 balanceSupply = 0; for ( uint256 i = 0; i < basicProductInput.initialBalances.length; i++ ) { uint256 value = basicProductInput.initialBalances[i].balance; address to = basicProductInput.initialBalances[i].account; securityTokenBalances.mint(to, value); balanceSupply += value; } if (balanceSupply != totalSupply) revert TotalSupplyNotMatchTotalInitialSupply(); } else { securityTokenBalances.mint(issuer.account, totalSupply); } } /** * @dev ERC165. Indicates that the product implements the ISettlement,IERC20Adapter and IProduct interfaces. */ function supportsInterface(bytes4 interfaceId) override public view returns (bool) { return interfaceId == type(ISettlement).interfaceId || interfaceId == type(IERC20Adapter).interfaceId || interfaceId == type(IProduct).interfaceId || super.supportsInterface(interfaceId); } // Basic Token /** * @dev Shortcut to the account of the issuer legal entity */ function issuerAccount() external view returns (address) { return issuer.account; } /** * @dev Shortcut to the Legal Entity ID of the issuer legal entity */ function issuerLEI() external view returns (string memory) { return issuer.lei; } /** * @dev Shortcut to the account of the settlement agent legal entity */ function settlementAgentAccount() external view returns (address) { return settlementAgent.account; } /** * @dev Shortcut to the Legal Entity ID of the settlement agent legal entity */ function settlementAgentLEI() external view returns (string memory) { return settlementAgent.lei; } /** * @dev Shortcut to the account of the paying agent legal entity */ function payingAgentAccount() external view returns (address) { if (payingAgent.account == address(0)) revert PayingAgentNotSet(); return payingAgent.account; } /** * @dev Shortcut to the Legal Entity ID of the paying agent legal entity */ function payingAgentLEI() external view returns (string memory) { if (bytes(payingAgent.lei).length == 0) revert PayingAgentNotSet(); return payingAgent.lei; } /** * @dev Shortcut to the account of the registrar legal entity */ function registrarAccount() external view returns (address) { return registrar.account; } /** * @dev Shortcut to the Legal Entity ID of the registrar legal entity */ function registrarLEI() external view returns (string memory) { return registrar.lei; } /** * @dev Shortcut to the account of the guarantor legal entity */ function guarantorAccount() external view returns (address) { if (guarantor.account == address(0)) revert GuarantorNotSet(); return guarantor.account; } /** * @dev Shortcut to the Legal Entity ID of the guarantor legal entity */ function guarantorLEI() external view returns (string memory) { if (bytes(guarantor.lei).length == 0) revert GuarantorNotSet(); return guarantor.lei; } /** * @dev Return details of all tranches */ function getTranches() external view returns (Tranche[] memory) { return tranches; } // Modifiers /** * @dev Checks the product is not redeemed yet */ modifier onlyNotRedeemedProduct() { if (state >= ProductState.Redeemed) revert ProductIsFullyRedeemed(); _; } /** * @dev Checks there is no ongoing approve request for the same spender */ modifier onlyOnAvailableSpender(address spender) { if (ongoingApproves.hasOngoingApprove[msg.sender][spender]) revert OwnerHasOngoingApprove(); _; } /** * @dev Used to protect methods that only the product's settlement agent can call */ modifier settlerOnly() { if (msg.sender != settlementAgent.account) revert UnauthorizedSettler(); _; } /** * @dev Allows to change the product's extended data descriptor * NB: Only the registrar can call this method */ function setExtendeDataJson(string memory _extendedDataJson) external onlyRegistrar { extendedDataJson = _extendedDataJson; } /** * @dev Allows to change the product's ESG data descriptor * NB: Only the registrar can call this method */ function setEsg(string memory _esg) external onlyRegistrar { esg = _esg; } // [ERC-20] Only function balanceOf(address _owner) public view returns (uint256 balance) { return securityTokenBalances.getBalance(_owner); } /** * @dev Initiates two-step simple transfer(cf IERC20Adapter) and sends corresponding `TransferRequest` event */ function transfer(address _to, uint256 _value) external virtual override returns (bool) { if (_value == 0) revert ZeroValueCheck(); if (_to == msg.sender) revert InvalidReceiver(); bytes32 transferHash = ongoingTransfers.addTransfer( securityTokenBalances, msg.sender, _to, _value, false, address(0) ); emit Transfer(msg.sender, _to, 0); // Required by https://eips.ethereum.org/EIPS/eip-20#transfer emit TransferRequest(transferHash, msg.sender, _to, _value); return true; } /** * @dev Initiates two-step approve(cf IERC20Adapter) and sends corresponding `ApproveRequest` event */ function approve(address _spender, uint256 _value) external virtual override onlyOnAvailableSpender(_spender) returns (bool) { bytes32 approveHash = ongoingApproves.addApprove( securityTokenBalances, msg.sender, _spender, _value ); emit ApproveRequest(approveHash, msg.sender, _spender, _value); return true; } /** * @dev Validates two-step transfer(cf IERC20Adapter) and sends corresponding `TransferValidated` event * NB: Only the registrar can call this method */ function validateTransfer(bytes32 transferHash) external override onlyRegistrar returns (bool) { ongoingTransfers.validateTransfer(securityTokenBalances, transferHash); emit TransferValidated(transferHash); return true; } /** * @dev Rejects two-step transfer(cf IERC20Adapter) and sends corresponding `TransferRejected` event * Unlocks token if simple transfer * Restore allowance if tranferFrom * NB: Only the registrar can call this method */ function rejectTransfer(bytes32 transferHash) external override onlyRegistrar returns (bool) { ongoingTransfers.rejectTransfer(transferHash); TransferAdapterLibrary.Transfer memory transferRequest = ongoingTransfers.transfers[transferHash]; if (transferRequest.isTransferFrom) { ongoingApproves.allowances[transferRequest.from][ transferRequest.spender ] += transferRequest.value; } else { securityTokenBalances.unlock( transferRequest.from, transferRequest.value ); } emit TransferRejected(transferHash); return true; } /** * @dev Validates two-step approve(cf IERC20Adapter) and sends corresponding `ApproveValidated` event * NB: Only the registrar can call this method */ function validateApprove(bytes32 approveHash) external override onlyRegistrar returns (bool) { ongoingApproves.validateApprove(approveHash); ApproveAdapterLibrary.Approve memory approveRequest = ongoingApproves .approves[approveHash]; emit Approval( approveRequest.owner, approveRequest.spender, approveRequest.value ); emit ApproveValidated(approveHash); return true; } /** * @dev Rejects two-step transfer(cf IERC20Adapter) and sends corresponding `ApproveRejected` event * NB: Only the registrar can call this method */ function rejectApprove(bytes32 approveHash) external override onlyRegistrar returns (bool) { ongoingApproves.rejectApprove(securityTokenBalances, approveHash); emit ApproveRejected(approveHash); return true; } /** * @dev Returns current allowance for provided `owner` and `spender` */ function allowance(address owner, address spender) external view override returns (uint256) { return ongoingApproves.allowance(owner, spender); } /** * @dev Initiates two-step transferFrom(cf IERC20Adapter) and sends corresponding `TransferRequest` event */ function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool) { bytes32 transferHash = ongoingApproves.transferFrom( securityTokenBalances, ongoingTransfers, msg.sender, from, to, amount ); emit TransferRequest(transferHash, msg.sender, to, amount); return true; } /** * @dev Security tokens are not divisible. * Only an integer number of tokens can be manipulated */ function decimals() public pure returns (uint8) { return 0; } /** * @dev Burn the given `quantity` of tokens * The product's totalSupply is updated accordingly. * NB : only the product's registrar can call this method */ function burn(uint256 quantity) public onlyRegistrar { internalBurn(issuer.account, quantity); } function internalBurn(address account, uint256 quantity) internal { securityTokenBalances.burn(account, quantity); seriesRedeemedAmountCent += quantity * denominationCent; recomputeTotalSupply(); } // IBasicToken /** * @dev Returns all balances as an array of Balance structures(including total and locked balance) */ function getFullBalances() public view returns (SecurityTokenBalancesLibrary.Balance[] memory value) { return securityTokenBalances.getFullBalances(); } /** * @dev Returns balance of `owner` as a Balance structures(including total and locked balance) */ function getFullBalance(address owner) public view returns (SecurityTokenBalancesLibrary.Balance memory value) { return securityTokenBalances.getFullBalance(owner); } /** * @dev Returns balance of `owner` (this is the total balance, which includes locked tokens) */ function getBalance(address _address) public view returns (uint256 value) { return securityTokenBalances.getBalance(_address); } /** * @dev Allows to update the STR's URL * NB : only the product's registrar can call this method */ function setStrUrl(string memory _strUrl) public onlyRegistrar { strUrl = _strUrl; } // ISettlement /** * @dev Initiate a Subscription Settlement Transaction (counterparty buys product on primary market from the product's issuer) * and sends the corresponding `SubscriptionInitiated` event * The tokens are locked waiting for the cash leg to settle (see functions confirmPaymentReceived/confirmPaymentTransferred) * NB : only the product's registrar can call this method * NB : the call fails if the product has previously been redeemed */ function initiateSubscription( SettlementRepositoryLibrary.PartialSettlementTransaction memory partialSettlementTransaction ) public override onlyRegistrar onlyNotRedeemedProduct { SettlementWorkflowLibrary.initiateSubscription( settlementTransactionRepository, securityTokenBalances, partialSettlementTransaction ); state = ProductState.Running; emit SubscriptionInitiated(partialSettlementTransaction.txId); } /** * @dev Initiate a Trade Settlement Transaction (one counterparty buys, the other sells) * and sends the corresponding `TradeInitiated` event * The tokens are locked waiting for the cash leg to settle (see functions confirmPaymentReceived/confirmPaymentTransferred) * NB : only the product's registrar can call this method * NB : the call fails if the product has previously been redeemed */ function initiateTrade( SettlementRepositoryLibrary.PartialSettlementTransaction memory partialSettlementTransaction ) public override onlyRegistrar onlyNotRedeemedProduct { SettlementWorkflowLibrary.initiateTrade( settlementTransactionRepository, securityTokenBalances, partialSettlementTransaction ); state = ProductState.Running; emit TradeInitiated(partialSettlementTransaction.txId); } /** * @dev Execute unilateral Transfer Settlement Transactions * and sends the corresponding `TransferExecuted` event * As there is no cash leg to settle, the tokens are transfered right away and the Settlement Transaction is marked as Settled * NB : only the product's registrar can call this method */ function executeTransfer( SettlementRepositoryLibrary.PartialSettlementTransaction memory partialSettlementTransaction ) external override onlyRegistrar onlyNotRedeemedProduct{ SettlementWorkflowLibrary.executeTransfer( settlementTransactionRepository, securityTokenBalances, partialSettlementTransaction ); settlementTransactionRepository.setSettlementTransactionStatus( partialSettlementTransaction.txId, SettlementRepositoryLibrary.SettlementTransactionStatus.Settled ); emit TransferExecuted(partialSettlementTransaction.txId); } /** * @dev Initiate a Redemption Settlement Transactions (issuer redeems product to all holders and gets the tokens back) * and sends the corresponding `RedemptionInitiated` event * The tokens are locked waiting for the cash leg to settle (see functions confirmPaymentReceived/confirmPaymentTransferred) * NB : only the product's registrar can call this method * NB : the call fails if the product has previously been redeemed * NB : extended data in the form of JSON string can be associated with this operation */ function initiateRedemption( SettlementRepositoryLibrary.PartialSettlementTransaction[] memory partialSettlementTransactions, string memory extendedData ) public override onlyRegistrar onlyNotRedeemedProduct { uint256[] memory ids = new uint256[]( partialSettlementTransactions.length ); SettlementWorkflowLibrary.initiateRedemption( settlementTransactionRepository, securityTokenBalances, partialSettlementTransactions ); uint256 operationId = partialSettlementTransactions[0].operationId; operationExtendedDataJson[operationId] = extendedData; for (uint256 i = 0; i < partialSettlementTransactions.length; i++) { ids[i] = partialSettlementTransactions[i].txId; } state = ProductState.Redeemed; emit RedemptionInitiated(ids); } /** * @dev Initiate a Coupon Settlement Transactions (issuer pays coupon to all holders) * and sends the corresponding `CouponInitiated` event * NB: the tokens are not locked for this kind of transaction * NB : only the product's registrar can call this method * NB : the call fails if the product has previously been redeemed * NB : extended data in the form of JSON string can be associated with this operation */ function initiateCoupon( SettlementRepositoryLibrary.PartialSettlementTransaction[] memory partialSettlementTransactions, string memory extendedData ) public override onlyRegistrar onlyNotRedeemedProduct { uint256[] memory ids = new uint256[]( partialSettlementTransactions.length ); SettlementWorkflowLibrary.initiateCoupon( settlementTransactionRepository, partialSettlementTransactions ); uint256 operationId = partialSettlementTransactions[0].operationId; operationExtendedDataJson[operationId] = extendedData; for (uint256 i = 0; i < partialSettlementTransactions.length; i++) { ids[i] = partialSettlementTransactions[i].txId; } emit CouponInitiated(ids); } /** * @dev Confirms that the payment for Settlement Transaction with id `_settlementTransactionId` was received * and sends the corresponding `PaymentReceived` event * The tokens are actually transferred to the recipient (except for Coupon where no token is exchanged) * If the Settlement Transaction is part of a Redemption operation, the tokens are burnt right after being transferred back to the issuer. * The Settlement Transaction state moves to Processed * The call fails if the Settlement Transaction with id `_settlementTransactionId` is not found in the repository * The call fails if the Settlement Transaction is not in the Acknowledged state. * NB : only the product's settlement agent can call this method */ function confirmPaymentReceived(uint256 _settlementTransactionId) external override settlerOnly { SettlementRepositoryLibrary.SettlementTransaction memory settlementTransaction = settlementTransactionRepository .getSettlementTransactionById(_settlementTransactionId); if ( settlementTransaction.operationType == SettlementRepositoryLibrary.OperationType.Undefined ) revert InvalidOperationType(); _handleConfirmPaymentReceived(_settlementTransactionId); } /** * @dev Internal method that does the actual job of `confirmPaymentReceived` */ function _handleConfirmPaymentReceived(uint256 settlementTransactionId) internal { SettlementRepositoryLibrary.SettlementTransaction memory st = settlementTransactionRepository .getSettlementTransactionById(settlementTransactionId); if ( st.status != SettlementRepositoryLibrary.SettlementTransactionStatus.Acknowledged ) revert SettlementTransactionNotInAcknowledgedState(); if ( st.operationType != SettlementRepositoryLibrary.OperationType.Coupon ) { securityTokenBalances.transferLocked( st.deliverySenderAccountNumber, st.deliveryReceiverAccountNumber, st.deliveryQuantity ); } if ( st.operationType == SettlementRepositoryLibrary.OperationType.Redemption ) { internalBurn( st.deliveryReceiverAccountNumber, st.deliveryQuantity ); } settlementTransactionRepository.setSettlementTransactionStatus( settlementTransactionId, SettlementRepositoryLibrary.SettlementTransactionStatus.Processed ); emit PaymentReceived(settlementTransactionId, st.operationType); } /** * @dev Confirms that the payment for Settlement Transaction with id `_settlementTransactionId` was transferred to the recipient * and sends the corresponding `PaymentTransferred` event * The Settlement Transaction state moves to Settled * The call fails if the Settlement Transaction with id `_settlementTransactionId` is not found in the repository * The call fails if the Settlement Transaction is not in the Processed state. * NB : only the product's settlement agent can call this method */ function confirmPaymentTransferred(uint256 _settlementTransactionId) external override settlerOnly { _handleConfirmPaymentTransferred(_settlementTransactionId); } /** * @dev Internal method that does the actual job of `confirmPaymentTransferred` */ function _handleConfirmPaymentTransferred(uint256 _settlementTransactionId) internal { SettlementRepositoryLibrary.SettlementTransaction memory st = settlementTransactionRepository .getSettlementTransactionById(_settlementTransactionId); if ( st.operationType == SettlementRepositoryLibrary.OperationType.Undefined ) revert InvalidOperationType(); if ( st.status != SettlementRepositoryLibrary.SettlementTransactionStatus.Processed ) revert SettlementTransactionNotInProcessedState(); settlementTransactionRepository.setSettlementTransactionStatus( _settlementTransactionId, SettlementRepositoryLibrary.SettlementTransactionStatus.Settled ); emit PaymentTransferred(_settlementTransactionId, st.operationType); } /** * @dev Returns the details of Settlement Transaction with id `_settlementTransactionId` */ function getSettlementTransaction(uint256 _settlementTransactionId) external view returns (SettlementRepositoryLibrary.SettlementTransaction memory) { return settlementTransactionRepository.getSettlementTransactionById( _settlementTransactionId ); } /** * @dev Cancels ongoing settlement transaction with id `settlementTransactionId` * and sends the corresponding `SettlementTransactionCancelled` event * Unlocks tokens * Fails if the settlement transaction is not in the Acknowledged state. * NB : only the product's registrar can call this method * */ function cancelSettlementTransaction(uint256 settlementTransactionId) public override onlyRegistrar { SettlementWorkflowLibrary.cancelSettlementTransaction( settlementTransactionRepository, securityTokenBalances, settlementTransactionId ); emit SettlementTransactionCancelled(settlementTransactionId); } /** * @dev Internal function that recomputes the totalSupply when it changes (mint/burn) * */ function recomputeTotalSupply() internal { seriesOutstandingNominalAmountCent = seriesNominalAmountCent - seriesRedeemedAmountCent; totalSupply = seriesOutstandingNominalAmountCent / denominationCent; } /** * @dev Internal function that adds a new tranche and updates aggregated amounts accordingly. * */ function internalCreateTranche(Tranche memory newTranche) internal { tranches.push(newTranche); seriesNominalAmountCent += newTranche.nominalAmountCent; recomputeTotalSupply(); } /** * @dev Issue a new tranche of tokens for the same product * Mints the corresponding number of tokens * The product's totalSupply is updated accordingly. * NB : only the product's registrar can call this method */ function createTranche(Tranche memory newTranche) public onlyRegistrar { securityTokenBalances.mint(issuer.account, newTranche.nominalAmountCent / denominationCent); internalCreateTranche(newTranche); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
pragma solidity 0.8.17; /** * @dev IERC20Adapter is an interface allowing to (mostly) comply with the ERC20 standard while remaining compliant with * the financial regulations(mostly KYC and due dilligence obligations). * Each call to transfer()/transferFrom() or approve() has to be reviewed by *some* validator authority before either proceeding (by calling validateTransfer() * /validateApprove()) or cancelling (by calling rejectTransfer()/rejectApprove()) * see TransferAdapterLibrary and ApproveAdapteLibrary for implementation. */ interface IERC20Adapter { /** * @dev Initiate a transfer request. Same semantic as ERC20's transfer function although the transfer * will only actually occur once reviewed by validator(who will call validateTransfer) */ function transfer(address _to, uint256 _value) external returns (bool); /** * @dev Actually performs the transfer request corresponding to the given `transferHash` * Called by the validator authority */ function validateTransfer(bytes32 transferHash) external returns (bool); /** * @dev Rejects(and thus, actually cancels) the transfer request corresponding to the given `transferHash` * Called by the validator authority */ function rejectTransfer(bytes32 transferHash) external returns (bool); /** * @dev Initiate an approve request. Same semantic as ERC20's approve function although the approve * will only actually occur once reviewed by validator(who will call validateApprove) */ function approve(address _spender, uint256 _value) external returns (bool); /** * @dev Same semantic as ERC20's allowance function */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Initiate a transferFrom request. Same semantic as ERC20's transferFrom function although the transferFrom * will only actually occur once reviewed by validator(who will call validateTransfer) */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); /** * @dev Actually performs the approve request corresponding to the given `transferHash` * Called by the validator authority */ function validateApprove(bytes32 approveHash) external returns (bool); /** * @dev Rejects(and thus, actually cancels) the approve request corresponding to the given `transferHash` * Called by the validator authority */ function rejectApprove(bytes32 approveHash) external returns (bool); /** * @dev Emitted when a transfer actuelly occurs(that is, when validateTransfer() is called by the validator authority */ event Transfer(address indexed _from, address indexed _to, uint256 _value); /** * @dev Emitted when an approve request is initiated */ event ApproveRequest( bytes32 approveHash, address indexed owner, address indexed spender, uint256 value ); /** * @dev Emitted when an approve request is rejected */ event ApproveRejected(bytes32 approveHash); /** * @dev Emitted when an approve request is validated */ event ApproveValidated(bytes32 approveHash); /** * @dev Emitted when an approve actually occurs(that is, when validateApprove() is called by the validator authority */ event Approval( address indexed owner, address indexed spender, uint256 value ); /** * @dev Emitted when a transfer request is initiated */ event TransferRequest( bytes32 transferHash, address indexed from, address indexed to, uint256 value ); /** * @dev Emitted when a transfer request is rejected */ event TransferRejected(bytes32 transferHash); /** * @dev Emitted when a transfer request is validated */ event TransferValidated(bytes32 transferHash); }
pragma solidity 0.8.17; /** * @dev This interface mostly lists all structures used by the Product contract */ // Maybe add common functions for products interface IProduct { /** * @dev Details of a legal entity */ struct LegalEntity { /** * @dev Legal Entity Identifier of the legal entity */ string lei; /** * @dev Account address of the legal entity */ address account; } /** * @dev Describes an issuance tranche */ struct Tranche { uint256 nominalAmountCent; uint256 issueDate; } /** * @dev Represents a simple balance with value `balance` for address `account` */ struct InitBalance { address account; uint256 balance; } // pourquoi pas dans ISettlement ? event TransferExecuted(uint256 settlementTransactionId); /** * @dev This structure describes the parameters of the product to create/issue * Most parameters are financial characteristics of the product */ struct BasicProductInput { /** * @dev The balances to setup at the contract's creation * Used when migrating from an existing contract with existing balances */ InitBalance[] initialBalances; /** * @dev The details of the initial issuance tranches */ Tranche[] initialTranches; /** * @dev The address of a previous contract that is replaced with this one (allows to keep track of successive contract migrations) */ address previousContract; /** * @dev FIGI code of the product(optional) */ string figi; /** * @dev JSON string of extended information about the product. Can be roughly anything. * Will be used to hold financial information specific to a some products. */ string extendedDataJson; /** * @dev String holding ESG information about the product (JSON format) */ string esg; /** * @dev This product's note status */ string noteStatus; /** * @dev This product's form of the node (e.g. Registered) */ string formOfNote; /** * @dev Name of the issuance series (a group of tranches) */ string series; /** * @dev The issuer's issuance program this product is part of */ string program; /** * @dev The URL of the Settlement Transaction Repository that gives access to confidential information in the Settlement Transactions */ string strUrl; /** * @dev The type of the financial product */ string productType; /** * @dev Details of the product's guarantor legal entity */ LegalEntity guarantor; /** * @dev Details of the product's issuer legal entity */ LegalEntity issuer; /** * @dev Details of the product's paying agent legal entity */ LegalEntity payingAgent; /** * @dev Details of the product's settlement agent legal entity */ LegalEntity settlementAgent; /** * @dev Details of the product's registrar legal entity */ LegalEntity registrar; /** * @dev The product's currency */ string currency; /** * @dev The address of the IProductRegistry where the product should be listed */ address registryAddress; /** * @dev String describing the market places where the product is listed */ string listing; /** * @dev The governing law of the product */ string governingLaw; /** * @dev The product's maturity date */ uint256 maturityDate; /** * @dev The product's denomination in cents */ uint256 denominationCent; /** * @dev The product's symbol */ string symbol; /** * @dev The product's name */ string name; /** * @dev The product's ISIN code */ string isinCode; } }
pragma solidity 0.8.17; import "../libraries/SettlementRepositoryLibrary.sol"; /** * @dev This interface lists the methods allowing to initiate and settle so-called Settlement Transaction. * Please refer to CAST framework's whitepaper for details about what Settlement Transactions are */ interface ISettlement { /** * @dev Initiate a Subscription Settlement Transaction (counterparty buys product on primary market from the product's issuer) * The tokens are locked waiting for the cash leg to settle (see functions confirmPaymentReceived/confirmPaymentTransferred) */ function initiateSubscription( SettlementRepositoryLibrary.PartialSettlementTransaction calldata partialSettlementTransaction ) external; /** * @dev Initiate a Trade Settlement Transaction (one counterparty buys, the other sells) * The tokens are locked waiting for the cash leg to settle (see functions confirmPaymentReceived/confirmPaymentTransferred) */ function initiateTrade( SettlementRepositoryLibrary.PartialSettlementTransaction calldata partialSettlementTransaction ) external; /** * @dev Initiate a Redemption Settlement Transactions (issuer redeems product to all holders and gets the tokens back) * The tokens are locked waiting for the cash leg to settle (see functions confirmPaymentReceived/confirmPaymentTransferred) */ function initiateRedemption( SettlementRepositoryLibrary.PartialSettlementTransaction[] calldata settlementTransaction, string calldata extendedData ) external; /** * @dev Execute unilateral Transfer Settlement Transactions * As there is no cash leg to settle, the tokens are transfered right away and the Settlement Transaction is marked as Settled */ function executeTransfer( SettlementRepositoryLibrary.PartialSettlementTransaction memory partialSettlementTransaction ) external; /** * @dev Initiate a Coupon Settlement Transactions (issuer pays coupon to all holders) * NB: the tokens are not locked for this kind of transaction */ function initiateCoupon( SettlementRepositoryLibrary.PartialSettlementTransaction[] calldata settlementTransaction, string calldata extendedData ) external; /** * @dev Cancels ongoing settlement transaction with id `settlementTransactionId` */ function cancelSettlementTransaction(uint256 settlementTransactionId) external; /** * @dev Confirms that the payment for Settlement Transaction with id `settlementTransactionId` was correctly received * (by the settlement agent). The tokens are unlocked and transferred to the buyer. Settlement Transaction's status moves to Processed */ function confirmPaymentReceived(uint256 settlementTransactionId) external; /** * @dev Confirms that the payment for Settlement Transaction with id `settlementTransactionId` was correctly transferred to the seller * (by the settlement agent). Settlement Transaction's status moves to Settled */ function confirmPaymentTransferred(uint256 settlementTransactionId) external; /** * @dev Emitted when Subscription Settlement Transaction with id `settlementTransactionId` was initiated. */ event SubscriptionInitiated(uint256 settlementTransactionId); /** * @dev Emitted when Trade Settlement Transaction with id `settlementTransactionId` was initiated. */ event TradeInitiated(uint256 settlementTransactionId); /** * @dev Emitted when Redemption Settlement Transactions with ids `settlementTransactionIds` were initiated. */ event RedemptionInitiated(uint256[] settlementTransactionIds); /** * @dev Emitted when Coupon Settlement Transactions with ids `settlementTransactionId`s were initiated. */ event CouponInitiated(uint256[] settlementTransactionIds); /** * @dev Emitted when payment for Settlement Transaction with id `settlementTransactionId` was reported as received */ event PaymentReceived( uint256 settlementTransactionId, SettlementRepositoryLibrary.OperationType settlementTransactionOperationType ); /** * @dev Emitted when payment for Settlement Transaction with id `settlementTransactionId` was reported as transferred */ event PaymentTransferred( uint256 settlementTransactionId, SettlementRepositoryLibrary.OperationType settlementTransactionOperationType ); /** * @dev Emitted when Settlement Transaction with id `settlementTransactionId` was cancelled */ event SettlementTransactionCancelled(uint256 settlementTransactionId); }
pragma solidity 0.8.17; import "./EncodingUtils.sol"; import "./SecurityTokenBalancesLibrary.sol"; import "./TransferAdapterLibrary.sol"; import { ZeroAddressCheck, InvalidApproveStatus, OwnerHasOngoingApprove, ApproveDoesNotExists, InsufficientAllowance } from "../../utils/ProductErrorReporter.sol"; /** * @dev This library allows to handle two-step approves as described in IERC20Adapter */ library ApproveAdapterLibrary { using SecurityTokenBalancesLibrary for SecurityTokenBalancesLibrary.SecurityTokenBalances; using TransferAdapterLibrary for TransferAdapterLibrary.OngoingTransfers; /** * @dev The different status an approve request can have * Approve requests are initially in the `Created` state * If validated by the validator authority they move to the `Validated` state, which is a final state * If rejected by the validator authority they move to the `Rejected` state, which is a final state * */ enum ApproveStatus { Undefined, Created, Validated, Rejected } /** * @dev The details of an approve request */ struct Approve { /** * @dev The address of the owner */ address owner; /** * @dev The address of the spender */ address spender; /** * @dev The number of tokens that the spender is allowed to spend */ uint256 value; /** * @dev The status of the approve request */ ApproveStatus status; } /** * @dev Structure containing all ongoing approve requests * Requests are indexed by the hash of their content */ struct OngoingApproves { mapping(bytes32 => Approve) approves; /** * @dev Counter of requests, allowing all request to be unique */ uint256 counter; /** * @dev Current allowances indexed by owner address, then by spender address */ mapping(address => mapping(address => uint256)) allowances; /** * @dev Boolean indicating for a couple (owner,spender) whether there is an ongoing approve request * This enables to reject approve request really if there is already an ongoing approve request for the same (owner, spender), thus * avoiding complex issues */ mapping(address => mapping(address => bool)) hasOngoingApprove; } /** * @dev Initiates an approve request * If the requested allowance is less than current allowance, the excess tokens are unlocked * If the requested allowance is more than current allowance, the excess tokens are locked * NB : as the allowance is first reset to 0, the allowance will stay 0 is the request is rejected. * This is by design and not a bug. */ function addApprove( OngoingApproves storage self, SecurityTokenBalancesLibrary.SecurityTokenBalances storage securityTokenBalances, address owner, address spender, uint256 value ) public returns (bytes32) { if (owner == address(0)) revert ZeroAddressCheck(); if (spender == address(0)) revert ZeroAddressCheck(); uint256 currentAllowedAmount = self.allowances[owner][spender]; if (currentAllowedAmount > value) { securityTokenBalances.unlock(owner, (currentAllowedAmount - value)); } else if (currentAllowedAmount < value) { securityTokenBalances.lock(owner, (value - currentAllowedAmount)); } self.allowances[owner][spender] = 0; // reset allowance bytes32 approveHash = EncodingUtils.encodeRequest( owner, spender, value, self.counter ); self.approves[approveHash] = Approve( owner, spender, value, ApproveStatus.Created ); self.hasOngoingApprove[owner][spender] = true; self.counter += 1; return approveHash; } /** * @dev Validates an approve request * Provided there is a matching approve request in state Created, the approve is performed (that is, the allowance is set to the target * value, and the approve request status moves to Validated) */ function validateApprove(OngoingApproves storage self, bytes32 approveHash) public { Approve storage approve = self.approves[approveHash]; if (approve.status == ApproveStatus.Undefined) revert ApproveDoesNotExists(); if (approve.status != ApproveStatus.Created) revert InvalidApproveStatus(); self.allowances[approve.owner][approve.spender] = approve.value; self.hasOngoingApprove[approve.owner][approve.spender] = false; self.approves[approveHash].status = ApproveStatus.Validated; } /** * @dev Rejects an approve request * Provided there is a matching approve request in state Created, the approve is cancelled (that is, the tokens are unlocked * , and the approve request status moves to Validated) * NB: after the request has be rejected, the allowance is 0 (and not the allowance that existed before the request was sent), this * is by design and not a bug */ function rejectApprove( OngoingApproves storage self, SecurityTokenBalancesLibrary.SecurityTokenBalances storage securityTokenBalances, bytes32 approveHash ) public { Approve memory approve = self.approves[approveHash]; if (approve.status == ApproveStatus.Undefined) revert ApproveDoesNotExists(); if (approve.status != ApproveStatus.Created) revert InvalidApproveStatus(); securityTokenBalances.unlock(approve.owner, approve.value); self.hasOngoingApprove[approve.owner][approve.spender] = false; self.approves[approveHash].status = ApproveStatus.Rejected; } /** * @dev Initiates a transferFrom request * This code is here to enable checking the allowance before accepting request */ function transferFrom( OngoingApproves storage self, SecurityTokenBalancesLibrary.SecurityTokenBalances storage securityTokenBalances, TransferAdapterLibrary.OngoingTransfers storage ongoingTransfers, address spender, address from, address to, uint256 value ) public returns (bytes32) { uint256 currentAmount = self.allowances[from][spender]; if (currentAmount < value) revert InsufficientAllowance(); self.allowances[from][spender] -= value; bytes32 transferHash = ongoingTransfers.addTransfer( securityTokenBalances, from, to, value, true, // isTransferFrom spender ); return transferHash; } /** * @dev Returns current allowance for `owner` and `spender` */ function allowance( OngoingApproves storage self, address owner, address spender ) public view returns (uint256) { return self.allowances[owner][spender]; } }
pragma solidity 0.8.17; library EncodingUtils { /** * @dev Computes the hash of a tranfer or approve request * Enables to index requests in mappings */ function encodeRequest( address _from, address _to, uint256 _value, uint256 counter ) internal view returns (bytes32) { return keccak256(abi.encode(block.timestamp, _from, _to, _value, counter)); } }
pragma solidity 0.8.17; error KeyNotInBalances(); /** * @dev An iterable mapping of security token balances. * Handles total and locked balances (locked balance corresponds to tokens that are reserved for an ongoing Settlement Transaction) */ library IterableBalances { struct iterableBalances { mapping(address => Balance) balances; KeyFlag[] keys; uint256 size; } struct Balance { uint256 keyIndex; uint256 total; uint256 locked; } struct KeyFlag { address key; bool deleted; } function insert( iterableBalances storage self, address key, uint256 total ) public { uint256 keyIndex = self.balances[key].keyIndex; self.balances[key].total = total; if (keyIndex == 0) { keyIndex = self.keys.length; self.keys.push(); self.balances[key].keyIndex = keyIndex + 1; self.keys[keyIndex].key = key; self.size++; } } function remove(iterableBalances storage self, address key) public { uint256 keyIndex = self.balances[key].keyIndex; if (keyIndex == 0) revert KeyNotInBalances(); delete self.balances[key]; self.keys[keyIndex - 1].deleted = true; self.size--; } function contains(iterableBalances storage self, address key) public view returns (bool) { return self.balances[key].keyIndex > 0; } function iterate_start(iterableBalances storage self) public view returns (uint256 keyIndex) { return iterate_next(self, type(uint256).max); } function iterate_valid(iterableBalances storage self, uint256 keyIndex) public view returns (bool) { return keyIndex < self.keys.length; } function iterate_next(iterableBalances storage self, uint256 keyIndex) public view returns (uint256 r_keyIndex) { unchecked { keyIndex++; } while (keyIndex < self.keys.length && self.keys[keyIndex].deleted) { keyIndex++; } return keyIndex; } function iterate_get(iterableBalances storage self, uint256 keyIndex) public view returns ( address key, uint256 total, uint256 locked ) { key = self.keys[keyIndex].key; total = self.balances[key].total; locked = self.balances[key].locked; } }
pragma solidity 0.8.17; import "./IterableBalances.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import { InsufficientDisposableBalance, InsufficientBalance, InsufficientLockedBalance } from "../../utils/ProductErrorReporter.sol"; /// @dev Models a address -> uint mapping where it is possible to iterate over all keys. library SecurityTokenBalancesLibrary { using IterableBalances for IterableBalances.iterableBalances; using SafeMath for uint256; struct SecurityTokenBalances { address issuer; IterableBalances.iterableBalances iterableBalances; } modifier onlyWhenBalanceDisposable( SecurityTokenBalances storage self, address _from, uint256 _value ) { if ( self.iterableBalances.balances[_from].total - self.iterableBalances.balances[_from].locked < _value ) revert InsufficientDisposableBalance(); _; } struct Balance { address account; uint256 total; uint256 locked; } event Transfer(address indexed _from, address indexed _to, uint256 _value); // Only for erc20 explorer function setIssuer(SecurityTokenBalances storage self, address key) public { self.issuer = key; } function mint( SecurityTokenBalances storage self, address key, uint256 balance ) public { self.iterableBalances.insert(key, balance); emit Transfer(0x0000000000000000000000000000000000000000, key, balance); } function lock( SecurityTokenBalances storage self, address key, uint256 valueToLock ) public onlyWhenBalanceDisposable(self, key, valueToLock) { self.iterableBalances.balances[key].locked += valueToLock; } function unlock( SecurityTokenBalances storage self, address key, uint256 valueToUnlock ) public { if (self.iterableBalances.balances[key].total < valueToUnlock) revert InsufficientBalance(); if (self.iterableBalances.balances[key].locked < valueToUnlock) revert InsufficientLockedBalance(); self.iterableBalances.balances[key].locked -= valueToUnlock; } function burn( SecurityTokenBalances storage self, address _from, uint256 _value ) public onlyWhenBalanceDisposable(self, _from, _value) { self.iterableBalances.balances[_from].total -= _value; emit Transfer(_from, address(0), _value); } function transferLocked( SecurityTokenBalances storage self, address _from, address _to, uint256 _value ) external { unlock(self, _from, _value); self.iterableBalances.balances[_from].total -= _value; self.iterableBalances.insert( _to, self.iterableBalances.balances[_to].total + _value ); emit Transfer(_from, _to, _value); } // should check this of any security issue? function transfer( SecurityTokenBalances storage self, address _from, address _to, uint256 _value ) external onlyWhenBalanceDisposable(self, _from, _value) { self.iterableBalances.balances[_from].total -= _value; self.iterableBalances.insert( _to, self.iterableBalances.balances[_to].total + _value ); emit Transfer(_from, _to, _value); } // rename to getTotalBalance() function getBalance(SecurityTokenBalances storage self, address _address) external view returns (uint256 balance) { return self.iterableBalances.balances[_address].total; } function getAvailableBalance( SecurityTokenBalances storage self, address _address ) external view returns (uint256 balance) { return self.iterableBalances.balances[_address].total - self.iterableBalances.balances[_address].locked; } function getFullBalance( SecurityTokenBalances storage self, address _address ) external view returns (Balance memory value) { return Balance( _address, self.iterableBalances.balances[_address].total, self.iterableBalances.balances[_address].locked ); } function getFullBalances(SecurityTokenBalances storage self) public view returns (Balance[] memory value) { address tokenHolder = address(0); uint256 balance; uint256 locked; uint256 balancesSize = self.iterableBalances.size; Balance[] memory addressBalanceArray = new Balance[](balancesSize); for ( uint256 index = self.iterableBalances.iterate_start(); self.iterableBalances.iterate_valid(index); index = self.iterableBalances.iterate_next(index) ) { (tokenHolder, balance, locked) = self.iterableBalances.iterate_get( index ); addressBalanceArray[index] = Balance(tokenHolder, balance, locked); } return addressBalanceArray; } }
pragma solidity 0.8.17; import "./SecurityTokenBalancesLibrary.sol"; import { NotSupportedTrustedToken, InvalidSettlementTransactionStatus, SettlementTransactionAlreadyExists } from "../../utils/ProductErrorReporter.sol"; /** * @dev This library handles the Settlement Transaction Repository which is the container for all * Settlement Transactions for a given product */ library SettlementRepositoryLibrary { using SecurityTokenBalancesLibrary for SecurityTokenBalancesLibrary.SecurityTokenBalances; using SettlementRepositoryLibrary for SettlementRepositoryLibrary.SettlementTransactionRepository; /** * @dev The different status a Settlement Transaction can have * Settlement Transactions are initially in the `Created` state. * Once correctly initiated they move to the Acknowledged state. * When the payment of the cash leg (if any) is received by the settlement agent, they move to the Processed state * When the payment of the cash leg is transferred to the receiving end, they move to the Settled state, which is a final state. * Whenever a Settlement Transaction is cancelled, it moves to the Cancelled state, which is a final state */ enum SettlementTransactionStatus { Undefined, Created, Acknowledged, Processed, Settled, Cancelled } /** * @dev The different operation types * Operation types is used to keep track of the type of business operation that a Settlement Transaction is part of. * Some business operations(e.g. Redemption) lead to several Settlement Transactions */ enum OperationType { Undefined, Subscription, Redemption, Trade, Coupon, ExecuteTransfer } /** * @dev The actual Settlement Transaction Repository, which maps Settlement Transaction ids to Settlement Transaction details */ struct SettlementTransactionRepository { mapping(uint256 => SettlementTransaction) settlementTransactionById; // mapping ( settlementtransactionId => settlementtransaction) } /** * @dev The details of a Settlement Transaction * NB: actually these are only the details that can be publicly disclosed on the blockchain * The confidential details are available on a public server called the STR, which URL is available in the strUrl field of the products */ struct SettlementTransaction { /** * @dev The UUID of the Settlement Transaction(as an integer) */ uint256 txId; /** * @dev Optional id of the business operation this Settlement Transaction is part of. */ uint256 operationId; /** * @dev The address of counterparty that delivers the security tokens(a.k.a product) */ address deliverySenderAccountNumber; /** * @dev The address of counterparty that receives the security tokens(a.k.a product) */ address deliveryReceiverAccountNumber; /** * @dev The quantity of security tokens(a.k.a product) that should be delivered */ uint256 deliveryQuantity; /** * @dev Hash of the Settlement Transaction details */ string txHash; /** * @dev Current status of the Settlement Transaction */ SettlementTransactionStatus status; /** * @dev The type of the business operation this Settlement Transaction is part of. */ OperationType operationType; } /** * @dev Partial details of a Settlement Transaction that are passed when initiating the transaction */ struct PartialSettlementTransaction { /** * @dev The UUID of the Settlement Transaction(as an integer) */ uint256 txId; /** * @dev Optional id of the business operation this Settlement Transaction is part of. */ uint256 operationId; /** * @dev The address of counterparty that delivers the security tokens(a.k.a product) * e.g the issuer for a Subscription operation, the investor for a Redemption operation, the seller for a Trade operation */ address deliverySenderAccountNumber; /** * @dev The address of counterparty that receives the security tokens(a.k.a product) * e.g the investor for a Subscription operation, the issuer for a Redemption operation, the buyer for a Trade operation */ address deliveryReceiverAccountNumber; /** * @dev The quantity of security tokens(a.k.a product) that should be delivered */ uint256 deliveryQuantity; /** * @dev Hash of the Settlement Transaction details */ string txHash; } /** * @dev Returns the details of the Settlement Transaction with id `id` */ function getSettlementTransactionById( SettlementTransactionRepository storage settlementTransactionRepository, uint256 id ) public view returns (SettlementTransaction memory) { SettlementTransaction memory settlementTransaction = settlementTransactionRepository .settlementTransactionById[id]; return settlementTransaction; } /** * @dev Updates the status of Settlement Transaction with id `txId` */ function setSettlementTransactionStatus( SettlementTransactionRepository storage settlementTransactionRepository, uint256 txId, SettlementTransactionStatus status ) internal { if (status == SettlementTransactionStatus.Undefined) revert InvalidSettlementTransactionStatus(); SettlementTransaction storage settlementTransaction = settlementTransactionRepository .settlementTransactionById[txId]; settlementTransaction.status = status; } /** * @dev Adds Settlement Transaction with given details to the repository. * NB : status is initialized to `Created` */ function createSettlementTransaction( SettlementTransactionRepository storage settlementTransactionRepository, PartialSettlementTransaction memory partialSettlementTransaction, OperationType operationType ) internal { if ( settlementTransactionRepository .settlementTransactionById[partialSettlementTransaction.txId] .txId == partialSettlementTransaction.txId ) revert SettlementTransactionAlreadyExists(); SettlementTransaction memory newSettlementTransaction = SettlementTransaction({ txId: partialSettlementTransaction.txId, operationId: partialSettlementTransaction.operationId, deliverySenderAccountNumber: partialSettlementTransaction .deliverySenderAccountNumber, deliveryReceiverAccountNumber: partialSettlementTransaction .deliveryReceiverAccountNumber, deliveryQuantity: partialSettlementTransaction.deliveryQuantity, txHash: partialSettlementTransaction.txHash, status: SettlementTransactionStatus.Created, operationType: operationType }); settlementTransactionRepository.settlementTransactionById[ partialSettlementTransaction.txId ] = newSettlementTransaction; } }
pragma solidity 0.8.17; import "./SettlementRepositoryLibrary.sol"; import "./SecurityTokenBalancesLibrary.sol"; import { SettlementTransactionNotInAcknowledgedState, DeliveryReceiverAccountNumberNotMatchTokenIssuer, InvalidSettlementTransactionStatus } from "../../utils/ProductErrorReporter.sol"; /** * @dev This library handles the details of the different Settlement Transaction workflows */ library SettlementWorkflowLibrary { using SettlementRepositoryLibrary for SettlementRepositoryLibrary.SettlementTransactionRepository; using SecurityTokenBalancesLibrary for SecurityTokenBalancesLibrary.SecurityTokenBalances; /** * @dev Mutualizes code for initializing DVP-type Settlement Transactions. * DVP means Delivery Versus Payment, meaning that there are both a token leg and a cash leg * In this case the tokens have to be locked while awaiting payment confirmation by the settlement agent */ function initiateDVP( SettlementRepositoryLibrary.SettlementTransactionRepository storage settlementTransactionRepository, SecurityTokenBalancesLibrary.SecurityTokenBalances storage securityTokenBalances, uint256 settlementTransactionId ) public { SettlementRepositoryLibrary.SettlementTransaction memory st = settlementTransactionRepository .getSettlementTransactionById(settlementTransactionId); securityTokenBalances.lock( st.deliverySenderAccountNumber, st.deliveryQuantity ); settlementTransactionRepository.setSettlementTransactionStatus( settlementTransactionId, SettlementRepositoryLibrary.SettlementTransactionStatus.Acknowledged ); } /** * @dev Initiate a Subscription Settlement Transaction (counterparty buys product on primary market from the product's issuer) * The tokens are locked waiting for the cash leg to settle (see functions confirmPaymentReceived/confirmPaymentTransferred) */ function initiateSubscription( SettlementRepositoryLibrary.SettlementTransactionRepository storage settlementTransactionRepository, SecurityTokenBalancesLibrary.SecurityTokenBalances storage securityTokenBalances, SettlementRepositoryLibrary.PartialSettlementTransaction memory partialSettlementTransaction ) public { settlementTransactionRepository.createSettlementTransaction( partialSettlementTransaction, SettlementRepositoryLibrary.OperationType.Subscription ); initiateDVP( settlementTransactionRepository, securityTokenBalances, partialSettlementTransaction.txId ); } /** * @dev Execute unilateral Transfer Settlement Transactions * As there is no cash leg to settle, the tokens are transfered right away and the Settlement Transaction is marked as Settled */ function executeTransfer( SettlementRepositoryLibrary.SettlementTransactionRepository storage settlementTransactionRepository, SecurityTokenBalancesLibrary.SecurityTokenBalances storage securityTokenBalances, SettlementRepositoryLibrary.PartialSettlementTransaction memory partialSettlementTransaction ) public { settlementTransactionRepository.createSettlementTransaction( partialSettlementTransaction, SettlementRepositoryLibrary.OperationType.ExecuteTransfer ); securityTokenBalances.transfer( partialSettlementTransaction.deliverySenderAccountNumber, partialSettlementTransaction.deliveryReceiverAccountNumber, partialSettlementTransaction.deliveryQuantity ); } /** * @dev Initiate a Trade Settlement Transaction (one counterparty buys, the other sells) * The tokens are locked waiting for the cash leg to settle (see functions confirmPaymentReceived/confirmPaymentTransferred) */ function initiateTrade( SettlementRepositoryLibrary.SettlementTransactionRepository storage settlementTransactionRepository, SecurityTokenBalancesLibrary.SecurityTokenBalances storage securityTokenBalances, SettlementRepositoryLibrary.PartialSettlementTransaction memory partialSettlementTransaction ) public { settlementTransactionRepository.createSettlementTransaction( partialSettlementTransaction, SettlementRepositoryLibrary.OperationType.Trade ); initiateDVP( settlementTransactionRepository, securityTokenBalances, partialSettlementTransaction.txId ); } /** * @dev Initiate a Redemption Settlement Transactions (issuer redeems product to all holders and gets the tokens back) * The tokens are locked waiting for the cash leg to settle (see functions confirmPaymentReceived/confirmPaymentTransferred) */ function initiateRedemption( SettlementRepositoryLibrary.SettlementTransactionRepository storage settlementTransactionRepository, SecurityTokenBalancesLibrary.SecurityTokenBalances storage securityTokenBalances, SettlementRepositoryLibrary.PartialSettlementTransaction[] memory partialSettlementTransactions ) public { for (uint256 i = 0; i < partialSettlementTransactions.length; i++) { if ( securityTokenBalances.issuer != partialSettlementTransactions[i].deliveryReceiverAccountNumber ) revert DeliveryReceiverAccountNumberNotMatchTokenIssuer(); settlementTransactionRepository.createSettlementTransaction( partialSettlementTransactions[i], SettlementRepositoryLibrary.OperationType.Redemption ); initiateDVP( settlementTransactionRepository, securityTokenBalances, partialSettlementTransactions[i].txId ); } } /** * @dev Initiate a Coupon Settlement Transactions (issuer pays coupon to all holders) * NB: the tokens are not locked for this kind of transaction */ function initiateCoupon( SettlementRepositoryLibrary.SettlementTransactionRepository storage settlementTransactionRepository, SettlementRepositoryLibrary.PartialSettlementTransaction[] memory partialSettlementTransactions ) public { for (uint256 i = 0; i < partialSettlementTransactions.length; i++) { settlementTransactionRepository.createSettlementTransaction( partialSettlementTransactions[i], SettlementRepositoryLibrary.OperationType.Coupon ); settlementTransactionRepository.setSettlementTransactionStatus( partialSettlementTransactions[i].txId, SettlementRepositoryLibrary .SettlementTransactionStatus .Acknowledged ); } } /** * @dev Cancels ongoing settlement transaction with id `settlementTransactionId` * Unlocks tokens * Fails if the settlement transaction is not in the Acknowledged state. */ function cancelSettlementTransaction( SettlementRepositoryLibrary.SettlementTransactionRepository storage settlementTransactionRepository, SecurityTokenBalancesLibrary.SecurityTokenBalances storage securityTokenBalances, uint256 settlementTransactionId ) public { SettlementRepositoryLibrary.SettlementTransaction memory settlementTransaction = settlementTransactionRepository .settlementTransactionById[settlementTransactionId]; if ( settlementTransaction.status != SettlementRepositoryLibrary.SettlementTransactionStatus.Acknowledged ) revert SettlementTransactionNotInAcknowledgedState(); securityTokenBalances.unlock( settlementTransaction.deliverySenderAccountNumber, settlementTransaction.deliveryQuantity ); settlementTransactionRepository.setSettlementTransactionStatus( settlementTransactionId, SettlementRepositoryLibrary.SettlementTransactionStatus.Cancelled ); } }
pragma solidity 0.8.17; import "./EncodingUtils.sol"; import "./SecurityTokenBalancesLibrary.sol"; import { ZeroAddressCheck, TransferRequestNotFound, InvalidTransferRequestStatus } from "../../utils/ProductErrorReporter.sol"; /** * @dev This library allows to handle two-step transfers as described in IERC20Adapter */ library TransferAdapterLibrary { using SecurityTokenBalancesLibrary for SecurityTokenBalancesLibrary.SecurityTokenBalances; /** * @dev The different status a transfer request can have * Transfer requests are initially in the `Created` state * If validated by the validator authority they move to the `Validated` state, which is a final state * If rejected by the validator authority they move to the `Rejected` state, which is a final state * */ enum TransferStatus { Undefined, Created, Validated, Rejected } /** * @dev The details of a transfer request */ struct Transfer { /** * @dev The source address of the transfer */ address from; /** * @dev The destination address of the transfer */ address to; /** * @dev The number of tokens to transfer */ uint256 value; /** * @dev The status of the transfer request */ TransferStatus status; /** * @dev Whether this is a transferFrom request (i.e. allowance will be consumed) */ bool isTransferFrom; /** * @dev Address of the spender address, in case of transferFrom request */ address spender; } /** * @dev Structure containing all ongoing transfer requests * Requests are indexed by the hash of their content */ struct OngoingTransfers { mapping(bytes32 => Transfer) transfers; uint256 counter; } /** * @dev Initiates a transfer request * If simple transfer request, the tokens are locked, awaiting either validation or rejection by the validator authority * If transferFrom, the tockens where already locked when the approve request was done */ function addTransfer( OngoingTransfers storage self, SecurityTokenBalancesLibrary.SecurityTokenBalances storage securityTokenBalances, address from, address to, uint256 value, bool isTransferFrom, address spender ) public returns (bytes32) { if (from == address(0)) revert ZeroAddressCheck(); if (to == address(0)) revert ZeroAddressCheck(); if (!isTransferFrom) { securityTokenBalances.lock(from, value); } bytes32 transferHash = EncodingUtils.encodeRequest( from, to, value, self.counter ); self.transfers[transferHash] = Transfer( from, to, value, TransferStatus.Created, isTransferFrom, spender ); self.counter += 1; return transferHash; } /** * @dev Validates a transfer request * Provided there is a matching transfer request in state Created, the transfer is performed (that is, the tokens are * transferred to the destination address, and unlocked, and the transfer request status moves to Validated) */ function validateTransfer( OngoingTransfers storage self, SecurityTokenBalancesLibrary.SecurityTokenBalances storage securityTokenBalances, bytes32 transferHash ) public { Transfer storage transfer = self.transfers[transferHash]; if (transfer.status == TransferStatus.Undefined) revert TransferRequestNotFound(); if (transfer.status != TransferStatus.Created) revert InvalidTransferRequestStatus(); securityTokenBalances.transferLocked( transfer.from, transfer.to, transfer.value ); transfer.status = TransferStatus.Validated; } /** * @dev Rejects a transfer request * Provided there is a matching transfer request in state Created, the transfer is cancelled (that is, the transfer request staus moves * to Rejected) * NB : due to the complexity of the token unlocking logic (depending on whether the transfer request was a transferFrom or not, either * the tokens should be unlocked (simple transfer) or the previous allowance should be restored (transferFrom)) and to avoid complex * inter-dependency between ApproveAdapterLibrary and TransferAdapterLibrary, this logic is perform directly in Product.rejectTransfer */ function rejectTransfer(OngoingTransfers storage self, bytes32 transferHash) public { Transfer storage transfer = self.transfers[transferHash]; if (transfer.status == TransferStatus.Undefined) revert TransferRequestNotFound(); if (transfer.status != TransferStatus.Created) revert InvalidTransferRequestStatus(); transfer.status = TransferStatus.Rejected; } }
pragma solidity 0.8.17; /** * @title The product registry * @dev The registry listing all financial products handled by a given registrar(the owner of the registry). */ interface IProductRegistry { /** * @dev Add a new product to the registry * @param name The name of the product * @param isinCode The ISIN code of the product * @param productAddress The adress of the product's contract */ function listProduct( string calldata name, string calldata isinCode, address productAddress ) external; /** * @dev Get the address of a product by providing its name * @param name The name of the product * @return product The found product's contract address */ function getProductByName(string calldata name) external view returns (address product); /** * @dev Get the address of a product by providing its ISIN code * @param isin The ISIN code of the product * @return product The found product's contract address */ function getProductByIsinCode(string calldata isin) external view returns (address product); /** * @dev Get all products' addresses at once * @return product An array of all producs' addresses */ function getAllProducts() external view returns (address[] memory product); /// @dev Remove a product from the registry /// @param isin The ISIN code of the product function unListProduct(string calldata isin) external; }
pragma solidity 0.8.17; /** * @dev Used when a function reserved to the registrar is called by some other account */ import { UnauthorizedRegistrar, ZeroAddressCheck } from "./ProductErrorReporter.sol"; /** * @dev The Ownable contract handles an owner, called the registrar, and a modifier used to protect methods reserved to the registrar. */ abstract contract Ownable { address private registrarAgent; /** * @dev `_registrar` will be the owner of the contract */ constructor(address _registrar) { if(_registrar == address(0)) revert ZeroAddressCheck(); registrarAgent = _registrar; } /** * @dev Throws an error if the caller is not the contract's owner(a.k.a. registrar) */ modifier onlyRegistrar() { if (msg.sender != registrarAgent) revert UnauthorizedRegistrar(); _; } }
pragma solidity 0.8.17; error TotalSupplyNotMatchTotalInitialSupply(); error PayingAgentNotSet(); error GuarantorNotSet(); error UnauthorizedIssuer(); error UnauthorizedSettler(); error ProductIsFullyRedeemed(); error SettlementTransactionNotInProcessedState(); error SettlementTransactionNotInAcknowledgedState(); error SettlementTransactionAlreadyExists(); error InvalidSettlementTransactionStatus(); error DeliveryReceiverAccountNumberNotMatchTokenIssuer(); error InvalidOperationType(); error InvalidTrustedToken(); error NotSupportedTrustedToken(); error InsufficientDisposableBalance(); error InsufficientBalance(); error InsufficientLockedBalance(); error TransferRequestNotFound(); error InvalidTransferRequestStatus(); error ZeroAddressCheck(); error OwnerHasOngoingApprove(); error ApproveDoesNotExists(); error InvalidApproveStatus(); error InsufficientAllowance(); error UnauthorizedRegistrar(); error ZeroValueCheck(); error InvalidReceiver();
{ "optimizer": { "enabled": true, "runs": 1000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": { "contracts/product/libraries/ApproveAdapterLibrary.sol": { "ApproveAdapterLibrary": "0x783c952feeb792aa63908c9b85c83ab46b0bf2fd" }, "contracts/product/libraries/SecurityTokenBalancesLibrary.sol": { "SecurityTokenBalancesLibrary": "0xe320252f58d744a09584c79ac4f3629fca3798cb" }, "contracts/product/libraries/SettlementRepositoryLibrary.sol": { "SettlementRepositoryLibrary": "0xc21b38fffc1bbe9cd95e7d9be962ad0dc5593e16" }, "contracts/product/libraries/SettlementWorkflowLibrary.sol": { "SettlementWorkflowLibrary": "0x7dac013c0caa344f7086ae3f06419be9208d6e89" }, "contracts/product/libraries/TransferAdapterLibrary.sol": { "TransferAdapterLibrary": "0x128d1485f8feb919100fcddd0571df2975010acd" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"components":[{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"}],"internalType":"struct IProduct.InitBalance[]","name":"initialBalances","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"nominalAmountCent","type":"uint256"},{"internalType":"uint256","name":"issueDate","type":"uint256"}],"internalType":"struct IProduct.Tranche[]","name":"initialTranches","type":"tuple[]"},{"internalType":"address","name":"previousContract","type":"address"},{"internalType":"string","name":"figi","type":"string"},{"internalType":"string","name":"extendedDataJson","type":"string"},{"internalType":"string","name":"esg","type":"string"},{"internalType":"string","name":"noteStatus","type":"string"},{"internalType":"string","name":"formOfNote","type":"string"},{"internalType":"string","name":"series","type":"string"},{"internalType":"string","name":"program","type":"string"},{"internalType":"string","name":"strUrl","type":"string"},{"internalType":"string","name":"productType","type":"string"},{"components":[{"internalType":"string","name":"lei","type":"string"},{"internalType":"address","name":"account","type":"address"}],"internalType":"struct IProduct.LegalEntity","name":"guarantor","type":"tuple"},{"components":[{"internalType":"string","name":"lei","type":"string"},{"internalType":"address","name":"account","type":"address"}],"internalType":"struct IProduct.LegalEntity","name":"issuer","type":"tuple"},{"components":[{"internalType":"string","name":"lei","type":"string"},{"internalType":"address","name":"account","type":"address"}],"internalType":"struct IProduct.LegalEntity","name":"payingAgent","type":"tuple"},{"components":[{"internalType":"string","name":"lei","type":"string"},{"internalType":"address","name":"account","type":"address"}],"internalType":"struct IProduct.LegalEntity","name":"settlementAgent","type":"tuple"},{"components":[{"internalType":"string","name":"lei","type":"string"},{"internalType":"address","name":"account","type":"address"}],"internalType":"struct IProduct.LegalEntity","name":"registrar","type":"tuple"},{"internalType":"string","name":"currency","type":"string"},{"internalType":"address","name":"registryAddress","type":"address"},{"internalType":"string","name":"listing","type":"string"},{"internalType":"string","name":"governingLaw","type":"string"},{"internalType":"uint256","name":"maturityDate","type":"uint256"},{"internalType":"uint256","name":"denominationCent","type":"uint256"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"isinCode","type":"string"}],"internalType":"struct IProduct.BasicProductInput","name":"basicProductInput","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"GuarantorNotSet","type":"error"},{"inputs":[],"name":"InvalidOperationType","type":"error"},{"inputs":[],"name":"InvalidReceiver","type":"error"},{"inputs":[],"name":"InvalidSettlementTransactionStatus","type":"error"},{"inputs":[],"name":"OwnerHasOngoingApprove","type":"error"},{"inputs":[],"name":"PayingAgentNotSet","type":"error"},{"inputs":[],"name":"ProductIsFullyRedeemed","type":"error"},{"inputs":[],"name":"SettlementTransactionNotInAcknowledgedState","type":"error"},{"inputs":[],"name":"SettlementTransactionNotInProcessedState","type":"error"},{"inputs":[],"name":"TotalSupplyNotMatchTotalInitialSupply","type":"error"},{"inputs":[],"name":"UnauthorizedRegistrar","type":"error"},{"inputs":[],"name":"UnauthorizedSettler","type":"error"},{"inputs":[],"name":"ZeroAddressCheck","type":"error"},{"inputs":[],"name":"ZeroValueCheck","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"approveHash","type":"bytes32"}],"name":"ApproveRejected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"approveHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"ApproveRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"approveHash","type":"bytes32"}],"name":"ApproveValidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"settlementTransactionIds","type":"uint256[]"}],"name":"CouponInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"settlementTransactionId","type":"uint256"},{"indexed":false,"internalType":"enum SettlementRepositoryLibrary.OperationType","name":"settlementTransactionOperationType","type":"uint8"}],"name":"PaymentReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"settlementTransactionId","type":"uint256"},{"indexed":false,"internalType":"enum SettlementRepositoryLibrary.OperationType","name":"settlementTransactionOperationType","type":"uint8"}],"name":"PaymentTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"settlementTransactionIds","type":"uint256[]"}],"name":"RedemptionInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"settlementTransactionId","type":"uint256"}],"name":"SettlementTransactionCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"settlementTransactionId","type":"uint256"}],"name":"SubscriptionInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"settlementTransactionId","type":"uint256"}],"name":"TradeInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"settlementTransactionId","type":"uint256"}],"name":"TransferExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"transferHash","type":"bytes32"}],"name":"TransferRejected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"transferHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"transferHash","type":"bytes32"}],"name":"TransferValidated","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"settlementTransactionId","type":"uint256"}],"name":"cancelSettlementTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_settlementTransactionId","type":"uint256"}],"name":"confirmPaymentReceived","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_settlementTransactionId","type":"uint256"}],"name":"confirmPaymentTransferred","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nominalAmountCent","type":"uint256"},{"internalType":"uint256","name":"issueDate","type":"uint256"}],"internalType":"struct IProduct.Tranche","name":"newTranche","type":"tuple"}],"name":"createTranche","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currency","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"denominationCent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"esg","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"txId","type":"uint256"},{"internalType":"uint256","name":"operationId","type":"uint256"},{"internalType":"address","name":"deliverySenderAccountNumber","type":"address"},{"internalType":"address","name":"deliveryReceiverAccountNumber","type":"address"},{"internalType":"uint256","name":"deliveryQuantity","type":"uint256"},{"internalType":"string","name":"txHash","type":"string"}],"internalType":"struct SettlementRepositoryLibrary.PartialSettlementTransaction","name":"partialSettlementTransaction","type":"tuple"}],"name":"executeTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"extendedDataJson","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"figi","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"formOfNote","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getBalance","outputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"getFullBalance","outputs":[{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"locked","type":"uint256"}],"internalType":"struct SecurityTokenBalancesLibrary.Balance","name":"value","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFullBalances","outputs":[{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"locked","type":"uint256"}],"internalType":"struct SecurityTokenBalancesLibrary.Balance[]","name":"value","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_settlementTransactionId","type":"uint256"}],"name":"getSettlementTransaction","outputs":[{"components":[{"internalType":"uint256","name":"txId","type":"uint256"},{"internalType":"uint256","name":"operationId","type":"uint256"},{"internalType":"address","name":"deliverySenderAccountNumber","type":"address"},{"internalType":"address","name":"deliveryReceiverAccountNumber","type":"address"},{"internalType":"uint256","name":"deliveryQuantity","type":"uint256"},{"internalType":"string","name":"txHash","type":"string"},{"internalType":"enum SettlementRepositoryLibrary.SettlementTransactionStatus","name":"status","type":"uint8"},{"internalType":"enum SettlementRepositoryLibrary.OperationType","name":"operationType","type":"uint8"}],"internalType":"struct SettlementRepositoryLibrary.SettlementTransaction","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTranches","outputs":[{"components":[{"internalType":"uint256","name":"nominalAmountCent","type":"uint256"},{"internalType":"uint256","name":"issueDate","type":"uint256"}],"internalType":"struct IProduct.Tranche[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governingLaw","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guarantor","outputs":[{"internalType":"string","name":"lei","type":"string"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guarantorAccount","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guarantorLEI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"txId","type":"uint256"},{"internalType":"uint256","name":"operationId","type":"uint256"},{"internalType":"address","name":"deliverySenderAccountNumber","type":"address"},{"internalType":"address","name":"deliveryReceiverAccountNumber","type":"address"},{"internalType":"uint256","name":"deliveryQuantity","type":"uint256"},{"internalType":"string","name":"txHash","type":"string"}],"internalType":"struct SettlementRepositoryLibrary.PartialSettlementTransaction[]","name":"partialSettlementTransactions","type":"tuple[]"},{"internalType":"string","name":"extendedData","type":"string"}],"name":"initiateCoupon","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"txId","type":"uint256"},{"internalType":"uint256","name":"operationId","type":"uint256"},{"internalType":"address","name":"deliverySenderAccountNumber","type":"address"},{"internalType":"address","name":"deliveryReceiverAccountNumber","type":"address"},{"internalType":"uint256","name":"deliveryQuantity","type":"uint256"},{"internalType":"string","name":"txHash","type":"string"}],"internalType":"struct SettlementRepositoryLibrary.PartialSettlementTransaction[]","name":"partialSettlementTransactions","type":"tuple[]"},{"internalType":"string","name":"extendedData","type":"string"}],"name":"initiateRedemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"txId","type":"uint256"},{"internalType":"uint256","name":"operationId","type":"uint256"},{"internalType":"address","name":"deliverySenderAccountNumber","type":"address"},{"internalType":"address","name":"deliveryReceiverAccountNumber","type":"address"},{"internalType":"uint256","name":"deliveryQuantity","type":"uint256"},{"internalType":"string","name":"txHash","type":"string"}],"internalType":"struct SettlementRepositoryLibrary.PartialSettlementTransaction","name":"partialSettlementTransaction","type":"tuple"}],"name":"initiateSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"txId","type":"uint256"},{"internalType":"uint256","name":"operationId","type":"uint256"},{"internalType":"address","name":"deliverySenderAccountNumber","type":"address"},{"internalType":"address","name":"deliveryReceiverAccountNumber","type":"address"},{"internalType":"uint256","name":"deliveryQuantity","type":"uint256"},{"internalType":"string","name":"txHash","type":"string"}],"internalType":"struct SettlementRepositoryLibrary.PartialSettlementTransaction","name":"partialSettlementTransaction","type":"tuple"}],"name":"initiateTrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isinCode","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"issuer","outputs":[{"internalType":"string","name":"lei","type":"string"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"issuerAccount","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"issuerLEI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"listing","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maturityDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"noteStatus","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"operationExtendedDataJson","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payingAgent","outputs":[{"internalType":"string","name":"lei","type":"string"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payingAgentAccount","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payingAgentLEI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"previousContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"productType","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"program","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registrar","outputs":[{"internalType":"string","name":"lei","type":"string"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registrarAccount","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registrarLEI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"approveHash","type":"bytes32"}],"name":"rejectApprove","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transferHash","type":"bytes32"}],"name":"rejectTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"series","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"seriesNominalAmountCent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"seriesOutstandingNominalAmountCent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"seriesRedeemedAmountCent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_esg","type":"string"}],"name":"setEsg","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_extendedDataJson","type":"string"}],"name":"setExtendeDataJson","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_strUrl","type":"string"}],"name":"setStrUrl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settlementAgent","outputs":[{"internalType":"string","name":"lei","type":"string"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"settlementAgentAccount","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"settlementAgentLEI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state","outputs":[{"internalType":"enum Product.ProductState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"strUrl","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tranches","outputs":[{"internalType":"uint256","name":"nominalAmountCent","type":"uint256"},{"internalType":"uint256","name":"issueDate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"approveHash","type":"bytes32"}],"name":"validateApprove","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transferHash","type":"bytes32"}],"name":"validateTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b50604051620049b8380380620049b8833981016040819052620000349162000a51565b610200810151602001516001600160a01b03811662000066576040516399676b1160e01b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03929092169190911790556103208101516007906200009b908262000ee7565b50610300810151600b90620000b1908262000ee7565b506102e0810151601390620000c7908262000ee7565b506102c08101516002556102a0810151600355610280810151600490620000ef908262000ee7565b50610260810151600a9062000105908262000ee7565b506014805460ff1916600190811790915561022082015162000128908262000ee7565b5060408051808201909152610200820180515180835290516020908101516001600160a01b031690830152600f90819062000164908262000ee7565b5060209182015160019190910180546001600160a01b0319166001600160a01b039283161790556101e08301519091015116620001b4576040516399676b1160e01b815260040160405180910390fd5b604080518082019091526101e0820180515180835290516020908101516001600160a01b0316908301526011908190620001ef908262000ee7565b5060209182015160019190910180546001600160a01b0319166001600160a01b03928316179055604080518082019091526101c08401805151808352905184015190921692810192909252600c9081906200024b908262000ee7565b5060209182015160019190910180546001600160a01b0319166001600160a01b03928316179055604080518082019091526101a084018051518083529051840151909216928101929092526008908190620002a7908262000ee7565b5060209190910151600190910180546001600160a01b0319166001600160a01b0392831617905560095460405163d29dde5760e01b8152601f60048201529116602482015273e320252f58d744a09584c79ac4f3629fca3798cb9063d29dde579060440160006040518083038186803b1580156200032457600080fd5b505af415801562000339573d6000803e3d6000fd5b505060408051808201909152610180840180515180835290516020908101516001600160a01b0316908301529092506005915081906200037a908262000ee7565b5060209190910151600190910180546001600160a01b0319166001600160a01b03909216919091179055610140810151601590620003b9908262000ee7565b50610160810151600e90620003cf908262000ee7565b50610120810151601690620003e5908262000ee7565b50610100810151601790620003fb908262000ee7565b5060c081015160189062000410908262000ee7565b5060e0810151601b9062000425908262000ee7565b5060808101516019906200043a908262000ee7565b5060a0810151601a906200044f908262000ee7565b506060810151601c9062000464908262000ee7565b506040810151601d80546001600160a01b0319166001600160a01b0390921691909117905560005b816020015151811015620004e057620004cb82602001518281518110620004b757620004b762000fb3565b6020026020010151620006a260201b60201c565b80620004d78162000fdf565b9150506200048c565b50805151156200061a576000805b825151811015620005ef5760008360000151828151811062000514576200051462000fb3565b60200260200101516020015190506000846000015183815181106200053d576200053d62000fb3565b60209081029190910101515160405163ec2a214f60e01b8152601f60048201526001600160a01b03821660248201526044810184905290915073e320252f58d744a09584c79ac4f3629fca3798cb9063ec2a214f9060640160006040518083038186803b158015620005ae57600080fd5b505af4158015620005c3573d6000803e3d6000fd5b505050508184620005d5919062000ffb565b935050508080620005e69062000fdf565b915050620004ee565b50602e5481146200061357604051633b47470b60e21b815260040160405180910390fd5b506200069b565b600954602e5460405163ec2a214f60e01b8152601f60048201526001600160a01b039092166024830152604482015273e320252f58d744a09584c79ac4f3629fca3798cb9063ec2a214f9060640160006040518083038186803b1580156200068157600080fd5b505af415801562000696573d6000803e3d6000fd5b505050505b5062001050565b602a80546001810182556000918252825160029091027fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d2810182905560208401517fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d390910155602b8054919290916200071d90849062000ffb565b909155506200072d905062000730565b50565b602d54602b5462000742919062001017565b602c81905560025462000755916200102d565b602e55565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200079557620007956200075a565b60405290565b60405161034081016001600160401b03811182821017156200079557620007956200075a565b604051601f8201601f191681016001600160401b0381118282101715620007ec57620007ec6200075a565b604052919050565b60006001600160401b038211156200081057620008106200075a565b5060051b60200190565b80516001600160a01b03811681146200083257600080fd5b919050565b600082601f8301126200084957600080fd5b81516020620008626200085c83620007f4565b620007c1565b82815260069290921b840181019181810190868411156200088257600080fd5b8286015b84811015620008cf5760408189031215620008a15760008081fd5b620008ab62000770565b620008b6826200081a565b8152818501518582015283529183019160400162000886565b509695505050505050565b600082601f830112620008ec57600080fd5b81516020620008ff6200085c83620007f4565b82815260069290921b840181019181810190868411156200091f57600080fd5b8286015b84811015620008cf57604081890312156200093e5760008081fd5b6200094862000770565b81518152848201518582015283529183019160400162000923565b600082601f8301126200097557600080fd5b81516001600160401b038111156200099157620009916200075a565b6020620009a7601f8301601f19168201620007c1565b8281528582848701011115620009bc57600080fd5b60005b83811015620009dc578581018301518282018401528201620009bf565b506000928101909101919091529392505050565b60006040828403121562000a0357600080fd5b62000a0d62000770565b82519091506001600160401b0381111562000a2757600080fd5b62000a358482850162000963565b82525062000a46602083016200081a565b602082015292915050565b60006020828403121562000a6457600080fd5b81516001600160401b038082111562000a7c57600080fd5b90830190610340828603121562000a9257600080fd5b62000a9c6200079b565b82518281111562000aac57600080fd5b62000aba8782860162000837565b82525060208301518281111562000ad057600080fd5b62000ade87828601620008da565b60208301525062000af2604084016200081a565b604082015260608301518281111562000b0a57600080fd5b62000b188782860162000963565b60608301525060808301518281111562000b3157600080fd5b62000b3f8782860162000963565b60808301525060a08301518281111562000b5857600080fd5b62000b668782860162000963565b60a08301525060c08301518281111562000b7f57600080fd5b62000b8d8782860162000963565b60c08301525060e08301518281111562000ba657600080fd5b62000bb48782860162000963565b60e083015250610100808401518381111562000bcf57600080fd5b62000bdd8882870162000963565b828401525050610120808401518381111562000bf857600080fd5b62000c068882870162000963565b828401525050610140808401518381111562000c2157600080fd5b62000c2f8882870162000963565b828401525050610160808401518381111562000c4a57600080fd5b62000c588882870162000963565b828401525050610180808401518381111562000c7357600080fd5b62000c8188828701620009f0565b8284015250506101a0808401518381111562000c9c57600080fd5b62000caa88828701620009f0565b8284015250506101c0808401518381111562000cc557600080fd5b62000cd388828701620009f0565b8284015250506101e0808401518381111562000cee57600080fd5b62000cfc88828701620009f0565b828401525050610200808401518381111562000d1757600080fd5b62000d2588828701620009f0565b828401525050610220808401518381111562000d4057600080fd5b62000d4e8882870162000963565b82840152505061024062000d648185016200081a565b90820152610260838101518381111562000d7d57600080fd5b62000d8b8882870162000963565b828401525050610280808401518381111562000da657600080fd5b62000db48882870162000963565b8284015250506102a08084015181830152506102c08084015181830152506102e0808401518381111562000de757600080fd5b62000df58882870162000963565b828401525050610300808401518381111562000e1057600080fd5b62000e1e8882870162000963565b828401525050610320808401518381111562000e3957600080fd5b62000e478882870162000963565b918301919091525095945050505050565b600181811c9082168062000e6d57607f821691505b60208210810362000e8e57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000ee257600081815260208120601f850160051c8101602086101562000ebd5750805b601f850160051c820191505b8181101562000ede5782815560010162000ec9565b5050505b505050565b81516001600160401b0381111562000f035762000f036200075a565b62000f1b8162000f14845462000e58565b8462000e94565b602080601f83116001811462000f53576000841562000f3a5750858301515b600019600386901b1c1916600185901b17855562000ede565b600085815260208120601f198616915b8281101562000f845788860151825594840194600190910190840162000f63565b508582101562000fa35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820162000ff45762000ff462000fc9565b5060010190565b8082018082111562001011576200101162000fc9565b92915050565b8181038181111562001011576200101162000fc9565b6000826200104b57634e487b7160e01b600052601260045260246000fd5b500490565b61395880620010606000396000f3fe608060405234801561001057600080fd5b50600436106104725760003560e01c80638876678d11610250578063cac0652211610150578063dd62ed3e116100c8578063e4ae852911610097578063e96b38281161007c578063e96b3828146108c3578063f12d870f146108d6578063f8b2cb4f146106a557600080fd5b8063e4ae8529146108a8578063e5a6b10f146108bb57600080fd5b8063dd62ed3e14610867578063e109ca7a1461087a578063e3406ff61461088d578063e46871f1146108a057600080fd5b8063d9474b2c1161011f578063dc2f511b11610104578063dc2f511b14610837578063dc9c8aa81461084c578063dcc59ec21461085f57600080fd5b8063d9474b2c14610827578063da15ff911461082f57600080fd5b8063cac06522146107d6578063d1eac5cc146107de578063d497ec04146107fe578063d59624b41461081e57600080fd5b8063b9f534c0116101e3578063c19d93fb116101b2578063c62c564711610197578063c62c5647146107be578063c76b9527146107c6578063c860ebc6146107ce57600080fd5b8063c19d93fb14610791578063c4842b6c146107ab57600080fd5b8063b9f534c01461075b578063bc7c55ed14610763578063bf554b9f1461076b578063c1136a291461077e57600080fd5b80639e2c91371161021f5780639e2c913714610724578063a5462be71461072d578063a9059cbb14610735578063b71f31f31461074857600080fd5b80638876678d146106f65780638c8d0ce01461070b578063942a05161461071357806395d89b411461071c57600080fd5b806342966c68116103765780636121c61d116102ee57806371cf516b116102bd57806378954b3b116102a257806378954b3b146106c85780637fbeb89c146106db57806381aa632c146106ee57600080fd5b806371cf516b146106b8578063781d219a146106c057600080fd5b80636121c61d1461067957806362d103361461068157806362f4774c1461069257806370a08231146106a557600080fd5b8063524f7f761161034557806357786f711161032a57806357786f71146106605780635962e266146106695780635e4795a91461067157600080fd5b8063524f7f761461061c57806354fd4d501461062457600080fd5b806342966c68146105d25780634493b8f3146105e55780634ec3714c146105f65780634ec4928e1461060957600080fd5b80631fce02201161040957806326c25962116103d85780632b20e397116103bd5780632b20e397146105b2578063313ce567146105ba57806334356674146105c957600080fd5b806326c259621461058257806326fa713b146105aa57600080fd5b80631fce02201461052457806323b872dd14610537578063255f6a9b1461054a578063266a85c21461055d57600080fd5b8063095ea7b311610445578063095ea7b3146104df5780630a720745146104f257806318160ddd146105055780631d1438481461051c57600080fd5b806301ffc9a714610477578063053576ad1461049f5780630665d994146104b557806306fdde03146104ca575b600080fd5b61048a610485366004612cbc565b6108de565b60405190151581526020015b60405180910390f35b6104a761098e565b604051610496929190612d36565b6104c86104c3366004612e50565b610a2f565b005b6104d2610a6a565b6040516104969190612e8d565b61048a6104ed366004612eb5565b610af8565b61048a610500366004612ee1565b610c5f565b61050e602e5481565b604051908152602001610496565b6104a7610e22565b61048a610532366004612ee1565b610e31565b61048a610545366004612efa565b610f28565b6104c861055836600461300e565b611042565b6010546001600160a01b03165b6040516001600160a01b039091168152602001610496565b610595610590366004612ee1565b61124b565b60408051928352602083019190915201610496565b6104d2611279565b6104a761130e565b60405160008152602001610496565b61050e60025481565b6104c86105e0366004612ee1565b61131d565b6012546001600160a01b031661056a565b6104c86106043660046130e2565b611361565b6104c861061736600461300e565b611492565b6104d261169e565b6104d26040518060400160405280600381526020017f312e31000000000000000000000000000000000000000000000000000000000081525081565b61050e602b5481565b6104d26116df565b6104a76116ec565b6104d26116fb565b6009546001600160a01b031661056a565b6104c86106a0366004612e50565b611708565b61050e6106b3366004613117565b61173f565b6104a76117de565b6104d26117ed565b601d5461056a906001600160a01b031681565b61048a6106e9366004612ee1565b6117ff565b6104d2611a76565b6106fe611ab7565b6040516104969190613134565b6104d2611b50565b61050e602d5481565b6104d2611b5d565b61050e602c5481565b6104d2611b6a565b61048a610743366004612eb5565b611b77565b6104c861075636600461319f565b611d57565b6104d2611e2c565b6104d2611e39565b6104c8610779366004612ee1565b611e46565b6104d261078c366004612ee1565b611f2c565b60145461079e9060ff1681565b6040516104969190613204565b6104c86107b93660046130e2565b611f45565b6104d261206c565b61056a61207e565b6104d26120ba565b6104d26120c7565b6107f16107ec366004613117565b6120d4565b604051610496919061321e565b61081161080c366004612ee1565b61219d565b6040516104969190613265565b61050e60035481565b6104d2612262565b61056a61226f565b61083f6122ab565b60405161049691906132f5565b61048a61085a366004612ee1565b61231e565b6104d2612406565b61050e610875366004613344565b612413565b6104c86108883660046130e2565b6124c1565b6104c861089b366004612ee1565b6125e8565b6104d26126d6565b6104c86108b6366004612e50565b6126e3565b6104d261271a565b6104c86108d1366004612ee1565b612727565b6104d261275b565b60006001600160e01b031982167fb5ab740e00000000000000000000000000000000000000000000000000000000148061094157506001600160e01b031982167fe81f93ba00000000000000000000000000000000000000000000000000000000145b8061095457506001600160e01b03198216155b8061098857507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b60118054819061099d9061337d565b80601f01602080910402602001604051908101604052809291908181526020018280546109c99061337d565b8015610a165780601f106109eb57610100808354040283529160200191610a16565b820191906000526020600020905b8154815290600101906020018083116109f957829003601f168201915b505050600190930154919250506001600160a01b031682565b6000546001600160a01b03163314610a5a57604051631a88efbf60e11b815260040160405180910390fd5b6019610a668282613406565b5050565b600b8054610a779061337d565b80601f0160208091040260200160405190810160405280929190818152602001828054610aa39061337d565b8015610af05780601f10610ac557610100808354040283529160200191610af0565b820191906000526020600020905b815481529060010190602001808311610ad357829003601f168201915b505050505081565b3360009081526029602090815260408083206001600160a01b0386168452909152812054839060ff1615610b58576040517f4714a5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f3498e56c00000000000000000000000000000000000000000000000000000000815260266004820152601f60248201523360448201526001600160a01b03851660648201526084810184905260009073783c952feeb792aa63908c9b85c83ab46b0bf2fd90633498e56c9060a401602060405180830381865af4158015610be7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0b91906134c6565b60408051828152602081018790529192506001600160a01b0387169133917f57d1524865ded40de243246267aece0a56c052311c9ce71c4d0cbbed21249eb3910160405180910390a3506001949350505050565b600080546001600160a01b03163314610c8b57604051631a88efbf60e11b815260040160405180910390fd5b6040517f7d674945000000000000000000000000000000000000000000000000000000008152602660048201526024810183905273783c952feeb792aa63908c9b85c83ab46b0bf2fd90637d6749459060440160006040518083038186803b158015610cf657600080fd5b505af4158015610d0a573d6000803e3d6000fd5b5050506000838152602660209081526040808320815160808101835281546001600160a01b0390811682526001830154169381019390935260028101549183019190915260038082015493945091929091606084019160ff1690811115610d7357610d736131ee565b6003811115610d8457610d846131ee565b81525050905080602001516001600160a01b031681600001516001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258360400151604051610ddb91815260200190565b60405180910390a36040518381527f1cd3564f5a2b43649814052b7428dc0ba155f5d18f8f5fcf50bd32cc88359fb4906020015b60405180910390a160019150505b919050565b60088054819061099d9061337d565b600080546001600160a01b03163314610e5d57604051631a88efbf60e11b815260040160405180910390fd5b6040517fcdb4242e00000000000000000000000000000000000000000000000000000000815260266004820152601f60248201526044810183905273783c952feeb792aa63908c9b85c83ab46b0bf2fd9063cdb4242e9060640160006040518083038186803b158015610ecf57600080fd5b505af4158015610ee3573d6000803e3d6000fd5b505050507f891e5cbb521c74b11f09b9a17b9f0fab0c8cdd158908914196b5d9f1e741dd7582604051610f1891815260200190565b60405180910390a1506001919050565b6040517f1c64d94700000000000000000000000000000000000000000000000000000000815260266004820152601f60248083019190915260448201523360648201526001600160a01b038085166084830152831660a482015260c48101829052600090819073783c952feeb792aa63908c9b85c83ab46b0bf2fd90631c64d9479060e401602060405180830381865af4158015610fca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fee91906134c6565b60408051828152602081018690529192506001600160a01b0386169133917f957db550c8482e0e40d923e90c7e1c7388a338f015b090168eae3a7dd36903c7910160405180910390a3506001949350505050565b6000546001600160a01b0316331461106d57604051631a88efbf60e11b815260040160405180910390fd5b600360145460ff166003811115611086576110866131ee565b106110a4576040516383b3712f60e01b815260040160405180910390fd5b6000825167ffffffffffffffff8111156110c0576110c0612d61565b6040519080825280602002602001820160405280156110e9578160200160208202803683370190505b506040517f1f5263e9000000000000000000000000000000000000000000000000000000008152909150737dac013c0caa344f7086ae3f06419be9208d6e8990631f5263e99061114090602390879060040161357d565b60006040518083038186803b15801561115857600080fd5b505af415801561116c573d6000803e3d6000fd5b5050505060008360008151811061118557611185613596565b602002602001015160200151905082601e600083815260200190815260200160002090816111b39190613406565b5060005b845181101561120d578481815181106111d2576111d2613596565b6020026020010151600001518382815181106111f0576111f0613596565b602090810291909101015280611205816135c2565b9150506111b7565b507f354e5f2b05309441ea51dd05db8e29f7a5e5341858336b8d4a1466ab7deef5ba8260405161123d91906135db565b60405180910390a150505050565b602a818154811061125b57600080fd5b60009182526020909120600290910201805460019091015490915082565b6060600f600001805461128b9061337d565b80601f01602080910402602001604051908101604052809291908181526020018280546112b79061337d565b80156113045780601f106112d957610100808354040283529160200191611304565b820191906000526020600020905b8154815290600101906020018083116112e757829003601f168201915b5050505050905090565b600f8054819061099d9061337d565b6000546001600160a01b0316331461134857604051631a88efbf60e11b815260040160405180910390fd5b60095461135e906001600160a01b031682612768565b50565b6000546001600160a01b0316331461138c57604051631a88efbf60e11b815260040160405180910390fd5b600360145460ff1660038111156113a5576113a56131ee565b106113c3576040516383b3712f60e01b815260040160405180910390fd5b6040517fbfc9867b000000000000000000000000000000000000000000000000000000008152737dac013c0caa344f7086ae3f06419be9208d6e899063bfc9867b9061141990602390601f908690600401613613565b60006040518083038186803b15801561143157600080fd5b505af4158015611445573d6000803e3d6000fd5b505082516114599250602391506004612827565b80516040519081527ff49c7151a34f944c290bea0b71e18d61f02bfd24115ac372517b6ba94ebd9546906020015b60405180910390a150565b6000546001600160a01b031633146114bd57604051631a88efbf60e11b815260040160405180910390fd5b600360145460ff1660038111156114d6576114d66131ee565b106114f4576040516383b3712f60e01b815260040160405180910390fd5b6000825167ffffffffffffffff81111561151057611510612d61565b604051908082528060200260200182016040528015611539578160200160208202803683370190505b506040517f56d10ebd000000000000000000000000000000000000000000000000000000008152909150737dac013c0caa344f7086ae3f06419be9208d6e89906356d10ebd9061159390602390601f90889060040161363b565b60006040518083038186803b1580156115ab57600080fd5b505af41580156115bf573d6000803e3d6000fd5b505050506000836000815181106115d8576115d8613596565b602002602001015160200151905082601e600083815260200190815260200160002090816116069190613406565b5060005b84518110156116605784818151811061162557611625613596565b60200260200101516000015183828151811061164357611643613596565b602090810291909101015280611658816135c2565b91505061160a565b506014805460ff191660031790556040517f1d13bbc19c4b8f9e6a70801e6ff012075a3f608962f7374206a6b0dafc1992719061123d9084906135db565b6060600c60000180546116b09061337d565b90506000036116d257604051631f950c7960e11b815260040160405180910390fd5b600c805461128b9061337d565b601b8054610a779061337d565b600c8054819061099d9061337d565b600e8054610a779061337d565b6000546001600160a01b0316331461173357604051631a88efbf60e11b815260040160405180910390fd5b6015610a668282613406565b6040517f75ac38c2000000000000000000000000000000000000000000000000000000008152601f60048201526001600160a01b038216602482015260009073e320252f58d744a09584c79ac4f3629fca3798cb906375ac38c290604401602060405180830381865af41580156117ba573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098891906134c6565b60058054819061099d9061337d565b60606011600001805461128b9061337d565b600080546001600160a01b0316331461182b57604051631a88efbf60e11b815260040160405180910390fd5b6040517f5c226beb000000000000000000000000000000000000000000000000000000008152602460048201819052810183905273128d1485f8feb919100fcddd0571df2975010acd90635c226beb9060440160006040518083038186803b15801561189657600080fd5b505af41580156118aa573d6000803e3d6000fd5b5050506000838152602460209081526040808320815160c08101835281546001600160a01b0390811682526001830154169381019390935260028101549183019190915260038082015493945091929091606084019160ff1690811115611913576119136131ee565b6003811115611924576119246131ee565b815260039190910154610100810460ff16151560208301526201000090046001600160a01b03166040909101526080810151909150156119ad5760408082015182516001600160a01b0390811660009081526028602090815284822060a08701519093168252919091529182208054919290916119a290849061365a565b90915550611a469050565b805160408083015190517f580e2c44000000000000000000000000000000000000000000000000000000008152601f60048201526001600160a01b039092166024830152604482015273e320252f58d744a09584c79ac4f3629fca3798cb9063580e2c449060640160006040518083038186803b158015611a2d57600080fd5b505af4158015611a41573d6000803e3d6000fd5b505050505b6040518381527f6a9eda23525b3a9b3aa9326b05e25ca9af576996fa0ae91c62afbc835839b0cb90602001610e0f565b606060056000018054611a889061337d565b9050600003611aaa576040516373aba56b60e01b815260040160405180910390fd5b6005805461128b9061337d565b6040517f4bb4caef000000000000000000000000000000000000000000000000000000008152601f600482015260609073e320252f58d744a09584c79ac4f3629fca3798cb90634bb4caef90602401600060405180830381865af4158015611b23573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611b4b91908101906136df565b905090565b60078054610a779061337d565b60138054610a779061337d565b60158054610a779061337d565b600081600003611bb3576040517fbabd61a500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336001600160a01b03841603611bf5576040517f1e4ec46b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f84a04370000000000000000000000000000000000000000000000000000000008152602460048201819052601f908201523360448201526001600160a01b038416606482015260848101839052600060a4820181905260c482018190529073128d1485f8feb919100fcddd0571df2975010acd906384a043709060e401602060405180830381865af4158015611c93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cb791906134c6565b9050836001600160a01b0316336001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6000604051611cff91815260200190565b60405180910390a360408051828152602081018590526001600160a01b0386169133917f957db550c8482e0e40d923e90c7e1c7388a338f015b090168eae3a7dd36903c7910160405180910390a35060019392505050565b6000546001600160a01b03163314611d8257604051631a88efbf60e11b815260040160405180910390fd5b600954600254825173e320252f58d744a09584c79ac4f3629fca3798cb9263ec2a214f92601f926001600160a01b0390921691611dbf9190613779565b6040516001600160e01b031960e086901b16815260048101939093526001600160a01b039091166024830152604482015260640160006040518083038186803b158015611e0b57600080fd5b505af4158015611e1f573d6000803e3d6000fd5b5050505061135e816128ac565b601c8054610a779061337d565b600a8054610a779061337d565b6000546001600160a01b03163314611e7157604051631a88efbf60e11b815260040160405180910390fd5b6040517fd9ea7a0600000000000000000000000000000000000000000000000000000000815260236004820152601f602482015260448101829052737dac013c0caa344f7086ae3f06419be9208d6e899063d9ea7a069060640160006040518083038186803b158015611ee357600080fd5b505af4158015611ef7573d6000803e3d6000fd5b505050507f5ac1d96566a8d80ac0b7c75ce8ad501255fb99929aa34a2328f9b192b1d0c0a98160405161148791815260200190565b601e6020526000908152604090208054610a779061337d565b6000546001600160a01b03163314611f7057604051631a88efbf60e11b815260040160405180910390fd5b600360145460ff166003811115611f8957611f896131ee565b10611fa7576040516383b3712f60e01b815260040160405180910390fd5b6040517fcd2002fd000000000000000000000000000000000000000000000000000000008152737dac013c0caa344f7086ae3f06419be9208d6e899063cd2002fd90611ffd90602390601f908690600401613613565b60006040518083038186803b15801561201557600080fd5b505af4158015612029573d6000803e3d6000fd5b50506014805460ff19166002179055505080516040519081527fc40a4f74d715da2ee96119fbf8d8da1df0f5b79e92c3fd855f1ddc102d51d04790602001611487565b60606008600001805461128b9061337d565b6006546000906001600160a01b03166120aa576040516373aba56b60e01b815260040160405180910390fd5b506006546001600160a01b031690565b60168054610a779061337d565b601a8054610a779061337d565b612101604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b6040517f5d1605b3000000000000000000000000000000000000000000000000000000008152601f60048201526001600160a01b038316602482015273e320252f58d744a09584c79ac4f3629fca3798cb90635d1605b390604401606060405180830381865af4158015612179573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610988919061379b565b6121e3604080516101008101825260008082526020820181905291810182905260608082018390526080820183905260a08201529060c082019081526020016000905290565b6040516318366f3560e21b8152602360048201526024810183905273c21b38fffc1bbe9cd95e7d9be962ad0dc5593e16906360d9bcd490604401600060405180830381865af415801561223a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610988919081019061380b565b60188054610a779061337d565b600d546000906001600160a01b031661229b57604051631f950c7960e11b815260040160405180910390fd5b50600d546001600160a01b031690565b6060602a805480602002602001604051908101604052809291908181526020016000905b82821015612315578382906000526020600020906002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906122cf565b50505050905090565b600080546001600160a01b0316331461234a57604051631a88efbf60e11b815260040160405180910390fd5b6040517f284d9c96000000000000000000000000000000000000000000000000000000008152602460048201819052601f908201526044810183905273128d1485f8feb919100fcddd0571df2975010acd9063284d9c969060640160006040518083038186803b1580156123bd57600080fd5b505af41580156123d1573d6000803e3d6000fd5b505050507ff293a19d8e1c857cb5b75138774de0ea944b21327ae79db4cb55296627b5237182604051610f1891815260200190565b60198054610a779061337d565b6040517fd8e9cf03000000000000000000000000000000000000000000000000000000008152602660048201526001600160a01b0380841660248301528216604482015260009073783c952feeb792aa63908c9b85c83ab46b0bf2fd9063d8e9cf0390606401602060405180830381865af4158015612496573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ba91906134c6565b9392505050565b6000546001600160a01b031633146124ec57604051631a88efbf60e11b815260040160405180910390fd5b600360145460ff166003811115612505576125056131ee565b10612523576040516383b3712f60e01b815260040160405180910390fd5b6040517f06846dce000000000000000000000000000000000000000000000000000000008152737dac013c0caa344f7086ae3f06419be9208d6e89906306846dce9061257990602390601f908690600401613613565b60006040518083038186803b15801561259157600080fd5b505af41580156125a5573d6000803e3d6000fd5b50506014805460ff19166002179055505080516040519081527f0bed382b9aad3b5629da3f0660006b5b0ebaf727367204f573a175544a0f930d90602001611487565b6012546001600160a01b0316331461261357604051631de3f8c960e21b815260040160405180910390fd5b6040516318366f3560e21b8152602360048201526024810182905260009073c21b38fffc1bbe9cd95e7d9be962ad0dc5593e16906360d9bcd490604401600060405180830381865af415801561266d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612695919081019061380b565b905060008160e0015160058111156126af576126af6131ee565b036126cd57604051630ead561960e11b815260040160405180910390fd5b610a6682612933565b60048054610a779061337d565b6000546001600160a01b0316331461270e57604051631a88efbf60e11b815260040160405180910390fd5b601a610a668282613406565b60018054610a779061337d565b6012546001600160a01b0316331461275257604051631de3f8c960e21b815260040160405180910390fd5b61135e81612b4b565b60178054610a779061337d565b6040517f51a0cf48000000000000000000000000000000000000000000000000000000008152601f60048201526001600160a01b03831660248201526044810182905273e320252f58d744a09584c79ac4f3629fca3798cb906351a0cf489060640160006040518083038186803b1580156127e257600080fd5b505af41580156127f6573d6000803e3d6000fd5b505050506002548161280891906138db565b602d6000828254612819919061365a565b90915550610a669050612c96565b600081600581111561283b5761283b6131ee565b03612872576040517f7ec04df100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260208490526040902060068101805483919060ff191660018360058111156128a1576128a16131ee565b021790555050505050565b602a80546001810182556000918252825160029091027fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d2810182905560208401517fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d390910155602b80549192909161292590849061365a565b9091555061135e9050612c96565b6040516318366f3560e21b8152602360048201526024810182905260009073c21b38fffc1bbe9cd95e7d9be962ad0dc5593e16906360d9bcd490604401600060405180830381865af415801561298d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526129b5919081019061380b565b905060028160c0015160058111156129cf576129cf6131ee565b14612a06576040517f6b67159000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60048160e001516005811115612a1e57612a1e6131ee565b14612ace576040818101516060830151608084015192517f9030099a000000000000000000000000000000000000000000000000000000008152601f60048201526001600160a01b03928316602482015291166044820152606481019190915273e320252f58d744a09584c79ac4f3629fca3798cb90639030099a9060840160006040518083038186803b158015612ab557600080fd5b505af4158015612ac9573d6000803e3d6000fd5b505050505b60028160e001516005811115612ae657612ae66131ee565b03612afd57612afd81606001518260800151612768565b612b0a6023836003612827565b7f9bbe037a1a1faac87c3e07d5beed35ad6d3c54fbbc21637447918822abb04583828260e00151604051612b3f9291906138f2565b60405180910390a15050565b6040516318366f3560e21b8152602360048201526024810182905260009073c21b38fffc1bbe9cd95e7d9be962ad0dc5593e16906360d9bcd490604401600060405180830381865af4158015612ba5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612bcd919081019061380b565b905060008160e001516005811115612be757612be76131ee565b03612c0557604051630ead561960e11b815260040160405180910390fd5b60038160c001516005811115612c1d57612c1d6131ee565b14612c54576040517f1109e7ce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612c616023836004612827565b7fa86580040b7b220b796aa9b66b3eede5540d9130c21f31e27b6667458720f3f8828260e00151604051612b3f9291906138f2565b602d54602b54612ca6919061390f565b602c819055600254612cb791613779565b602e55565b600060208284031215612cce57600080fd5b81356001600160e01b0319811681146124ba57600080fd5b60005b83811015612d01578181015183820152602001612ce9565b50506000910152565b60008151808452612d22816020860160208601612ce6565b601f01601f19169290920160200192915050565b604081526000612d496040830185612d0a565b90506001600160a01b03831660208301529392505050565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715612d9b57612d9b612d61565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612dca57612dca612d61565b604052919050565b600067ffffffffffffffff821115612dec57612dec612d61565b50601f01601f191660200190565b600082601f830112612e0b57600080fd5b8135612e1e612e1982612dd2565b612da1565b818152846020838601011115612e3357600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215612e6257600080fd5b813567ffffffffffffffff811115612e7957600080fd5b612e8584828501612dfa565b949350505050565b6020815260006124ba6020830184612d0a565b6001600160a01b038116811461135e57600080fd5b60008060408385031215612ec857600080fd5b8235612ed381612ea0565b946020939093013593505050565b600060208284031215612ef357600080fd5b5035919050565b600080600060608486031215612f0f57600080fd5b8335612f1a81612ea0565b92506020840135612f2a81612ea0565b929592945050506040919091013590565b600067ffffffffffffffff821115612f5557612f55612d61565b5060051b60200190565b600060c08284031215612f7157600080fd5b60405160c0810167ffffffffffffffff8282108183111715612f9557612f95612d61565b81604052829350843583526020850135602084015260408501359150612fba82612ea0565b81604084015260608501359150612fd082612ea0565b8160608401526080850135608084015260a0850135915080821115612ff457600080fd5b5061300185828601612dfa565b60a0830152505092915050565b6000806040838503121561302157600080fd5b823567ffffffffffffffff8082111561303957600080fd5b818501915085601f83011261304d57600080fd5b8135602061305d612e1983612f3b565b82815260059290921b8401810191818101908984111561307c57600080fd5b8286015b848110156130b4578035868111156130985760008081fd5b6130a68c86838b0101612f5f565b845250918301918301613080565b50965050860135925050808211156130cb57600080fd5b506130d885828601612dfa565b9150509250929050565b6000602082840312156130f457600080fd5b813567ffffffffffffffff81111561310b57600080fd5b612e8584828501612f5f565b60006020828403121561312957600080fd5b81356124ba81612ea0565b6020808252825182820181905260009190848201906040850190845b818110156131935761318083855180516001600160a01b0316825260208082015190830152604090810151910152565b9284019260609290920191600101613150565b50909695505050505050565b6000604082840312156131b157600080fd5b6040516040810181811067ffffffffffffffff821117156131d4576131d4612d61565b604052823581526020928301359281019290925250919050565b634e487b7160e01b600052602160045260246000fd5b6020810160048310613218576132186131ee565b91905290565b81516001600160a01b03168152602080830151908201526040808301519082015260608101610988565b6006811061135e5761135e6131ee565b61326181613248565b9052565b602081528151602082015260208201516040820152600060408301516001600160a01b0380821660608501528060608601511660808501525050608083015160a083015260a08301516101008060c08501526132c5610120850183612d0a565b915060c08501516132d960e0860182613258565b5060e08501516132eb82860182613258565b5090949350505050565b602080825282518282018190526000919060409081850190868401855b8281101561333757815180518552860151868501529284019290850190600101613312565b5091979650505050505050565b6000806040838503121561335757600080fd5b823561336281612ea0565b9150602083013561337281612ea0565b809150509250929050565b600181811c9082168061339157607f821691505b6020821081036133b157634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561340157600081815260208120601f850160051c810160208610156133de5750805b601f850160051c820191505b818110156133fd578281556001016133ea565b5050505b505050565b815167ffffffffffffffff81111561342057613420612d61565b6134348161342e845461337d565b846133b7565b602080601f83116001811461346957600084156134515750858301515b600019600386901b1c1916600185901b1785556133fd565b600085815260208120601f198616915b8281101561349857888601518255948401946001909101908401613479565b50858210156134b65787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156134d857600080fd5b5051919050565b8051825260208101516020830152600060408201516001600160a01b03808216604086015280606085015116606086015250506080820151608084015260a082015160c060a0850152612e8560c0850182612d0a565b600081518084526020808501808196508360051b8101915082860160005b8581101561333757828403895261356b8483516134df565b98850198935090840190600101613553565b828152604060208201526000612e856040830184613535565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016135d4576135d46135ac565b5060010190565b6020808252825182820181905260009190848201906040850190845b81811015613193578351835292840192918401916001016135f7565b83815282602082015260606040820152600061363260608301846134df565b95945050505050565b8381528260208201526060604082015260006136326060830184613535565b80820180821115610988576109886135ac565b8051610e1d81612ea0565b60006060828403121561368a57600080fd5b6040516060810181811067ffffffffffffffff821117156136ad576136ad612d61565b806040525080915082516136c081612ea0565b8082525060208301516020820152604083015160408201525092915050565b600060208083850312156136f257600080fd5b825167ffffffffffffffff81111561370957600080fd5b8301601f8101851361371a57600080fd5b8051613728612e1982612f3b565b8181526060918202830184019184820191908884111561374757600080fd5b938501935b8385101561376d5761375e8986613678565b8352938401939185019161374c565b50979650505050505050565b60008261379657634e487b7160e01b600052601260045260246000fd5b500490565b6000606082840312156137ad57600080fd5b6124ba8383613678565b600082601f8301126137c857600080fd5b81516137d6612e1982612dd2565b8181528460208386010111156137eb57600080fd5b612e85826020830160208701612ce6565b805160068110610e1d57600080fd5b60006020828403121561381d57600080fd5b815167ffffffffffffffff8082111561383557600080fd5b90830190610100828603121561384a57600080fd5b613852612d77565b825181526020830151602082015261386c6040840161366d565b604082015261387d6060840161366d565b60608201526080830151608082015260a08301518281111561389e57600080fd5b6138aa878286016137b7565b60a0830152506138bc60c084016137fc565b60c08201526138cd60e084016137fc565b60e082015295945050505050565b8082028115828204841417610988576109886135ac565b8281526040810161390283613248565b8260208301529392505050565b81810381811115610988576109886135ac56fea26469706673582212206b14e1154ef6f2ad60e97f357f0e3f3018b51011d5f6cfc870fed9abac6e424564736f6c63430008110033000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004a0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000088000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000980000000000000000000000000a72cd393790f4d85da4d348d7a6cc7de05d0f68100000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000006b0cbc8000000000000000000000000000000000000000000000000000000000009896800000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000aa00000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000000000006567d08000000000000000000000000000000000000000000000000000000000000000034e2f41000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000717b22696e74657265737452617465223a3430312c22636f75706f6e7061796d656e74416d6f756e7463656e74223a343031352c2266696e616c526564656d7074696f6e416d6f756e7450657263656e74223a31303030302c22696e7465726573745061796d656e7444617465223a5b5d7d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000867b2273656375726974794f6e636861696e436172626f6e466f6f747072696e74457374696d6174654b67434f326571756976616c656e74427959656172223a22302e3634222c22657374696d61746544617465223a22323032332d31312d3330222c227265706f7274223a22687474703a2f2f7777772e7367666f7267652e636f6d2f227d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009556e736563757265640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002253454355524954595f544f4b454e535f494e5f5245474953545245445f464f524d5300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034e2f4100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007454d544e205347000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017687474703a2f2f7374723a363636302f6772617068716c0000000000000000000000000000000000000000000000000000000000000000000000000000000006626f6e64563100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000dc03823bbccc2fe2a6cea8976ab803709c1be0a400000000000000000000000000000000000000000000000000000000000000194f32524e453849425850345230544438505534312d4446494e000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000dc03823bbccc2fe2a6cea8976ab803709c1be0a400000000000000000000000000000000000000000000000000000000000000194f32524e453849425850345230544438505534312d4446494e00000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000065980908e77b276c3e6cd73f609da62d1fc8e062000000000000000000000000000000000000000000000000000000000000001a4f32524e453849425850345230544438505534312d20534753530000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000e08106fad4add8dbffbbd0813027625a57c06fbd000000000000000000000000000000000000000000000000000000000000000d464f5247455f534554544c455200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000089ace546613b2cbb4510eab030a61bcdd11c8b8500000000000000000000000000000000000000000000000000000000000000143936393530304658384b34305a4457344633373700000000000000000000000000000000000000000000000000000000000000000000000000000000000000034555520000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a4c5558454d424f55524700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000246520000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040534f43494554452047454e4552414c45204555522031304d203359204449474954414c20475245454e2053454e494f5220505245464552524544204e4f5445530000000000000000000000000000000000000000000000000000000000000040534f43494554452047454e4552414c45204555522031304d203359204449474954414c20475245454e2053454e494f5220505245464552524544204e4f544553000000000000000000000000000000000000000000000000000000000000000c46523030313430304d4447350000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104725760003560e01c80638876678d11610250578063cac0652211610150578063dd62ed3e116100c8578063e4ae852911610097578063e96b38281161007c578063e96b3828146108c3578063f12d870f146108d6578063f8b2cb4f146106a557600080fd5b8063e4ae8529146108a8578063e5a6b10f146108bb57600080fd5b8063dd62ed3e14610867578063e109ca7a1461087a578063e3406ff61461088d578063e46871f1146108a057600080fd5b8063d9474b2c1161011f578063dc2f511b11610104578063dc2f511b14610837578063dc9c8aa81461084c578063dcc59ec21461085f57600080fd5b8063d9474b2c14610827578063da15ff911461082f57600080fd5b8063cac06522146107d6578063d1eac5cc146107de578063d497ec04146107fe578063d59624b41461081e57600080fd5b8063b9f534c0116101e3578063c19d93fb116101b2578063c62c564711610197578063c62c5647146107be578063c76b9527146107c6578063c860ebc6146107ce57600080fd5b8063c19d93fb14610791578063c4842b6c146107ab57600080fd5b8063b9f534c01461075b578063bc7c55ed14610763578063bf554b9f1461076b578063c1136a291461077e57600080fd5b80639e2c91371161021f5780639e2c913714610724578063a5462be71461072d578063a9059cbb14610735578063b71f31f31461074857600080fd5b80638876678d146106f65780638c8d0ce01461070b578063942a05161461071357806395d89b411461071c57600080fd5b806342966c68116103765780636121c61d116102ee57806371cf516b116102bd57806378954b3b116102a257806378954b3b146106c85780637fbeb89c146106db57806381aa632c146106ee57600080fd5b806371cf516b146106b8578063781d219a146106c057600080fd5b80636121c61d1461067957806362d103361461068157806362f4774c1461069257806370a08231146106a557600080fd5b8063524f7f761161034557806357786f711161032a57806357786f71146106605780635962e266146106695780635e4795a91461067157600080fd5b8063524f7f761461061c57806354fd4d501461062457600080fd5b806342966c68146105d25780634493b8f3146105e55780634ec3714c146105f65780634ec4928e1461060957600080fd5b80631fce02201161040957806326c25962116103d85780632b20e397116103bd5780632b20e397146105b2578063313ce567146105ba57806334356674146105c957600080fd5b806326c259621461058257806326fa713b146105aa57600080fd5b80631fce02201461052457806323b872dd14610537578063255f6a9b1461054a578063266a85c21461055d57600080fd5b8063095ea7b311610445578063095ea7b3146104df5780630a720745146104f257806318160ddd146105055780631d1438481461051c57600080fd5b806301ffc9a714610477578063053576ad1461049f5780630665d994146104b557806306fdde03146104ca575b600080fd5b61048a610485366004612cbc565b6108de565b60405190151581526020015b60405180910390f35b6104a761098e565b604051610496929190612d36565b6104c86104c3366004612e50565b610a2f565b005b6104d2610a6a565b6040516104969190612e8d565b61048a6104ed366004612eb5565b610af8565b61048a610500366004612ee1565b610c5f565b61050e602e5481565b604051908152602001610496565b6104a7610e22565b61048a610532366004612ee1565b610e31565b61048a610545366004612efa565b610f28565b6104c861055836600461300e565b611042565b6010546001600160a01b03165b6040516001600160a01b039091168152602001610496565b610595610590366004612ee1565b61124b565b60408051928352602083019190915201610496565b6104d2611279565b6104a761130e565b60405160008152602001610496565b61050e60025481565b6104c86105e0366004612ee1565b61131d565b6012546001600160a01b031661056a565b6104c86106043660046130e2565b611361565b6104c861061736600461300e565b611492565b6104d261169e565b6104d26040518060400160405280600381526020017f312e31000000000000000000000000000000000000000000000000000000000081525081565b61050e602b5481565b6104d26116df565b6104a76116ec565b6104d26116fb565b6009546001600160a01b031661056a565b6104c86106a0366004612e50565b611708565b61050e6106b3366004613117565b61173f565b6104a76117de565b6104d26117ed565b601d5461056a906001600160a01b031681565b61048a6106e9366004612ee1565b6117ff565b6104d2611a76565b6106fe611ab7565b6040516104969190613134565b6104d2611b50565b61050e602d5481565b6104d2611b5d565b61050e602c5481565b6104d2611b6a565b61048a610743366004612eb5565b611b77565b6104c861075636600461319f565b611d57565b6104d2611e2c565b6104d2611e39565b6104c8610779366004612ee1565b611e46565b6104d261078c366004612ee1565b611f2c565b60145461079e9060ff1681565b6040516104969190613204565b6104c86107b93660046130e2565b611f45565b6104d261206c565b61056a61207e565b6104d26120ba565b6104d26120c7565b6107f16107ec366004613117565b6120d4565b604051610496919061321e565b61081161080c366004612ee1565b61219d565b6040516104969190613265565b61050e60035481565b6104d2612262565b61056a61226f565b61083f6122ab565b60405161049691906132f5565b61048a61085a366004612ee1565b61231e565b6104d2612406565b61050e610875366004613344565b612413565b6104c86108883660046130e2565b6124c1565b6104c861089b366004612ee1565b6125e8565b6104d26126d6565b6104c86108b6366004612e50565b6126e3565b6104d261271a565b6104c86108d1366004612ee1565b612727565b6104d261275b565b60006001600160e01b031982167fb5ab740e00000000000000000000000000000000000000000000000000000000148061094157506001600160e01b031982167fe81f93ba00000000000000000000000000000000000000000000000000000000145b8061095457506001600160e01b03198216155b8061098857507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b60118054819061099d9061337d565b80601f01602080910402602001604051908101604052809291908181526020018280546109c99061337d565b8015610a165780601f106109eb57610100808354040283529160200191610a16565b820191906000526020600020905b8154815290600101906020018083116109f957829003601f168201915b505050600190930154919250506001600160a01b031682565b6000546001600160a01b03163314610a5a57604051631a88efbf60e11b815260040160405180910390fd5b6019610a668282613406565b5050565b600b8054610a779061337d565b80601f0160208091040260200160405190810160405280929190818152602001828054610aa39061337d565b8015610af05780601f10610ac557610100808354040283529160200191610af0565b820191906000526020600020905b815481529060010190602001808311610ad357829003601f168201915b505050505081565b3360009081526029602090815260408083206001600160a01b0386168452909152812054839060ff1615610b58576040517f4714a5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f3498e56c00000000000000000000000000000000000000000000000000000000815260266004820152601f60248201523360448201526001600160a01b03851660648201526084810184905260009073783c952feeb792aa63908c9b85c83ab46b0bf2fd90633498e56c9060a401602060405180830381865af4158015610be7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0b91906134c6565b60408051828152602081018790529192506001600160a01b0387169133917f57d1524865ded40de243246267aece0a56c052311c9ce71c4d0cbbed21249eb3910160405180910390a3506001949350505050565b600080546001600160a01b03163314610c8b57604051631a88efbf60e11b815260040160405180910390fd5b6040517f7d674945000000000000000000000000000000000000000000000000000000008152602660048201526024810183905273783c952feeb792aa63908c9b85c83ab46b0bf2fd90637d6749459060440160006040518083038186803b158015610cf657600080fd5b505af4158015610d0a573d6000803e3d6000fd5b5050506000838152602660209081526040808320815160808101835281546001600160a01b0390811682526001830154169381019390935260028101549183019190915260038082015493945091929091606084019160ff1690811115610d7357610d736131ee565b6003811115610d8457610d846131ee565b81525050905080602001516001600160a01b031681600001516001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258360400151604051610ddb91815260200190565b60405180910390a36040518381527f1cd3564f5a2b43649814052b7428dc0ba155f5d18f8f5fcf50bd32cc88359fb4906020015b60405180910390a160019150505b919050565b60088054819061099d9061337d565b600080546001600160a01b03163314610e5d57604051631a88efbf60e11b815260040160405180910390fd5b6040517fcdb4242e00000000000000000000000000000000000000000000000000000000815260266004820152601f60248201526044810183905273783c952feeb792aa63908c9b85c83ab46b0bf2fd9063cdb4242e9060640160006040518083038186803b158015610ecf57600080fd5b505af4158015610ee3573d6000803e3d6000fd5b505050507f891e5cbb521c74b11f09b9a17b9f0fab0c8cdd158908914196b5d9f1e741dd7582604051610f1891815260200190565b60405180910390a1506001919050565b6040517f1c64d94700000000000000000000000000000000000000000000000000000000815260266004820152601f60248083019190915260448201523360648201526001600160a01b038085166084830152831660a482015260c48101829052600090819073783c952feeb792aa63908c9b85c83ab46b0bf2fd90631c64d9479060e401602060405180830381865af4158015610fca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fee91906134c6565b60408051828152602081018690529192506001600160a01b0386169133917f957db550c8482e0e40d923e90c7e1c7388a338f015b090168eae3a7dd36903c7910160405180910390a3506001949350505050565b6000546001600160a01b0316331461106d57604051631a88efbf60e11b815260040160405180910390fd5b600360145460ff166003811115611086576110866131ee565b106110a4576040516383b3712f60e01b815260040160405180910390fd5b6000825167ffffffffffffffff8111156110c0576110c0612d61565b6040519080825280602002602001820160405280156110e9578160200160208202803683370190505b506040517f1f5263e9000000000000000000000000000000000000000000000000000000008152909150737dac013c0caa344f7086ae3f06419be9208d6e8990631f5263e99061114090602390879060040161357d565b60006040518083038186803b15801561115857600080fd5b505af415801561116c573d6000803e3d6000fd5b5050505060008360008151811061118557611185613596565b602002602001015160200151905082601e600083815260200190815260200160002090816111b39190613406565b5060005b845181101561120d578481815181106111d2576111d2613596565b6020026020010151600001518382815181106111f0576111f0613596565b602090810291909101015280611205816135c2565b9150506111b7565b507f354e5f2b05309441ea51dd05db8e29f7a5e5341858336b8d4a1466ab7deef5ba8260405161123d91906135db565b60405180910390a150505050565b602a818154811061125b57600080fd5b60009182526020909120600290910201805460019091015490915082565b6060600f600001805461128b9061337d565b80601f01602080910402602001604051908101604052809291908181526020018280546112b79061337d565b80156113045780601f106112d957610100808354040283529160200191611304565b820191906000526020600020905b8154815290600101906020018083116112e757829003601f168201915b5050505050905090565b600f8054819061099d9061337d565b6000546001600160a01b0316331461134857604051631a88efbf60e11b815260040160405180910390fd5b60095461135e906001600160a01b031682612768565b50565b6000546001600160a01b0316331461138c57604051631a88efbf60e11b815260040160405180910390fd5b600360145460ff1660038111156113a5576113a56131ee565b106113c3576040516383b3712f60e01b815260040160405180910390fd5b6040517fbfc9867b000000000000000000000000000000000000000000000000000000008152737dac013c0caa344f7086ae3f06419be9208d6e899063bfc9867b9061141990602390601f908690600401613613565b60006040518083038186803b15801561143157600080fd5b505af4158015611445573d6000803e3d6000fd5b505082516114599250602391506004612827565b80516040519081527ff49c7151a34f944c290bea0b71e18d61f02bfd24115ac372517b6ba94ebd9546906020015b60405180910390a150565b6000546001600160a01b031633146114bd57604051631a88efbf60e11b815260040160405180910390fd5b600360145460ff1660038111156114d6576114d66131ee565b106114f4576040516383b3712f60e01b815260040160405180910390fd5b6000825167ffffffffffffffff81111561151057611510612d61565b604051908082528060200260200182016040528015611539578160200160208202803683370190505b506040517f56d10ebd000000000000000000000000000000000000000000000000000000008152909150737dac013c0caa344f7086ae3f06419be9208d6e89906356d10ebd9061159390602390601f90889060040161363b565b60006040518083038186803b1580156115ab57600080fd5b505af41580156115bf573d6000803e3d6000fd5b505050506000836000815181106115d8576115d8613596565b602002602001015160200151905082601e600083815260200190815260200160002090816116069190613406565b5060005b84518110156116605784818151811061162557611625613596565b60200260200101516000015183828151811061164357611643613596565b602090810291909101015280611658816135c2565b91505061160a565b506014805460ff191660031790556040517f1d13bbc19c4b8f9e6a70801e6ff012075a3f608962f7374206a6b0dafc1992719061123d9084906135db565b6060600c60000180546116b09061337d565b90506000036116d257604051631f950c7960e11b815260040160405180910390fd5b600c805461128b9061337d565b601b8054610a779061337d565b600c8054819061099d9061337d565b600e8054610a779061337d565b6000546001600160a01b0316331461173357604051631a88efbf60e11b815260040160405180910390fd5b6015610a668282613406565b6040517f75ac38c2000000000000000000000000000000000000000000000000000000008152601f60048201526001600160a01b038216602482015260009073e320252f58d744a09584c79ac4f3629fca3798cb906375ac38c290604401602060405180830381865af41580156117ba573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098891906134c6565b60058054819061099d9061337d565b60606011600001805461128b9061337d565b600080546001600160a01b0316331461182b57604051631a88efbf60e11b815260040160405180910390fd5b6040517f5c226beb000000000000000000000000000000000000000000000000000000008152602460048201819052810183905273128d1485f8feb919100fcddd0571df2975010acd90635c226beb9060440160006040518083038186803b15801561189657600080fd5b505af41580156118aa573d6000803e3d6000fd5b5050506000838152602460209081526040808320815160c08101835281546001600160a01b0390811682526001830154169381019390935260028101549183019190915260038082015493945091929091606084019160ff1690811115611913576119136131ee565b6003811115611924576119246131ee565b815260039190910154610100810460ff16151560208301526201000090046001600160a01b03166040909101526080810151909150156119ad5760408082015182516001600160a01b0390811660009081526028602090815284822060a08701519093168252919091529182208054919290916119a290849061365a565b90915550611a469050565b805160408083015190517f580e2c44000000000000000000000000000000000000000000000000000000008152601f60048201526001600160a01b039092166024830152604482015273e320252f58d744a09584c79ac4f3629fca3798cb9063580e2c449060640160006040518083038186803b158015611a2d57600080fd5b505af4158015611a41573d6000803e3d6000fd5b505050505b6040518381527f6a9eda23525b3a9b3aa9326b05e25ca9af576996fa0ae91c62afbc835839b0cb90602001610e0f565b606060056000018054611a889061337d565b9050600003611aaa576040516373aba56b60e01b815260040160405180910390fd5b6005805461128b9061337d565b6040517f4bb4caef000000000000000000000000000000000000000000000000000000008152601f600482015260609073e320252f58d744a09584c79ac4f3629fca3798cb90634bb4caef90602401600060405180830381865af4158015611b23573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611b4b91908101906136df565b905090565b60078054610a779061337d565b60138054610a779061337d565b60158054610a779061337d565b600081600003611bb3576040517fbabd61a500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336001600160a01b03841603611bf5576040517f1e4ec46b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f84a04370000000000000000000000000000000000000000000000000000000008152602460048201819052601f908201523360448201526001600160a01b038416606482015260848101839052600060a4820181905260c482018190529073128d1485f8feb919100fcddd0571df2975010acd906384a043709060e401602060405180830381865af4158015611c93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cb791906134c6565b9050836001600160a01b0316336001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6000604051611cff91815260200190565b60405180910390a360408051828152602081018590526001600160a01b0386169133917f957db550c8482e0e40d923e90c7e1c7388a338f015b090168eae3a7dd36903c7910160405180910390a35060019392505050565b6000546001600160a01b03163314611d8257604051631a88efbf60e11b815260040160405180910390fd5b600954600254825173e320252f58d744a09584c79ac4f3629fca3798cb9263ec2a214f92601f926001600160a01b0390921691611dbf9190613779565b6040516001600160e01b031960e086901b16815260048101939093526001600160a01b039091166024830152604482015260640160006040518083038186803b158015611e0b57600080fd5b505af4158015611e1f573d6000803e3d6000fd5b5050505061135e816128ac565b601c8054610a779061337d565b600a8054610a779061337d565b6000546001600160a01b03163314611e7157604051631a88efbf60e11b815260040160405180910390fd5b6040517fd9ea7a0600000000000000000000000000000000000000000000000000000000815260236004820152601f602482015260448101829052737dac013c0caa344f7086ae3f06419be9208d6e899063d9ea7a069060640160006040518083038186803b158015611ee357600080fd5b505af4158015611ef7573d6000803e3d6000fd5b505050507f5ac1d96566a8d80ac0b7c75ce8ad501255fb99929aa34a2328f9b192b1d0c0a98160405161148791815260200190565b601e6020526000908152604090208054610a779061337d565b6000546001600160a01b03163314611f7057604051631a88efbf60e11b815260040160405180910390fd5b600360145460ff166003811115611f8957611f896131ee565b10611fa7576040516383b3712f60e01b815260040160405180910390fd5b6040517fcd2002fd000000000000000000000000000000000000000000000000000000008152737dac013c0caa344f7086ae3f06419be9208d6e899063cd2002fd90611ffd90602390601f908690600401613613565b60006040518083038186803b15801561201557600080fd5b505af4158015612029573d6000803e3d6000fd5b50506014805460ff19166002179055505080516040519081527fc40a4f74d715da2ee96119fbf8d8da1df0f5b79e92c3fd855f1ddc102d51d04790602001611487565b60606008600001805461128b9061337d565b6006546000906001600160a01b03166120aa576040516373aba56b60e01b815260040160405180910390fd5b506006546001600160a01b031690565b60168054610a779061337d565b601a8054610a779061337d565b612101604051806060016040528060006001600160a01b0316815260200160008152602001600081525090565b6040517f5d1605b3000000000000000000000000000000000000000000000000000000008152601f60048201526001600160a01b038316602482015273e320252f58d744a09584c79ac4f3629fca3798cb90635d1605b390604401606060405180830381865af4158015612179573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610988919061379b565b6121e3604080516101008101825260008082526020820181905291810182905260608082018390526080820183905260a08201529060c082019081526020016000905290565b6040516318366f3560e21b8152602360048201526024810183905273c21b38fffc1bbe9cd95e7d9be962ad0dc5593e16906360d9bcd490604401600060405180830381865af415801561223a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610988919081019061380b565b60188054610a779061337d565b600d546000906001600160a01b031661229b57604051631f950c7960e11b815260040160405180910390fd5b50600d546001600160a01b031690565b6060602a805480602002602001604051908101604052809291908181526020016000905b82821015612315578382906000526020600020906002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906122cf565b50505050905090565b600080546001600160a01b0316331461234a57604051631a88efbf60e11b815260040160405180910390fd5b6040517f284d9c96000000000000000000000000000000000000000000000000000000008152602460048201819052601f908201526044810183905273128d1485f8feb919100fcddd0571df2975010acd9063284d9c969060640160006040518083038186803b1580156123bd57600080fd5b505af41580156123d1573d6000803e3d6000fd5b505050507ff293a19d8e1c857cb5b75138774de0ea944b21327ae79db4cb55296627b5237182604051610f1891815260200190565b60198054610a779061337d565b6040517fd8e9cf03000000000000000000000000000000000000000000000000000000008152602660048201526001600160a01b0380841660248301528216604482015260009073783c952feeb792aa63908c9b85c83ab46b0bf2fd9063d8e9cf0390606401602060405180830381865af4158015612496573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ba91906134c6565b9392505050565b6000546001600160a01b031633146124ec57604051631a88efbf60e11b815260040160405180910390fd5b600360145460ff166003811115612505576125056131ee565b10612523576040516383b3712f60e01b815260040160405180910390fd5b6040517f06846dce000000000000000000000000000000000000000000000000000000008152737dac013c0caa344f7086ae3f06419be9208d6e89906306846dce9061257990602390601f908690600401613613565b60006040518083038186803b15801561259157600080fd5b505af41580156125a5573d6000803e3d6000fd5b50506014805460ff19166002179055505080516040519081527f0bed382b9aad3b5629da3f0660006b5b0ebaf727367204f573a175544a0f930d90602001611487565b6012546001600160a01b0316331461261357604051631de3f8c960e21b815260040160405180910390fd5b6040516318366f3560e21b8152602360048201526024810182905260009073c21b38fffc1bbe9cd95e7d9be962ad0dc5593e16906360d9bcd490604401600060405180830381865af415801561266d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612695919081019061380b565b905060008160e0015160058111156126af576126af6131ee565b036126cd57604051630ead561960e11b815260040160405180910390fd5b610a6682612933565b60048054610a779061337d565b6000546001600160a01b0316331461270e57604051631a88efbf60e11b815260040160405180910390fd5b601a610a668282613406565b60018054610a779061337d565b6012546001600160a01b0316331461275257604051631de3f8c960e21b815260040160405180910390fd5b61135e81612b4b565b60178054610a779061337d565b6040517f51a0cf48000000000000000000000000000000000000000000000000000000008152601f60048201526001600160a01b03831660248201526044810182905273e320252f58d744a09584c79ac4f3629fca3798cb906351a0cf489060640160006040518083038186803b1580156127e257600080fd5b505af41580156127f6573d6000803e3d6000fd5b505050506002548161280891906138db565b602d6000828254612819919061365a565b90915550610a669050612c96565b600081600581111561283b5761283b6131ee565b03612872576040517f7ec04df100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260208490526040902060068101805483919060ff191660018360058111156128a1576128a16131ee565b021790555050505050565b602a80546001810182556000918252825160029091027fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d2810182905560208401517fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d390910155602b80549192909161292590849061365a565b9091555061135e9050612c96565b6040516318366f3560e21b8152602360048201526024810182905260009073c21b38fffc1bbe9cd95e7d9be962ad0dc5593e16906360d9bcd490604401600060405180830381865af415801561298d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526129b5919081019061380b565b905060028160c0015160058111156129cf576129cf6131ee565b14612a06576040517f6b67159000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60048160e001516005811115612a1e57612a1e6131ee565b14612ace576040818101516060830151608084015192517f9030099a000000000000000000000000000000000000000000000000000000008152601f60048201526001600160a01b03928316602482015291166044820152606481019190915273e320252f58d744a09584c79ac4f3629fca3798cb90639030099a9060840160006040518083038186803b158015612ab557600080fd5b505af4158015612ac9573d6000803e3d6000fd5b505050505b60028160e001516005811115612ae657612ae66131ee565b03612afd57612afd81606001518260800151612768565b612b0a6023836003612827565b7f9bbe037a1a1faac87c3e07d5beed35ad6d3c54fbbc21637447918822abb04583828260e00151604051612b3f9291906138f2565b60405180910390a15050565b6040516318366f3560e21b8152602360048201526024810182905260009073c21b38fffc1bbe9cd95e7d9be962ad0dc5593e16906360d9bcd490604401600060405180830381865af4158015612ba5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612bcd919081019061380b565b905060008160e001516005811115612be757612be76131ee565b03612c0557604051630ead561960e11b815260040160405180910390fd5b60038160c001516005811115612c1d57612c1d6131ee565b14612c54576040517f1109e7ce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612c616023836004612827565b7fa86580040b7b220b796aa9b66b3eede5540d9130c21f31e27b6667458720f3f8828260e00151604051612b3f9291906138f2565b602d54602b54612ca6919061390f565b602c819055600254612cb791613779565b602e55565b600060208284031215612cce57600080fd5b81356001600160e01b0319811681146124ba57600080fd5b60005b83811015612d01578181015183820152602001612ce9565b50506000910152565b60008151808452612d22816020860160208601612ce6565b601f01601f19169290920160200192915050565b604081526000612d496040830185612d0a565b90506001600160a01b03831660208301529392505050565b634e487b7160e01b600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715612d9b57612d9b612d61565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612dca57612dca612d61565b604052919050565b600067ffffffffffffffff821115612dec57612dec612d61565b50601f01601f191660200190565b600082601f830112612e0b57600080fd5b8135612e1e612e1982612dd2565b612da1565b818152846020838601011115612e3357600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215612e6257600080fd5b813567ffffffffffffffff811115612e7957600080fd5b612e8584828501612dfa565b949350505050565b6020815260006124ba6020830184612d0a565b6001600160a01b038116811461135e57600080fd5b60008060408385031215612ec857600080fd5b8235612ed381612ea0565b946020939093013593505050565b600060208284031215612ef357600080fd5b5035919050565b600080600060608486031215612f0f57600080fd5b8335612f1a81612ea0565b92506020840135612f2a81612ea0565b929592945050506040919091013590565b600067ffffffffffffffff821115612f5557612f55612d61565b5060051b60200190565b600060c08284031215612f7157600080fd5b60405160c0810167ffffffffffffffff8282108183111715612f9557612f95612d61565b81604052829350843583526020850135602084015260408501359150612fba82612ea0565b81604084015260608501359150612fd082612ea0565b8160608401526080850135608084015260a0850135915080821115612ff457600080fd5b5061300185828601612dfa565b60a0830152505092915050565b6000806040838503121561302157600080fd5b823567ffffffffffffffff8082111561303957600080fd5b818501915085601f83011261304d57600080fd5b8135602061305d612e1983612f3b565b82815260059290921b8401810191818101908984111561307c57600080fd5b8286015b848110156130b4578035868111156130985760008081fd5b6130a68c86838b0101612f5f565b845250918301918301613080565b50965050860135925050808211156130cb57600080fd5b506130d885828601612dfa565b9150509250929050565b6000602082840312156130f457600080fd5b813567ffffffffffffffff81111561310b57600080fd5b612e8584828501612f5f565b60006020828403121561312957600080fd5b81356124ba81612ea0565b6020808252825182820181905260009190848201906040850190845b818110156131935761318083855180516001600160a01b0316825260208082015190830152604090810151910152565b9284019260609290920191600101613150565b50909695505050505050565b6000604082840312156131b157600080fd5b6040516040810181811067ffffffffffffffff821117156131d4576131d4612d61565b604052823581526020928301359281019290925250919050565b634e487b7160e01b600052602160045260246000fd5b6020810160048310613218576132186131ee565b91905290565b81516001600160a01b03168152602080830151908201526040808301519082015260608101610988565b6006811061135e5761135e6131ee565b61326181613248565b9052565b602081528151602082015260208201516040820152600060408301516001600160a01b0380821660608501528060608601511660808501525050608083015160a083015260a08301516101008060c08501526132c5610120850183612d0a565b915060c08501516132d960e0860182613258565b5060e08501516132eb82860182613258565b5090949350505050565b602080825282518282018190526000919060409081850190868401855b8281101561333757815180518552860151868501529284019290850190600101613312565b5091979650505050505050565b6000806040838503121561335757600080fd5b823561336281612ea0565b9150602083013561337281612ea0565b809150509250929050565b600181811c9082168061339157607f821691505b6020821081036133b157634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561340157600081815260208120601f850160051c810160208610156133de5750805b601f850160051c820191505b818110156133fd578281556001016133ea565b5050505b505050565b815167ffffffffffffffff81111561342057613420612d61565b6134348161342e845461337d565b846133b7565b602080601f83116001811461346957600084156134515750858301515b600019600386901b1c1916600185901b1785556133fd565b600085815260208120601f198616915b8281101561349857888601518255948401946001909101908401613479565b50858210156134b65787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156134d857600080fd5b5051919050565b8051825260208101516020830152600060408201516001600160a01b03808216604086015280606085015116606086015250506080820151608084015260a082015160c060a0850152612e8560c0850182612d0a565b600081518084526020808501808196508360051b8101915082860160005b8581101561333757828403895261356b8483516134df565b98850198935090840190600101613553565b828152604060208201526000612e856040830184613535565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016135d4576135d46135ac565b5060010190565b6020808252825182820181905260009190848201906040850190845b81811015613193578351835292840192918401916001016135f7565b83815282602082015260606040820152600061363260608301846134df565b95945050505050565b8381528260208201526060604082015260006136326060830184613535565b80820180821115610988576109886135ac565b8051610e1d81612ea0565b60006060828403121561368a57600080fd5b6040516060810181811067ffffffffffffffff821117156136ad576136ad612d61565b806040525080915082516136c081612ea0565b8082525060208301516020820152604083015160408201525092915050565b600060208083850312156136f257600080fd5b825167ffffffffffffffff81111561370957600080fd5b8301601f8101851361371a57600080fd5b8051613728612e1982612f3b565b8181526060918202830184019184820191908884111561374757600080fd5b938501935b8385101561376d5761375e8986613678565b8352938401939185019161374c565b50979650505050505050565b60008261379657634e487b7160e01b600052601260045260246000fd5b500490565b6000606082840312156137ad57600080fd5b6124ba8383613678565b600082601f8301126137c857600080fd5b81516137d6612e1982612dd2565b8181528460208386010111156137eb57600080fd5b612e85826020830160208701612ce6565b805160068110610e1d57600080fd5b60006020828403121561381d57600080fd5b815167ffffffffffffffff8082111561383557600080fd5b90830190610100828603121561384a57600080fd5b613852612d77565b825181526020830151602082015261386c6040840161366d565b604082015261387d6060840161366d565b60608201526080830151608082015260a08301518281111561389e57600080fd5b6138aa878286016137b7565b60a0830152506138bc60c084016137fc565b60c08201526138cd60e084016137fc565b60e082015295945050505050565b8082028115828204841417610988576109886135ac565b8281526040810161390283613248565b8260208301529392505050565b81810381811115610988576109886135ac56fea26469706673582212206b14e1154ef6f2ad60e97f357f0e3f3018b51011d5f6cfc870fed9abac6e424564736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004a0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000068000000000000000000000000000000000000000000000000000000000000006c0000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000007800000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000088000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000980000000000000000000000000a72cd393790f4d85da4d348d7a6cc7de05d0f68100000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000006b0cbc8000000000000000000000000000000000000000000000000000000000009896800000000000000000000000000000000000000000000000000000000000000a400000000000000000000000000000000000000000000000000000000000000aa00000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000000000006567d08000000000000000000000000000000000000000000000000000000000000000034e2f41000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000717b22696e74657265737452617465223a3430312c22636f75706f6e7061796d656e74416d6f756e7463656e74223a343031352c2266696e616c526564656d7074696f6e416d6f756e7450657263656e74223a31303030302c22696e7465726573745061796d656e7444617465223a5b5d7d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000867b2273656375726974794f6e636861696e436172626f6e466f6f747072696e74457374696d6174654b67434f326571756976616c656e74427959656172223a22302e3634222c22657374696d61746544617465223a22323032332d31312d3330222c227265706f7274223a22687474703a2f2f7777772e7367666f7267652e636f6d2f227d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009556e736563757265640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002253454355524954595f544f4b454e535f494e5f5245474953545245445f464f524d5300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034e2f4100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007454d544e205347000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017687474703a2f2f7374723a363636302f6772617068716c0000000000000000000000000000000000000000000000000000000000000000000000000000000006626f6e64563100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000dc03823bbccc2fe2a6cea8976ab803709c1be0a400000000000000000000000000000000000000000000000000000000000000194f32524e453849425850345230544438505534312d4446494e000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000dc03823bbccc2fe2a6cea8976ab803709c1be0a400000000000000000000000000000000000000000000000000000000000000194f32524e453849425850345230544438505534312d4446494e00000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000065980908e77b276c3e6cd73f609da62d1fc8e062000000000000000000000000000000000000000000000000000000000000001a4f32524e453849425850345230544438505534312d20534753530000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000e08106fad4add8dbffbbd0813027625a57c06fbd000000000000000000000000000000000000000000000000000000000000000d464f5247455f534554544c455200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000089ace546613b2cbb4510eab030a61bcdd11c8b8500000000000000000000000000000000000000000000000000000000000000143936393530304658384b34305a4457344633373700000000000000000000000000000000000000000000000000000000000000000000000000000000000000034555520000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a4c5558454d424f55524700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000246520000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040534f43494554452047454e4552414c45204555522031304d203359204449474954414c20475245454e2053454e494f5220505245464552524544204e4f5445530000000000000000000000000000000000000000000000000000000000000040534f43494554452047454e4552414c45204555522031304d203359204449474954414c20475245454e2053454e494f5220505245464552524544204e4f544553000000000000000000000000000000000000000000000000000000000000000c46523030313430304d4447350000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : basicProductInput (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
-----Encoded View---------------
91 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000340
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000360
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 00000000000000000000000000000000000000000000000000000000000003c0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000400
Arg [6] : 00000000000000000000000000000000000000000000000000000000000004a0
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000560
Arg [8] : 00000000000000000000000000000000000000000000000000000000000005a0
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000600
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000640
Arg [11] : 0000000000000000000000000000000000000000000000000000000000000680
Arg [12] : 00000000000000000000000000000000000000000000000000000000000006c0
Arg [13] : 0000000000000000000000000000000000000000000000000000000000000700
Arg [14] : 0000000000000000000000000000000000000000000000000000000000000780
Arg [15] : 0000000000000000000000000000000000000000000000000000000000000800
Arg [16] : 0000000000000000000000000000000000000000000000000000000000000880
Arg [17] : 0000000000000000000000000000000000000000000000000000000000000900
Arg [18] : 0000000000000000000000000000000000000000000000000000000000000980
Arg [19] : 000000000000000000000000a72cd393790f4d85da4d348d7a6cc7de05d0f681
Arg [20] : 00000000000000000000000000000000000000000000000000000000000009c0
Arg [21] : 0000000000000000000000000000000000000000000000000000000000000a00
Arg [22] : 000000000000000000000000000000000000000000000000000000006b0cbc80
Arg [23] : 0000000000000000000000000000000000000000000000000000000000989680
Arg [24] : 0000000000000000000000000000000000000000000000000000000000000a40
Arg [25] : 0000000000000000000000000000000000000000000000000000000000000aa0
Arg [26] : 0000000000000000000000000000000000000000000000000000000000000b00
Arg [27] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [28] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [29] : 000000000000000000000000000000000000000000000000000000003b9aca00
Arg [30] : 000000000000000000000000000000000000000000000000000000006567d080
Arg [31] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [32] : 4e2f410000000000000000000000000000000000000000000000000000000000
Arg [33] : 0000000000000000000000000000000000000000000000000000000000000071
Arg [34] : 7b22696e74657265737452617465223a3430312c22636f75706f6e7061796d65
Arg [35] : 6e74416d6f756e7463656e74223a343031352c2266696e616c526564656d7074
Arg [36] : 696f6e416d6f756e7450657263656e74223a31303030302c22696e7465726573
Arg [37] : 745061796d656e7444617465223a5b5d7d000000000000000000000000000000
Arg [38] : 0000000000000000000000000000000000000000000000000000000000000086
Arg [39] : 7b2273656375726974794f6e636861696e436172626f6e466f6f747072696e74
Arg [40] : 457374696d6174654b67434f326571756976616c656e74427959656172223a22
Arg [41] : 302e3634222c22657374696d61746544617465223a22323032332d31312d3330
Arg [42] : 222c227265706f7274223a22687474703a2f2f7777772e7367666f7267652e63
Arg [43] : 6f6d2f227d200000000000000000000000000000000000000000000000000000
Arg [44] : 0000000000000000000000000000000000000000000000000000000000000009
Arg [45] : 556e736563757265640000000000000000000000000000000000000000000000
Arg [46] : 0000000000000000000000000000000000000000000000000000000000000022
Arg [47] : 53454355524954595f544f4b454e535f494e5f5245474953545245445f464f52
Arg [48] : 4d53000000000000000000000000000000000000000000000000000000000000
Arg [49] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [50] : 4e2f410000000000000000000000000000000000000000000000000000000000
Arg [51] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [52] : 454d544e20534700000000000000000000000000000000000000000000000000
Arg [53] : 0000000000000000000000000000000000000000000000000000000000000017
Arg [54] : 687474703a2f2f7374723a363636302f6772617068716c000000000000000000
Arg [55] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [56] : 626f6e6456310000000000000000000000000000000000000000000000000000
Arg [57] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [58] : 000000000000000000000000dc03823bbccc2fe2a6cea8976ab803709c1be0a4
Arg [59] : 0000000000000000000000000000000000000000000000000000000000000019
Arg [60] : 4f32524e453849425850345230544438505534312d4446494e00000000000000
Arg [61] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [62] : 000000000000000000000000dc03823bbccc2fe2a6cea8976ab803709c1be0a4
Arg [63] : 0000000000000000000000000000000000000000000000000000000000000019
Arg [64] : 4f32524e453849425850345230544438505534312d4446494e00000000000000
Arg [65] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [66] : 00000000000000000000000065980908e77b276c3e6cd73f609da62d1fc8e062
Arg [67] : 000000000000000000000000000000000000000000000000000000000000001a
Arg [68] : 4f32524e453849425850345230544438505534312d2053475353000000000000
Arg [69] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [70] : 000000000000000000000000e08106fad4add8dbffbbd0813027625a57c06fbd
Arg [71] : 000000000000000000000000000000000000000000000000000000000000000d
Arg [72] : 464f5247455f534554544c455200000000000000000000000000000000000000
Arg [73] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [74] : 00000000000000000000000089ace546613b2cbb4510eab030a61bcdd11c8b85
Arg [75] : 0000000000000000000000000000000000000000000000000000000000000014
Arg [76] : 3936393530304658384b34305a44573446333737000000000000000000000000
Arg [77] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [78] : 4555520000000000000000000000000000000000000000000000000000000000
Arg [79] : 000000000000000000000000000000000000000000000000000000000000000a
Arg [80] : 4c5558454d424f55524700000000000000000000000000000000000000000000
Arg [81] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [82] : 4652000000000000000000000000000000000000000000000000000000000000
Arg [83] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [84] : 534f43494554452047454e4552414c45204555522031304d2033592044494749
Arg [85] : 54414c20475245454e2053454e494f5220505245464552524544204e4f544553
Arg [86] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [87] : 534f43494554452047454e4552414c45204555522031304d2033592044494749
Arg [88] : 54414c20475245454e2053454e494f5220505245464552524544204e4f544553
Arg [89] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [90] : 46523030313430304d4447350000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 29 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.