More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 2,194 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Batch Payments | 21756197 | 5 hrs ago | IN | 0 ETH | 0.00247497 | ||||
Batch Payments | 21752330 | 18 hrs ago | IN | 0 ETH | 0.00253862 | ||||
Batch Payments | 21752306 | 18 hrs ago | IN | 0 ETH | 0.00805429 | ||||
Batch Payments | 21746131 | 39 hrs ago | IN | 0 ETH | 0.00244401 | ||||
Batch Payments | 21745822 | 40 hrs ago | IN | 0 ETH | 0.01358843 | ||||
Batch Payments | 21744283 | 45 hrs ago | IN | 0 ETH | 0.00112926 | ||||
Batch Payments | 21744122 | 45 hrs ago | IN | 0 ETH | 0.00121342 | ||||
Batch Payments | 21744104 | 45 hrs ago | IN | 0 ETH | 0.00033019 | ||||
Batch Payments | 21744099 | 45 hrs ago | IN | 0 ETH | 0.00030176 | ||||
Batch Payments | 21743966 | 46 hrs ago | IN | 0 ETH | 0.00077168 | ||||
Batch Payments | 21743227 | 2 days ago | IN | 0 ETH | 0.00046008 | ||||
Batch Payments | 21742562 | 2 days ago | IN | 0 ETH | 0.00031799 | ||||
Batch Payments | 21741784 | 2 days ago | IN | 0 ETH | 0.00023683 | ||||
Batch Payments | 21739545 | 2 days ago | IN | 0 ETH | 0.00091963 | ||||
Batch Payments | 21738878 | 2 days ago | IN | 0 ETH | 0.00425179 | ||||
Batch Payments | 21738776 | 2 days ago | IN | 0 ETH | 0.00292561 | ||||
Batch Payments | 21737889 | 2 days ago | IN | 0 ETH | 0.00086747 | ||||
Batch Payments | 21737864 | 2 days ago | IN | 0 ETH | 0.00215775 | ||||
Batch Payments | 21737818 | 2 days ago | IN | 0 ETH | 0.0029467 | ||||
Batch Payments | 21737802 | 2 days ago | IN | 0 ETH | 0.00720668 | ||||
Batch Payments | 21736034 | 3 days ago | IN | 0 ETH | 0.00038013 | ||||
Batch Payments | 21736033 | 3 days ago | IN | 0 ETH | 0.00077525 | ||||
Batch Payments | 21735986 | 3 days ago | IN | 7.33718178 ETH | 0.00050423 | ||||
Batch Payments | 21734453 | 3 days ago | IN | 0 ETH | 0.00042982 | ||||
Batch Payments | 21731324 | 3 days ago | IN | 0 ETH | 0.00210863 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
21735986 | 3 days ago | 0.21370432 ETH | ||||
21735986 | 3 days ago | 0.21370432 ETH | ||||
21735986 | 3 days ago | 7.33718178 ETH | ||||
21723184 | 4 days ago | 0.00965081 ETH | ||||
21723184 | 4 days ago | 0.00965081 ETH | ||||
21723184 | 4 days ago | 0.05665816 ETH | ||||
21723184 | 4 days ago | 0.05665816 ETH | ||||
21723184 | 4 days ago | 0.15112553 ETH | ||||
21723184 | 4 days ago | 0.15112553 ETH | ||||
21687110 | 9 days ago | 0.02098049 ETH | ||||
21687110 | 9 days ago | 0.02098049 ETH | ||||
21687110 | 9 days ago | 0.7203304 ETH | ||||
21664545 | 13 days ago | 1.7 ETH | ||||
21664545 | 13 days ago | 1.7 ETH | ||||
21622943 | 18 days ago | 0.00115846 ETH | ||||
21622943 | 18 days ago | 0.00115846 ETH | ||||
21622943 | 18 days ago | 0.01207595 ETH | ||||
21622943 | 18 days ago | 0.01207595 ETH | ||||
21622943 | 18 days ago | 0.01522106 ETH | ||||
21622943 | 18 days ago | 0.01522106 ETH | ||||
21536998 | 30 days ago | 1 ETH | ||||
21536998 | 30 days ago | 1 ETH | ||||
21518987 | 33 days ago | 0.20410543 ETH | ||||
21518987 | 33 days ago | 0.20410543 ETH | ||||
21518987 | 33 days ago | 7.00761999 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
BatchConversionPayments
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import './interfaces/IERC20ConversionProxy.sol'; import './interfaces/IEthConversionProxy.sol'; import './BatchNoConversionPayments.sol'; /** * @title BatchConversionPayments * @notice This contract makes multiple conversion payments with references, in one transaction: * - on: * - ERC20 tokens: using Erc20ConversionProxy and ERC20FeeProxy * - Native tokens: (e.g. ETH) using EthConversionProxy and EthereumFeeProxy * - to: multiple addresses * - fees: conversion proxy fees and additional batch conversion fees are paid to the same address. * batchPayments is the main function to batch all kinds of payments at once. * If one transaction of the batch fails, all transactions are reverted. * @dev batchPayments is the main function, but other batch payment functions are "public" in order to do * gas optimization in some cases. */ contract BatchConversionPayments is BatchNoConversionPayments { using SafeERC20 for IERC20; IERC20ConversionProxy public paymentErc20ConversionProxy; IEthConversionProxy public paymentNativeConversionProxy; /** payerAuthorized is set to true to workaround the non-payable aspect in batch native conversion */ bool private payerAuthorized = false; /** * @dev Used by the batchPayments to handle information for heterogeneous batches, grouped by payment network: * - paymentNetworkId: from 0 to 4, cf. `batchPayments()` method * - requestDetails all the data required for conversion and no conversion requests to be paid */ struct MetaDetail { uint256 paymentNetworkId; RequestDetail[] requestDetails; } /** * @param _paymentErc20Proxy The ERC20 payment proxy address to use. * @param _paymentNativeProxy The native payment proxy address to use. * @param _paymentErc20ConversionProxy The ERC20 Conversion payment proxy address to use. * @param _paymentNativeConversionFeeProxy The native Conversion payment proxy address to use. * @param _chainlinkConversionPath The address of the conversion path contract. * @param _owner Owner of the contract. */ constructor( address _paymentErc20Proxy, address _paymentNativeProxy, address _paymentErc20ConversionProxy, address _paymentNativeConversionFeeProxy, address _chainlinkConversionPath, address _owner ) BatchNoConversionPayments( _paymentErc20Proxy, _paymentNativeProxy, _chainlinkConversionPath, _owner ) { paymentErc20ConversionProxy = IERC20ConversionProxy(_paymentErc20ConversionProxy); paymentNativeConversionProxy = IEthConversionProxy(_paymentNativeConversionFeeProxy); } /** * This contract is non-payable. * Making a Native payment with conversion requires the contract to accept incoming Native tokens. * @dev See the end of `paymentNativeConversionProxy.transferWithReferenceAndFee` where the leftover is given back. */ receive() external payable override { require(payerAuthorized || msg.value == 0, 'Non-payable'); } /** * @notice Batch payments on different payment networks at once. * @param metaDetails contains paymentNetworkId and requestDetails * - batchMultiERC20ConversionPayments, paymentNetworkId=0 * - batchERC20Payments, paymentNetworkId=1 * - batchMultiERC20Payments, paymentNetworkId=2 * - batchNativePayments, paymentNetworkId=3 * - batchNativeConversionPayments, paymentNetworkId=4 * If metaDetails use paymentNetworkId = 4, it must be at the end of the list, or the transaction can be reverted. * @param pathsToUSD The list of paths into USD for every token, used to limit the batch fees. * For batch native, mock an array of array to apply the limit, e.g: [[]] * Without paths, there is not limitation, neither for the batch native functions. * @param feeAddress The address where fees should be paid. * @dev Use pathsToUSD only if you are pretty sure the batch fees will higher than the * USD limit batchFeeAmountUSDLimit, because it increase gas consumption. * batchPayments only reduces gas consumption when using more than a single payment network. * For single payment network payments, it is more efficient to use the suited batch function. */ function batchPayments( MetaDetail[] calldata metaDetails, address[][] calldata pathsToUSD, address feeAddress ) external payable { require(metaDetails.length < 6, 'more than 5 metaDetails'); uint256 batchFeeAmountUSD = 0; for (uint256 i = 0; i < metaDetails.length; i++) { MetaDetail calldata metaDetail = metaDetails[i]; if (metaDetail.paymentNetworkId == 0) { batchFeeAmountUSD += _batchMultiERC20ConversionPayments( metaDetail.requestDetails, batchFeeAmountUSD, pathsToUSD, feeAddress ); } else if (metaDetail.paymentNetworkId == 1) { batchFeeAmountUSD += _batchERC20Payments( metaDetail.requestDetails, pathsToUSD, batchFeeAmountUSD, payable(feeAddress) ); } else if (metaDetail.paymentNetworkId == 2) { batchFeeAmountUSD += _batchMultiERC20Payments( metaDetail.requestDetails, pathsToUSD, batchFeeAmountUSD, feeAddress ); } else if (metaDetail.paymentNetworkId == 3) { if (metaDetails[metaDetails.length - 1].paymentNetworkId == 4) { // Set to false only if batchNativeConversionPayments is called after this function transferBackRemainingNativeTokens = false; } batchFeeAmountUSD += _batchNativePayments( metaDetail.requestDetails, pathsToUSD.length == 0, batchFeeAmountUSD, payable(feeAddress) ); if (metaDetails[metaDetails.length - 1].paymentNetworkId == 4) { transferBackRemainingNativeTokens = true; } } else if (metaDetail.paymentNetworkId == 4) { batchFeeAmountUSD += _batchNativeConversionPayments( metaDetail.requestDetails, pathsToUSD.length == 0, batchFeeAmountUSD, payable(feeAddress) ); } else { revert('Wrong paymentNetworkId'); } } } /** * @notice Send a batch of ERC20 payments with amounts based on a request * currency (e.g. fiat), with fees and paymentReferences to multiple accounts, with multiple tokens. * @param requestDetails List of ERC20 requests denominated in fiat to pay. * @param pathsToUSD The list of paths into USD for every token, used to limit the batch fees. * Without paths, there is not a fee limitation, and it consumes less gas. * @param feeAddress The fee recipient. */ function batchMultiERC20ConversionPayments( RequestDetail[] calldata requestDetails, address[][] calldata pathsToUSD, address feeAddress ) public returns (uint256) { return _batchMultiERC20ConversionPayments(requestDetails, 0, pathsToUSD, feeAddress); } /** * @notice Send a batch of Native conversion payments with fees and paymentReferences to multiple accounts. * If one payment fails, the whole batch is reverted. * @param requestDetails List of native requests denominated in fiat to pay. * @param skipFeeUSDLimit Setting the value to true skips the USD fee limit, and reduces gas consumption. * @param feeAddress The fee recipient. * @dev It uses NativeConversionProxy (EthereumConversionProxy) to pay an invoice and fees. * Please: * Note that if there is not enough Native token attached to the function call, * the following error is thrown: "revert paymentProxy transferExactEthWithReferenceAndFee failed" */ function batchNativeConversionPayments( RequestDetail[] calldata requestDetails, bool skipFeeUSDLimit, address payable feeAddress ) public payable returns (uint256) { return _batchNativeConversionPayments(requestDetails, skipFeeUSDLimit, 0, feeAddress); } /** * @notice Send a batch of ERC20 payments with amounts based on a request * currency (e.g. fiat), with fees and paymentReferences to multiple accounts, with multiple tokens. * @param requestDetails List of ERC20 requests denominated in fiat to pay. * @param batchFeeAmountUSD The batch fee amount in USD already paid. * @param pathsToUSD The list of paths into USD for every token, used to limit the batch fees. * Without paths, there is not a fee limitation, and it consumes less gas. * @param feeAddress The fee recipient. */ function _batchMultiERC20ConversionPayments( RequestDetail[] calldata requestDetails, uint256 batchFeeAmountUSD, address[][] calldata pathsToUSD, address feeAddress ) private returns (uint256) { Token[] memory uTokens = getUTokens(requestDetails); IERC20 requestedToken; // For each token: check allowance, transfer funds on the contract and approve the paymentProxy to spend if needed for (uint256 k = 0; k < uTokens.length && uTokens[k].amountAndFee > 0; k++) { uTokens[k].batchFeeAmount = (uTokens[k].amountAndFee * batchFee) / feeDenominator; requestedToken = IERC20(uTokens[k].tokenAddress); transferToContract( requestedToken, uTokens[k].amountAndFee, uTokens[k].batchFeeAmount, address(paymentErc20ConversionProxy) ); } // Batch pays the requests using Erc20ConversionFeeProxy for (uint256 i = 0; i < requestDetails.length; i++) { RequestDetail calldata rD = requestDetails[i]; paymentErc20ConversionProxy.transferFromWithReferenceAndFee( rD.recipient, rD.requestAmount, rD.path, rD.paymentReference, rD.feeAmount, feeAddress, rD.maxToSpend, rD.maxRateTimespan ); } // Batch sends back to the payer the tokens not spent and pays the batch fee for (uint256 k = 0; k < uTokens.length && uTokens[k].amountAndFee > 0; k++) { requestedToken = IERC20(uTokens[k].tokenAddress); // Batch sends back to the payer the tokens not spent = excessAmount // excessAmount = maxToSpend - reallySpent, which is equal to the remaining tokens on the contract uint256 excessAmount = requestedToken.balanceOf(address(this)); if (excessAmount > 0) { requestedToken.safeTransfer(msg.sender, excessAmount); } // Calculate batch fee to pay uint256 batchFeeToPay = ((uTokens[k].amountAndFee - excessAmount) * batchFee) / feeDenominator; (batchFeeToPay, batchFeeAmountUSD) = calculateBatchFeeToPay( batchFeeToPay, uTokens[k].tokenAddress, batchFeeAmountUSD, pathsToUSD ); // Payer pays the exact batch fees amount require( safeTransferFrom(uTokens[k].tokenAddress, feeAddress, batchFeeToPay), 'Batch fee transferFrom() failed' ); } return batchFeeAmountUSD; } /** * @notice Send a batch of Native conversion payments with fees and paymentReferences to multiple accounts. * If one payment fails, the whole batch is reverted. * @param requestDetails List of native requests denominated in fiat to pay. * @param skipFeeUSDLimit Setting the value to true skips the USD fee limit, and reduces gas consumption. * @param batchFeeAmountUSD The batch fee amount in USD already paid. * @param feeAddress The fee recipient. * @dev It uses NativeConversionProxy (EthereumConversionProxy) to pay an invoice and fees. * Please: * Note that if there is not enough Native token attached to the function call, * the following error is thrown: "revert paymentProxy transferExactEthWithReferenceAndFee failed" */ function _batchNativeConversionPayments( RequestDetail[] calldata requestDetails, bool skipFeeUSDLimit, uint256 batchFeeAmountUSD, address payable feeAddress ) private returns (uint256) { uint256 contractBalance = address(this).balance; payerAuthorized = true; // Batch contract pays the requests through nativeConversionProxy for (uint256 i = 0; i < requestDetails.length; i++) { RequestDetail calldata rD = requestDetails[i]; paymentNativeConversionProxy.transferWithReferenceAndFee{value: address(this).balance}( payable(rD.recipient), rD.requestAmount, rD.path, rD.paymentReference, rD.feeAmount, feeAddress, rD.maxRateTimespan ); } // Batch contract pays batch fee uint256 batchFeeToPay = (((contractBalance - address(this).balance)) * batchFee) / feeDenominator; if (skipFeeUSDLimit == false) { (batchFeeToPay, batchFeeAmountUSD) = calculateBatchFeeToPay( batchFeeToPay, pathsNativeToUSD[0][0], batchFeeAmountUSD, pathsNativeToUSD ); } require(address(this).balance >= batchFeeToPay, 'Not enough funds for batch conversion fees'); feeAddress.transfer(batchFeeToPay); // Batch contract transfers the remaining native tokens to the payer (bool sendBackSuccess, ) = payable(msg.sender).call{value: address(this).balance}(''); require(sendBackSuccess, 'Could not send remaining funds to the payer'); payerAuthorized = false; return batchFeeAmountUSD; } /* * Admin functions to edit the conversion proxies address and fees. */ /** * @param _paymentErc20ConversionProxy The address of the ERC20 Conversion payment proxy to use. * Update cautiously, the proxy has to match the invoice proxy. */ function setPaymentErc20ConversionProxy(address _paymentErc20ConversionProxy) external onlyOwner { paymentErc20ConversionProxy = IERC20ConversionProxy(_paymentErc20ConversionProxy); } /** * @param _paymentNativeConversionProxy The address of the native Conversion payment proxy to use. * Update cautiously, the proxy has to match the invoice proxy. */ function setPaymentNativeConversionProxy(address _paymentNativeConversionProxy) external onlyOwner { paymentNativeConversionProxy = IEthConversionProxy(_paymentNativeConversionProxy); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IERC20ConversionProxy { // Event to declare a conversion with a reference event TransferWithConversionAndReference( uint256 amount, address currency, bytes indexed paymentReference, uint256 feeAmount, uint256 maxRateTimespan ); // Event to declare a transfer with a reference event TransferWithReferenceAndFee( address tokenAddress, address to, uint256 amount, bytes indexed paymentReference, uint256 feeAmount, address feeAddress ); function transferFromWithReferenceAndFee( address _to, uint256 _requestAmount, address[] calldata _path, bytes calldata _paymentReference, uint256 _feeAmount, address _feeAddress, uint256 _maxToSpend, uint256 _maxRateTimespan ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title IEthConversionProxy * @notice This contract converts from chainlink then swaps ETH (or native token) * before paying a request thanks to a conversion payment proxy. * The inheritance from ReentrancyGuard is required to perform * "transferExactEthWithReferenceAndFee" on the eth-fee-proxy contract */ interface IEthConversionProxy { // Event to declare a conversion with a reference event TransferWithConversionAndReference( uint256 amount, address currency, bytes indexed paymentReference, uint256 feeAmount, uint256 maxRateTimespan ); // Event to declare a transfer with a reference // This event is emitted by this contract from a delegate call of the payment-proxy event TransferWithReferenceAndFee( address to, uint256 amount, bytes indexed paymentReference, uint256 feeAmount, address feeAddress ); /** * @notice Performs an ETH transfer with a reference computing the payment amount based on the request amount * @param _to Transfer recipient of the payement * @param _requestAmount Request amount * @param _path Conversion path * @param _paymentReference Reference of the payment related * @param _feeAmount The amount of the payment fee * @param _feeAddress The fee recipient * @param _maxRateTimespan Max time span with the oldestrate, ignored if zero */ function transferWithReferenceAndFee( address _to, uint256 _requestAmount, address[] calldata _path, bytes calldata _paymentReference, uint256 _feeAmount, address _feeAddress, uint256 _maxRateTimespan ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import './lib/SafeERC20.sol'; import '@openzeppelin/contracts/access/Ownable.sol'; import './interfaces/ERC20FeeProxy.sol'; import './interfaces/EthereumFeeProxy.sol'; import './ChainlinkConversionPath.sol'; /** * @title BatchNoConversionPayments * @notice This contract makes multiple payments with references, in one transaction: * - on: ERC20 Payment Proxy and Native (ETH) Payment Proxy of the Request Network protocol * - to: multiple addresses * - fees: ERC20 and Native (ETH) proxies fees are paid to the same address * An additional batch fee is paid to the same address * If one transaction of the batch fail, every transactions are reverted. * @dev It is a clone of BatchPayment.sol, with three main modifications: * - function "receive" has one other condition: payerAuthorized * - fees are now divided by 10_000 instead of 1_000 in previous version * - batch payment functions have new names and are now public, instead of external */ contract BatchNoConversionPayments is Ownable { using SafeERC20 for IERC20; IERC20FeeProxy public paymentErc20Proxy; IEthereumFeeProxy public paymentNativeProxy; ChainlinkConversionPath public chainlinkConversionPath; /** Used to calculate batch fees: batchFee = 30 represent 0.30% of fee */ uint16 public batchFee; /** Used to calculate batch fees: divide batchFee by feeDenominator */ uint16 internal feeDenominator = 10000; /** The amount of the batch fee cannot exceed a predefined amount in USD, e.g: batchFeeAmountUSDLimit = 150 * 1e8 represents $150 */ uint64 public batchFeeAmountUSDLimit; /** transferBackRemainingNativeTokens is set to false only if the payer use batchPayments and call both batchNativePayments and batchNativeConversionPayments */ bool internal transferBackRemainingNativeTokens = true; address public USDAddress; address public NativeAddress; address[][] public pathsNativeToUSD; /** Contains the address of a token, the sum of the amount and fees paid with it, and the batch fee amount */ struct Token { address tokenAddress; uint256 amountAndFee; uint256 batchFeeAmount; } /** * @dev All the information of a request, except the feeAddress * recipient: Recipient address of the payment * requestAmount: Request amount, in fiat for conversion payment * path: Only for conversion payment: the conversion path * paymentReference: Unique reference of the payment * feeAmount: The fee amount, denominated in the first currency of `path` for conversion payment * maxToSpend: Only for conversion payment: * Maximum amount the payer wants to spend, denominated in the last currency of `path`: * it includes fee proxy but NOT the batch fees to pay * maxRateTimespan: Only for conversion payment: * Max acceptable times span for conversion rates, ignored if zero */ struct RequestDetail { address recipient; uint256 requestAmount; address[] path; bytes paymentReference; uint256 feeAmount; uint256 maxToSpend; uint256 maxRateTimespan; } /** * @param _paymentErc20Proxy The address to the ERC20 fee payment proxy to use. * @param _paymentNativeProxy The address to the Native fee payment proxy to use. * @param _chainlinkConversionPath The address of the conversion path contract. * @param _owner Owner of the contract. */ constructor( address _paymentErc20Proxy, address _paymentNativeProxy, address _chainlinkConversionPath, address _owner ) { paymentErc20Proxy = IERC20FeeProxy(_paymentErc20Proxy); paymentNativeProxy = IEthereumFeeProxy(_paymentNativeProxy); chainlinkConversionPath = ChainlinkConversionPath(_chainlinkConversionPath); transferOwnership(_owner); batchFee = 0; } /** * This contract is non-payable. * @dev See the end of `paymentNativeProxy.transferWithReferenceAndFee` where the leftover is given back. */ receive() external payable virtual { require(msg.value == 0, 'Non-payable'); } /** * @notice Send a batch of Native token payments with fees and paymentReferences to multiple accounts. * If one payment fails, the whole batch reverts. * @param requestDetails List of Native tokens requests to pay. * @param skipFeeUSDLimit Setting the value to true skips the USD fee limit, and reduces gas consumption. * @param feeAddress The fee recipient. * @dev It uses NativeFeeProxy (EthereumFeeProxy) to pay an invoice and fees with a payment reference. * Make sure: msg.value >= sum(_amouts)+sum(_feeAmounts)+sumBatchFeeAmount */ function batchNativePayments( RequestDetail[] calldata requestDetails, bool skipFeeUSDLimit, address payable feeAddress ) public payable returns (uint256) { return _batchNativePayments(requestDetails, skipFeeUSDLimit, 0, payable(feeAddress)); } /** * @notice Send a batch of ERC20 payments with fees and paymentReferences to multiple accounts. * @param requestDetails List of ERC20 requests to pay, with only one ERC20 token. * @param pathsToUSD The list of paths into USD for every token, used to limit the batch fees. * Without paths, there is not a fee limitation, and it consumes less gas. * @param feeAddress The fee recipient. * @dev Uses ERC20FeeProxy to pay an invoice and fees, with a payment reference. * Make sure this contract has enough allowance to spend the payer's token. * Make sure the payer has enough tokens to pay the amount, the fee, and the batch fee. */ function batchERC20Payments( RequestDetail[] calldata requestDetails, address[][] calldata pathsToUSD, address feeAddress ) public returns (uint256) { return _batchERC20Payments(requestDetails, pathsToUSD, 0, feeAddress); } /** * @notice Send a batch of ERC20 payments with fees and paymentReferences to multiple accounts, with multiple tokens. * @param requestDetails List of ERC20 requests to pay. * @param pathsToUSD The list of paths into USD for every token, used to limit the batch fees. * Without paths, there is not a fee limitation, and it consumes less gas. * @param feeAddress The fee recipient. * @dev It uses ERC20FeeProxy to pay an invoice and fees, with a payment reference. * Make sure this contract has enough allowance to spend the payer's token. * Make sure the payer has enough tokens to pay the amount, the fee, and the batch fee. */ function batchMultiERC20Payments( RequestDetail[] calldata requestDetails, address[][] calldata pathsToUSD, address feeAddress ) public returns (uint256) { return _batchMultiERC20Payments(requestDetails, pathsToUSD, 0, feeAddress); } /** * @notice Send a batch of Native token payments with fees and paymentReferences to multiple accounts. * If one payment fails, the whole batch reverts. * @param requestDetails List of Native tokens requests to pay. * @param skipFeeUSDLimit Setting the value to true skips the USD fee limit, and reduces gas consumption. * @param batchFeeAmountUSD The batch fee amount in USD already paid. * @param feeAddress The fee recipient. * @dev It uses NativeFeeProxy (EthereumFeeProxy) to pay an invoice and fees with a payment reference. * Make sure: msg.value >= sum(_amouts)+sum(_feeAmounts)+sumBatchFeeAmount */ function _batchNativePayments( RequestDetail[] calldata requestDetails, bool skipFeeUSDLimit, uint256 batchFeeAmountUSD, address payable feeAddress ) internal returns (uint256) { // amount is used to get the total amount and then used as batch fee amount uint256 amount = 0; // Batch contract pays the requests thourgh NativeFeeProxy (EthFeeProxy) for (uint256 i = 0; i < requestDetails.length; i++) { RequestDetail calldata rD = requestDetails[i]; require(address(this).balance >= rD.requestAmount + rD.feeAmount, 'Not enough funds'); amount += rD.requestAmount; paymentNativeProxy.transferWithReferenceAndFee{value: rD.requestAmount + rD.feeAmount}( payable(rD.recipient), rD.paymentReference, rD.feeAmount, payable(feeAddress) ); } // amount is updated into batch fee amount amount = (amount * batchFee) / feeDenominator; if (skipFeeUSDLimit == false) { (amount, batchFeeAmountUSD) = calculateBatchFeeToPay( amount, pathsNativeToUSD[0][0], batchFeeAmountUSD, pathsNativeToUSD ); } // Check that batch contract has enough funds to pay batch fee require(address(this).balance >= amount, 'Not enough funds for batch fee'); // Batch pays batch fee feeAddress.transfer(amount); // Batch contract transfers the remaining Native tokens to the payer if (transferBackRemainingNativeTokens && address(this).balance > 0) { (bool sendBackSuccess, ) = payable(msg.sender).call{value: address(this).balance}(''); require(sendBackSuccess, 'Could not send remaining funds to the payer'); } return batchFeeAmountUSD; } /** * @notice Send a batch of ERC20 payments with fees and paymentReferences to multiple accounts. * @param requestDetails List of ERC20 requests to pay, with only one ERC20 token. * @param pathsToUSD The list of paths into USD for every token, used to limit the batch fees. * Without paths, there is not a fee limitation, and it consumes less gas. * @param batchFeeAmountUSD The batch fee amount in USD already paid. * @param feeAddress The fee recipient. * @dev Uses ERC20FeeProxy to pay an invoice and fees, with a payment reference. * Make sure this contract has enough allowance to spend the payer's token. * Make sure the payer has enough tokens to pay the amount, the fee, and the batch fee. */ function _batchERC20Payments( RequestDetail[] calldata requestDetails, address[][] calldata pathsToUSD, uint256 batchFeeAmountUSD, address feeAddress ) internal returns (uint256) { uint256 amountAndFee = 0; uint256 batchFeeAmount = 0; for (uint256 i = 0; i < requestDetails.length; i++) { amountAndFee += requestDetails[i].requestAmount + requestDetails[i].feeAmount; batchFeeAmount += requestDetails[i].requestAmount; } batchFeeAmount = (batchFeeAmount * batchFee) / feeDenominator; // batchFeeToPay and batchFeeAmountUSD are updated if needed (batchFeeAmount, batchFeeAmountUSD) = calculateBatchFeeToPay( batchFeeAmount, requestDetails[0].path[0], batchFeeAmountUSD, pathsToUSD ); IERC20 requestedToken = IERC20(requestDetails[0].path[0]); transferToContract(requestedToken, amountAndFee, batchFeeAmount, address(paymentErc20Proxy)); // Payer pays batch fee amount require( safeTransferFrom(requestDetails[0].path[0], feeAddress, batchFeeAmount), 'Batch fee transferFrom() failed' ); // Batch contract pays the requests using Erc20FeeProxy for (uint256 i = 0; i < requestDetails.length; i++) { RequestDetail calldata rD = requestDetails[i]; paymentErc20Proxy.transferFromWithReferenceAndFee( rD.path[0], rD.recipient, rD.requestAmount, rD.paymentReference, rD.feeAmount, feeAddress ); } return batchFeeAmountUSD; } /** * @notice Send a batch of ERC20 payments with fees and paymentReferences to multiple accounts, with multiple tokens. * @param requestDetails List of ERC20 requests to pay. * @param pathsToUSD The list of paths into USD for every token, used to limit the batch fees. * Without paths, there is not a fee limitation, and it consumes less gas. * @param batchFeeAmountUSD The batch fee amount in USD already paid. * @param feeAddress The fee recipient. * @dev It uses ERC20FeeProxy to pay an invoice and fees, with a payment reference. * Make sure this contract has enough allowance to spend the payer's token. * Make sure the payer has enough tokens to pay the amount, the fee, and the batch fee. */ function _batchMultiERC20Payments( RequestDetail[] calldata requestDetails, address[][] calldata pathsToUSD, uint256 batchFeeAmountUSD, address feeAddress ) internal returns (uint256) { Token[] memory uTokens = getUTokens(requestDetails); // The payer transfers tokens to the batch contract and pays batch fee for (uint256 i = 0; i < uTokens.length && uTokens[i].amountAndFee > 0; i++) { uTokens[i].batchFeeAmount = (uTokens[i].batchFeeAmount * batchFee) / feeDenominator; IERC20 requestedToken = IERC20(uTokens[i].tokenAddress); transferToContract( requestedToken, uTokens[i].amountAndFee, uTokens[i].batchFeeAmount, address(paymentErc20Proxy) ); // Payer pays batch fee amount uint256 batchFeeToPay = uTokens[i].batchFeeAmount; (batchFeeToPay, batchFeeAmountUSD) = calculateBatchFeeToPay( batchFeeToPay, uTokens[i].tokenAddress, batchFeeAmountUSD, pathsToUSD ); require( safeTransferFrom(uTokens[i].tokenAddress, feeAddress, batchFeeToPay), 'Batch fee transferFrom() failed' ); } // Batch contract pays the requests using Erc20FeeProxy for (uint256 i = 0; i < requestDetails.length; i++) { RequestDetail calldata rD = requestDetails[i]; paymentErc20Proxy.transferFromWithReferenceAndFee( rD.path[0], rD.recipient, rD.requestAmount, rD.paymentReference, rD.feeAmount, feeAddress ); } return batchFeeAmountUSD; } /* * Helper functions */ /** * Top up the contract with enough `requestedToken` to pay `amountAndFee`. * The contract is NOT topped-up for `batchFeeAmount`. * * It also performs a few checks: * - checks that the batch contract has enough allowance from the payer * - checks that the payer has enough funds, including batch fees * - increases the allowance of the contract to use the payment proxy if needed * * @param requestedToken The token to pay * @param amountAndFee The amount and the fee for a token to pay * @param batchFeeAmount The batch fee amount for a token to pay * @param paymentProxyAddress The payment proxy address used to pay */ function transferToContract( IERC20 requestedToken, uint256 amountAndFee, uint256 batchFeeAmount, address paymentProxyAddress ) internal { // Check proxy's allowance from user require( requestedToken.allowance(msg.sender, address(this)) >= amountAndFee, 'Insufficient allowance for batch to pay' ); // Check user's funds to pay amounts, it is an approximation for conversion payment require( requestedToken.balanceOf(msg.sender) >= amountAndFee + batchFeeAmount, 'Not enough funds, including fees' ); // Transfer the amount and fees (no batch fees) required for the token on the batch contract require( safeTransferFrom(address(requestedToken), address(this), amountAndFee), 'payment transferFrom() failed' ); // Batch contract approves Erc20ConversionProxy to spend the token if (requestedToken.allowance(address(this), paymentProxyAddress) < amountAndFee) { approvePaymentProxyToSpend(address(requestedToken), paymentProxyAddress); } } /** * It create a list of unique tokens used and the amounts associated. * It only considers tokens having: requestAmount + feeAmount > 0. * Regarding ERC20 no conversion payments: * batchFeeAmount is the sum of requestAmount and feeAmount. * Out of the function, batch fee rate is applied * @param requestDetails List of requests to pay. */ function getUTokens(RequestDetail[] calldata requestDetails) internal pure returns (Token[] memory uTokens) { // A list of unique tokens, with the sum of maxToSpend by token uTokens = new Token[](requestDetails.length); for (uint256 i = 0; i < requestDetails.length; i++) { for (uint256 k = 0; k < requestDetails.length; k++) { RequestDetail calldata rD = requestDetails[i]; // If the token is already in the existing uTokens list if (uTokens[k].tokenAddress == rD.path[rD.path.length - 1]) { if (rD.path.length > 1) { uTokens[k].amountAndFee += rD.maxToSpend; } else { // It is not a conversion payment uTokens[k].amountAndFee += rD.requestAmount + rD.feeAmount; uTokens[k].batchFeeAmount += rD.requestAmount; } break; } // If the token is not in the list (amountAndFee = 0) else if ( uTokens[k].amountAndFee == 0 && (rD.maxToSpend > 0 || rD.requestAmount + rD.feeAmount > 0) ) { uTokens[k].tokenAddress = rD.path[rD.path.length - 1]; if (rD.path.length > 1) { // amountAndFee is used to store _maxToSpend, useful to send enough tokens to this contract uTokens[k].amountAndFee = rD.maxToSpend; } else { // It is not a conversion payment uTokens[k].amountAndFee = rD.requestAmount + rD.feeAmount; uTokens[k].batchFeeAmount = rD.requestAmount; } break; } } } } /** * Calculate the batch fee amount to pay, using the USD fee limitation. * Without pathsToUSD or a wrong one, the fee limitation is not applied. * @param batchFeeToPay The amount of batch fee to pay * @param tokenAddress The address of the token * @param batchFeeAmountUSD The batch fee amount in USD already paid. * @param pathsToUSD The list of paths into USD for every token, used to limit the batch fees. * Without paths, there is not a fee limitation, and it consumes less gas. */ function calculateBatchFeeToPay( uint256 batchFeeToPay, address tokenAddress, uint256 batchFeeAmountUSD, address[][] memory pathsToUSD ) internal view returns (uint256, uint256) { // Fees are not limited if there is no pathsToUSD // Excepted if batchFeeAmountUSD is already >= batchFeeAmountUSDLimit if (pathsToUSD.length == 0 && batchFeeAmountUSD < batchFeeAmountUSDLimit) { return (batchFeeToPay, batchFeeAmountUSD); } // Apply the fee limit and calculate if needed batchFeeToPay if (batchFeeAmountUSD < batchFeeAmountUSDLimit) { for (uint256 i = 0; i < pathsToUSD.length; i++) { // Check if the pathToUSD is right if ( pathsToUSD[i][0] == tokenAddress && pathsToUSD[i][pathsToUSD[i].length - 1] == USDAddress ) { (uint256 conversionUSD, ) = chainlinkConversionPath.getConversion( batchFeeToPay, pathsToUSD[i] ); // Calculate the batch fee to pay, taking care of the batchFeeAmountUSDLimit uint256 conversionToPayUSD = conversionUSD; if (batchFeeAmountUSD + conversionToPayUSD > batchFeeAmountUSDLimit) { conversionToPayUSD = batchFeeAmountUSDLimit - batchFeeAmountUSD; batchFeeToPay = (batchFeeToPay * conversionToPayUSD) / conversionUSD; } batchFeeAmountUSD += conversionToPayUSD; // Add only once the fees break; } } } else { batchFeeToPay = 0; } return (batchFeeToPay, batchFeeAmountUSD); } /** * @notice Authorizes the proxy to spend a new request currency (ERC20). * @param _erc20Address Address of an ERC20 used as the request currency. * @param _paymentErc20Proxy Address of the proxy. */ function approvePaymentProxyToSpend(address _erc20Address, address _paymentErc20Proxy) internal { IERC20 erc20 = IERC20(_erc20Address); uint256 max = 2**256 - 1; erc20.safeApprove(address(_paymentErc20Proxy), max); } /** * @notice Call transferFrom ERC20 function and validates the return data of a ERC20 contract call. * @dev This is necessary because of non-standard ERC20 tokens that don't have a return value. * @return result The return value of the ERC20 call, returning true for non-standard tokens */ function safeTransferFrom( address _tokenAddress, address _to, uint256 _amount ) internal returns (bool result) { /* solium-disable security/no-inline-assembly */ // check if the address is a contract assembly { if iszero(extcodesize(_tokenAddress)) { revert(0, 0) } } // solium-disable-next-line security/no-low-level-calls (bool success, ) = _tokenAddress.call( abi.encodeWithSignature('transferFrom(address,address,uint256)', msg.sender, _to, _amount) ); assembly { switch returndatasize() case 0 { // Not a standard erc20 result := 1 } case 32 { // Standard erc20 returndatacopy(0, 0, 32) result := mload(0) } default { // Anything else, should revert for safety revert(0, 0) } } require(success, 'transferFrom() has been reverted'); /* solium-enable security/no-inline-assembly */ return result; } /* * Admin functions to edit the proxies address and fees */ /** * @notice Fees added when using Erc20/Native batch functions * @param _batchFee Between 0 and 200, i.e: batchFee = 30 represent 0.30% of fee */ function setBatchFee(uint16 _batchFee) external onlyOwner { // safety to avoid wrong setting require(_batchFee <= 200, 'The batch fee value is too high: > 2%'); batchFee = _batchFee; } /** * @param _paymentErc20Proxy The address to the Erc20 fee payment proxy to use. */ function setPaymentErc20Proxy(address _paymentErc20Proxy) external onlyOwner { paymentErc20Proxy = IERC20FeeProxy(_paymentErc20Proxy); } /** * @param _paymentNativeProxy The address to the Native fee payment proxy to use. */ function setPaymentNativeProxy(address _paymentNativeProxy) external onlyOwner { paymentNativeProxy = IEthereumFeeProxy(_paymentNativeProxy); } /** * @notice Update the conversion path contract used to fetch conversions. * @param _chainlinkConversionPath The address of the conversion path contract. */ function setChainlinkConversionPath(address _chainlinkConversionPath) external onlyOwner { chainlinkConversionPath = ChainlinkConversionPath(_chainlinkConversionPath); } /** * This function define variables allowing to limit the fees: * NativeAddress, USDAddress, and pathsNativeToUSD. * @param _NativeAddress The address representing the Native currency. * @param _USDAddress The address representing the USD currency. */ function setNativeAndUSDAddress(address _NativeAddress, address _USDAddress) external onlyOwner { NativeAddress = _NativeAddress; USDAddress = _USDAddress; pathsNativeToUSD = [[NativeAddress, USDAddress]]; } /** * @param _batchFeeAmountUSDLimit The limitation of the batch fee amount in USD, e.g: * batchFeeAmountUSDLimit = 150 * 1e8 represents $150 */ function setBatchFeeAmountUSDLimit(uint64 _batchFeeAmountUSDLimit) external onlyOwner { batchFeeAmountUSDLimit = _batchFeeAmountUSDLimit; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import '@openzeppelin/contracts/token/ERC20/ERC20.sol'; /** * @title SafeERC20 * @notice Works around implementations of ERC20 with transferFrom not returning success status. */ library SafeERC20 { /** * @notice Call transferFrom ERC20 function and validates the return data of a ERC20 contract call. * @dev This is necessary because of non-standard ERC20 tokens that don't have a return value. * @return result The return value of the ERC20 call, returning true for non-standard tokens */ function safeTransferFrom( IERC20 _token, address _from, address _to, uint256 _amount ) internal returns (bool result) { // solium-disable-next-line security/no-low-level-calls (bool success, bytes memory data) = address(_token).call( abi.encodeWithSignature('transferFrom(address,address,uint256)', _from, _to, _amount) ); return success && (data.length == 0 || abi.decode(data, (bool))); } /** * @notice Call approve ERC20 function and validates the return data of a ERC20 contract call. * @dev This is necessary because of non-standard ERC20 tokens that don't have a return value. * @return result The return value of the ERC20 call, returning true for non-standard tokens */ function safeApprove( IERC20 _token, address _spender, uint256 _amount ) internal returns (bool result) { // solium-disable-next-line security/no-low-level-calls (bool success, bytes memory data) = address(_token).call( abi.encodeWithSignature('approve(address,uint256)', _spender, _amount) ); return success && (data.length == 0 || abi.decode(data, (bool))); } /** * @notice Call transfer ERC20 function and validates the return data of a ERC20 contract call. * @dev This is necessary because of non-standard ERC20 tokens that don't have a return value. * @return result The return value of the ERC20 call, returning true for non-standard tokens */ function safeTransfer( IERC20 _token, address _to, uint256 _amount ) internal returns (bool result) { // solium-disable-next-line security/no-low-level-calls (bool success, bytes memory data) = address(_token).call( abi.encodeWithSignature('transfer(address,uint256)', _to, _amount) ); return success && (data.length == 0 || abi.decode(data, (bool))); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IERC20FeeProxy { event TransferWithReferenceAndFee( address tokenAddress, address to, uint256 amount, bytes indexed paymentReference, uint256 feeAmount, address feeAddress ); function transferFromWithReferenceAndFee( address _tokenAddress, address _to, uint256 _amount, bytes calldata _paymentReference, uint256 _feeAmount, address _feeAddress ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IEthereumFeeProxy { event TransferWithReferenceAndFee( address to, uint256 amount, bytes indexed paymentReference, uint256 feeAmount, address feeAddress ); function transferWithReferenceAndFee( address payable _to, bytes calldata _paymentReference, uint256 _feeAmount, address payable _feeAddress ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import './legacy_openzeppelin/contracts/access/roles/WhitelistAdminRole.sol'; interface ERC20fraction { function decimals() external view returns (uint8); } interface AggregatorFraction { function decimals() external view returns (uint8); function latestAnswer() external view returns (int256); function latestTimestamp() external view returns (uint256); } /** * @title ChainlinkConversionPath * * @notice ChainlinkConversionPath is a contract computing currency conversion rates based on Chainlink aggretators */ contract ChainlinkConversionPath is WhitelistAdminRole { uint256 constant PRECISION = 1e18; uint256 constant NATIVE_TOKEN_DECIMALS = 18; uint256 constant FIAT_DECIMALS = 8; address public nativeTokenHash; /** * @param _nativeTokenHash hash of the native token */ constructor(address _nativeTokenHash) { nativeTokenHash = _nativeTokenHash; } // Mapping of Chainlink aggregators (input currency => output currency => contract address) // input & output currencies are the addresses of the ERC20 contracts OR the sha3("currency code") mapping(address => mapping(address => address)) public allAggregators; // declare a new aggregator event AggregatorUpdated(address _input, address _output, address _aggregator); /** * @notice Update an aggregator * @param _input address representing the input currency * @param _output address representing the output currency * @param _aggregator address of the aggregator contract */ function updateAggregator( address _input, address _output, address _aggregator ) external onlyWhitelistAdmin { allAggregators[_input][_output] = _aggregator; emit AggregatorUpdated(_input, _output, _aggregator); } /** * @notice Update a list of aggregators * @param _inputs list of addresses representing the input currencies * @param _outputs list of addresses representing the output currencies * @param _aggregators list of addresses of the aggregator contracts */ function updateAggregatorsList( address[] calldata _inputs, address[] calldata _outputs, address[] calldata _aggregators ) external onlyWhitelistAdmin { require(_inputs.length == _outputs.length, 'arrays must have the same length'); require(_inputs.length == _aggregators.length, 'arrays must have the same length'); // For every conversions of the path for (uint256 i; i < _inputs.length; i++) { allAggregators[_inputs[i]][_outputs[i]] = _aggregators[i]; emit AggregatorUpdated(_inputs[i], _outputs[i], _aggregators[i]); } } /** * @notice Computes the conversion of an amount through a list of intermediate conversions * @param _amountIn Amount to convert * @param _path List of addresses representing the currencies for the intermediate conversions * @return result The result after all the conversions * @return oldestRateTimestamp The oldest timestamp of the path */ function getConversion(uint256 _amountIn, address[] calldata _path) external view returns (uint256 result, uint256 oldestRateTimestamp) { (uint256 rate, uint256 timestamp, uint256 decimals) = getRate(_path); // initialize the result result = (_amountIn * rate) / decimals; oldestRateTimestamp = timestamp; } /** * @notice Computes the conversion rate from a list of currencies * @param _path List of addresses representing the currencies for the conversions * @return rate The rate * @return oldestRateTimestamp The oldest timestamp of the path * @return decimals of the conversion rate */ function getRate(address[] memory _path) public view returns ( uint256 rate, uint256 oldestRateTimestamp, uint256 decimals ) { // initialize the result with 18 decimals (for more precision) rate = PRECISION; decimals = PRECISION; oldestRateTimestamp = block.timestamp; // For every conversion of the path for (uint256 i; i < _path.length - 1; i++) { ( AggregatorFraction aggregator, bool reverseAggregator, uint256 decimalsInput, uint256 decimalsOutput ) = getAggregatorAndDecimals(_path[i], _path[i + 1]); // store the latest timestamp of the path uint256 currentTimestamp = aggregator.latestTimestamp(); if (currentTimestamp < oldestRateTimestamp) { oldestRateTimestamp = currentTimestamp; } // get the rate of the current step uint256 currentRate = uint256(aggregator.latestAnswer()); // get the number of decimals of the current rate uint256 decimalsAggregator = uint256(aggregator.decimals()); // mul with the difference of decimals before the current rate computation (for more precision) if (decimalsAggregator > decimalsInput) { rate = rate * (10**(decimalsAggregator - decimalsInput)); } if (decimalsAggregator < decimalsOutput) { rate = rate * (10**(decimalsOutput - decimalsAggregator)); } // Apply the current rate (if path uses an aggregator in the reverse way, div instead of mul) if (reverseAggregator) { rate = (rate * (10**decimalsAggregator)) / currentRate; } else { rate = (rate * currentRate) / (10**decimalsAggregator); } // div with the difference of decimals AFTER the current rate computation (for more precision) if (decimalsAggregator < decimalsInput) { rate = rate / (10**(decimalsInput - decimalsAggregator)); } if (decimalsAggregator > decimalsOutput) { rate = rate / (10**(decimalsAggregator - decimalsOutput)); } } } /** * @notice Gets aggregators and decimals of two currencies * @param _input input Address * @param _output output Address * @return aggregator to get the rate between the two currencies * @return reverseAggregator true if the aggregator returned give the rate from _output to _input * @return decimalsInput decimals of _input * @return decimalsOutput decimals of _output */ function getAggregatorAndDecimals(address _input, address _output) private view returns ( AggregatorFraction aggregator, bool reverseAggregator, uint256 decimalsInput, uint256 decimalsOutput ) { // Try to get the right aggregator for the conversion aggregator = AggregatorFraction(allAggregators[_input][_output]); reverseAggregator = false; // if no aggregator found we try to find an aggregator in the reverse way if (address(aggregator) == address(0x00)) { aggregator = AggregatorFraction(allAggregators[_output][_input]); reverseAggregator = true; } require(address(aggregator) != address(0x00), 'No aggregator found'); // get the decimals for the two currencies decimalsInput = getDecimals(_input); decimalsOutput = getDecimals(_output); } /** * @notice Gets decimals from an address currency * @param _addr address to check * @return decimals number of decimals */ function getDecimals(address _addr) private view returns (uint256 decimals) { // by default we assume it is fiat decimals = FIAT_DECIMALS; // if address is the hash of the ETH currency if (_addr == nativeTokenHash) { decimals = NATIVE_TOKEN_DECIMALS; } else if (isContract(_addr)) { // otherwise, we get the decimals from the erc20 directly decimals = ERC20fraction(_addr).decimals(); } } /** * @notice Checks if an address is a contract * @param _addr Address to check * @return true if the address hosts a contract, false otherwise */ function isContract(address _addr) private view returns (bool) { uint32 size; // solium-disable security/no-inline-assembly assembly { size := extcodesize(_addr) } return (size > 0); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The default value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless this function is * overridden; * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); unchecked { _approve(sender, _msgSender(), currentAllowance - amount); } return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { uint256 currentAllowance = _allowances[_msgSender()][spender]; require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(_msgSender(), spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `sender` to `recipient`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[sender] = senderBalance - amount; } _balances[recipient] += amount; emit Transfer(sender, recipient, amount); _afterTokenTransfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; _balances[account] += amount; emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; } _totalSupply -= amount; emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import '@openzeppelin/contracts/utils/Context.sol'; import '../Roles.sol'; /** * @title WhitelistAdminRole * @dev WhitelistAdmins are responsible for assigning and removing Whitelisted accounts. */ abstract contract WhitelistAdminRole is Context { using Roles for Roles.Role; event WhitelistAdminAdded(address indexed account); event WhitelistAdminRemoved(address indexed account); Roles.Role private _whitelistAdmins; constructor() { _addWhitelistAdmin(_msgSender()); } modifier onlyWhitelistAdmin() { require( isWhitelistAdmin(_msgSender()), 'WhitelistAdminRole: caller does not have the WhitelistAdmin role' ); _; } function isWhitelistAdmin(address account) public view returns (bool) { return _whitelistAdmins.has(account); } function addWhitelistAdmin(address account) public onlyWhitelistAdmin { _addWhitelistAdmin(account); } function renounceWhitelistAdmin() public { _removeWhitelistAdmin(_msgSender()); } function _addWhitelistAdmin(address account) internal { _whitelistAdmins.add(account); emit WhitelistAdminAdded(account); } function _removeWhitelistAdmin(address account) internal { _whitelistAdmins.remove(account); emit WhitelistAdminRemoved(account); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title Roles * @dev Library for managing addresses assigned to a Role. */ library Roles { struct Role { mapping(address => bool) bearer; } /** * @dev Give an account access to this role. */ function add(Role storage role, address account) internal { require(!has(role, account), 'Roles: account already has role'); role.bearer[account] = true; } /** * @dev Remove an account's access to this role. */ function remove(Role storage role, address account) internal { require(has(role, account), 'Roles: account does not have role'); role.bearer[account] = false; } /** * @dev Check if an account has this role. * @return bool */ function has(Role storage role, address account) internal view returns (bool) { require(account != address(0), 'Roles: account is the zero address'); return role.bearer[account]; } }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_paymentErc20Proxy","type":"address"},{"internalType":"address","name":"_paymentNativeProxy","type":"address"},{"internalType":"address","name":"_paymentErc20ConversionProxy","type":"address"},{"internalType":"address","name":"_paymentNativeConversionFeeProxy","type":"address"},{"internalType":"address","name":"_chainlinkConversionPath","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"NativeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"requestAmount","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"bytes","name":"paymentReference","type":"bytes"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint256","name":"maxToSpend","type":"uint256"},{"internalType":"uint256","name":"maxRateTimespan","type":"uint256"}],"internalType":"struct BatchNoConversionPayments.RequestDetail[]","name":"requestDetails","type":"tuple[]"},{"internalType":"address[][]","name":"pathsToUSD","type":"address[][]"},{"internalType":"address","name":"feeAddress","type":"address"}],"name":"batchERC20Payments","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"batchFee","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"batchFeeAmountUSDLimit","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"requestAmount","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"bytes","name":"paymentReference","type":"bytes"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint256","name":"maxToSpend","type":"uint256"},{"internalType":"uint256","name":"maxRateTimespan","type":"uint256"}],"internalType":"struct BatchNoConversionPayments.RequestDetail[]","name":"requestDetails","type":"tuple[]"},{"internalType":"address[][]","name":"pathsToUSD","type":"address[][]"},{"internalType":"address","name":"feeAddress","type":"address"}],"name":"batchMultiERC20ConversionPayments","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"requestAmount","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"bytes","name":"paymentReference","type":"bytes"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint256","name":"maxToSpend","type":"uint256"},{"internalType":"uint256","name":"maxRateTimespan","type":"uint256"}],"internalType":"struct BatchNoConversionPayments.RequestDetail[]","name":"requestDetails","type":"tuple[]"},{"internalType":"address[][]","name":"pathsToUSD","type":"address[][]"},{"internalType":"address","name":"feeAddress","type":"address"}],"name":"batchMultiERC20Payments","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"requestAmount","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"bytes","name":"paymentReference","type":"bytes"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint256","name":"maxToSpend","type":"uint256"},{"internalType":"uint256","name":"maxRateTimespan","type":"uint256"}],"internalType":"struct BatchNoConversionPayments.RequestDetail[]","name":"requestDetails","type":"tuple[]"},{"internalType":"bool","name":"skipFeeUSDLimit","type":"bool"},{"internalType":"address payable","name":"feeAddress","type":"address"}],"name":"batchNativeConversionPayments","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"requestAmount","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"bytes","name":"paymentReference","type":"bytes"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint256","name":"maxToSpend","type":"uint256"},{"internalType":"uint256","name":"maxRateTimespan","type":"uint256"}],"internalType":"struct BatchNoConversionPayments.RequestDetail[]","name":"requestDetails","type":"tuple[]"},{"internalType":"bool","name":"skipFeeUSDLimit","type":"bool"},{"internalType":"address payable","name":"feeAddress","type":"address"}],"name":"batchNativePayments","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"paymentNetworkId","type":"uint256"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"requestAmount","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"bytes","name":"paymentReference","type":"bytes"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint256","name":"maxToSpend","type":"uint256"},{"internalType":"uint256","name":"maxRateTimespan","type":"uint256"}],"internalType":"struct BatchNoConversionPayments.RequestDetail[]","name":"requestDetails","type":"tuple[]"}],"internalType":"struct BatchConversionPayments.MetaDetail[]","name":"metaDetails","type":"tuple[]"},{"internalType":"address[][]","name":"pathsToUSD","type":"address[][]"},{"internalType":"address","name":"feeAddress","type":"address"}],"name":"batchPayments","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"chainlinkConversionPath","outputs":[{"internalType":"contract ChainlinkConversionPath","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"pathsNativeToUSD","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paymentErc20ConversionProxy","outputs":[{"internalType":"contract IERC20ConversionProxy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paymentErc20Proxy","outputs":[{"internalType":"contract IERC20FeeProxy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paymentNativeConversionProxy","outputs":[{"internalType":"contract IEthConversionProxy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paymentNativeProxy","outputs":[{"internalType":"contract IEthereumFeeProxy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_batchFee","type":"uint16"}],"name":"setBatchFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_batchFeeAmountUSDLimit","type":"uint64"}],"name":"setBatchFeeAmountUSDLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_chainlinkConversionPath","type":"address"}],"name":"setChainlinkConversionPath","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_NativeAddress","type":"address"},{"internalType":"address","name":"_USDAddress","type":"address"}],"name":"setNativeAndUSDAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_paymentErc20ConversionProxy","type":"address"}],"name":"setPaymentErc20ConversionProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_paymentErc20Proxy","type":"address"}],"name":"setPaymentErc20Proxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_paymentNativeConversionProxy","type":"address"}],"name":"setPaymentNativeConversionProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_paymentNativeProxy","type":"address"}],"name":"setPaymentNativeProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6080604052612710600360166101000a81548161ffff021916908361ffff1602179055506001600460006101000a81548160ff0219169083151502179055506000600860146101000a81548160ff0219169083151502179055503480156200006657600080fd5b5060405162005a2e38038062005a2e83398181016040528101906200008c9190620004a9565b85858383620000b0620000a46200023460201b60201c565b6200023c60201b60201c565b83600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062000184816200030060201b60201c565b6000600360146101000a81548161ffff021916908361ffff1602179055505050505083600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050505062000660565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b620003106200023460201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620003366200041660201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16146200038f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200038690620005a6565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141562000402576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003f9906200063e565b60405180910390fd5b62000413816200023c60201b60201c565b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620004718262000444565b9050919050565b620004838162000464565b81146200048f57600080fd5b50565b600081519050620004a38162000478565b92915050565b60008060008060008060c08789031215620004c957620004c86200043f565b5b6000620004d989828a0162000492565b9650506020620004ec89828a0162000492565b9550506040620004ff89828a0162000492565b94505060606200051289828a0162000492565b93505060806200052589828a0162000492565b92505060a06200053889828a0162000492565b9150509295509295509295565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006200058e60208362000545565b91506200059b8262000556565b602082019050919050565b60006020820190508181036000830152620005c1816200057f565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006200062660268362000545565b91506200063382620005c8565b604082019050919050565b60006020820190508181036000830152620006598162000617565b9050919050565b6153be80620006706000396000f3fe6080604052600436106101a05760003560e01c80638da2f6d8116100ec578063b677bf0e1161008a578063e695f75c11610064578063e695f75c14610606578063f2fde38b1461062f578063f4d0841214610658578063f8b823e41461068157610201565b8063b677bf0e14610575578063dae3d6bb146105b2578063df6557ec146105dd57610201565b8063946647f1116100c6578063946647f1146104a557806397aa096e146104d05780639af8a581146104fb578063a4b519ff1461053857610201565b80638da2f6d8146104355780638da5cb5b1461045e57806392cddb911461048957610201565b80633085df631161015957806360be74e61161013357806360be74e6146103a1578063715018a6146103cc5780637abff543146103e357806381fe66ce1461040c57610201565b80633085df631461030b578063333ec062146103485780634465549a1461037857610201565b80630917377f146102065780630a9157c4146102315780630e48b8db1461025c57806316ac30a91461028c5780632e2f0ca0146102b55780632fae95bf146102e057610201565b3661020157600860149054906101000a900460ff16806101c05750600034145b6101ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101f690613a00565b60405180910390fd5b005b600080fd5b34801561021257600080fd5b5061021b6106ac565b6040516102289190613a61565b60405180910390f35b34801561023d57600080fd5b506102466106d2565b6040516102539190613adb565b60405180910390f35b61027660048036038101906102719190613be5565b6106f8565b6040516102839190613c72565b60405180910390f35b34801561029857600080fd5b506102b360048036038101906102ae9190613ccd565b610712565b005b3480156102c157600080fd5b506102ca6107ba565b6040516102d79190613d1b565b60405180910390f35b3480156102ec57600080fd5b506102f56107e0565b6040516103029190613d45565b60405180910390f35b34801561031757600080fd5b50610332600480360381019061032d9190613d8c565b6107fa565b60405161033f9190613a61565b60405180910390f35b610362600480360381019061035d9190613be5565b610854565b60405161036f9190613c72565b60405180910390f35b34801561038457600080fd5b5061039f600480360381019061039a9190613df8565b61086e565b005b3480156103ad57600080fd5b506103b661092e565b6040516103c39190613e46565b60405180910390f35b3480156103d857600080fd5b506103e1610954565b005b3480156103ef57600080fd5b5061040a60048036038101906104059190613df8565b6109dc565b005b34801561041857600080fd5b50610433600480360381019061042e9190613df8565b610a9c565b005b34801561044157600080fd5b5061045c60048036038101906104579190613df8565b610b5c565b005b34801561046a57600080fd5b50610473610c1c565b6040516104809190613a61565b60405180910390f35b6104a3600480360381019061049e9190613f0d565b610c45565b005b3480156104b157600080fd5b506104ba610f07565b6040516104c79190613fc3565b60405180910390f35b3480156104dc57600080fd5b506104e5610f2d565b6040516104f29190613a61565b60405180910390f35b34801561050757600080fd5b50610522600480360381019061051d9190613fde565b610f53565b60405161052f9190613c72565b60405180910390f35b34801561054457600080fd5b5061055f600480360381019061055a9190613fde565b610f6f565b60405161056c9190613c72565b60405180910390f35b34801561058157600080fd5b5061059c60048036038101906105979190613fde565b610f8b565b6040516105a99190613c72565b60405180910390f35b3480156105be57600080fd5b506105c7610fa7565b6040516105d49190614094565b60405180910390f35b3480156105e957600080fd5b5061060460048036038101906105ff91906140af565b610fcd565b005b34801561061257600080fd5b5061062d60048036038101906106289190613df8565b61119f565b005b34801561063b57600080fd5b5061065660048036038101906106519190613df8565b61125f565b005b34801561066457600080fd5b5061067f600480360381019061067a9190614129565b611357565b005b34801561068d57600080fd5b5061069661143b565b6040516106a39190614165565b60405180910390f35b600460019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061070885858560008661144f565b9050949350505050565b61071a61188c565b73ffffffffffffffffffffffffffffffffffffffff16610738610c1c565b73ffffffffffffffffffffffffffffffffffffffff161461078e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610785906141cc565b60405180910390fd5b80600360186101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600360189054906101000a900467ffffffffffffffff1681565b6006828154811061080a57600080fd5b90600052602060002001818154811061082257600080fd5b906000526020600020016000915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000610864858585600086611894565b9050949350505050565b61087661188c565b73ffffffffffffffffffffffffffffffffffffffff16610894610c1c565b73ffffffffffffffffffffffffffffffffffffffff16146108ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906141cc565b60405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61095c61188c565b73ffffffffffffffffffffffffffffffffffffffff1661097a610c1c565b73ffffffffffffffffffffffffffffffffffffffff16146109d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109c7906141cc565b60405180910390fd5b6109da6000611d0d565b565b6109e461188c565b73ffffffffffffffffffffffffffffffffffffffff16610a02610c1c565b73ffffffffffffffffffffffffffffffffffffffff1614610a58576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a4f906141cc565b60405180910390fd5b80600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b610aa461188c565b73ffffffffffffffffffffffffffffffffffffffff16610ac2610c1c565b73ffffffffffffffffffffffffffffffffffffffff1614610b18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0f906141cc565b60405180910390fd5b80600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b610b6461188c565b73ffffffffffffffffffffffffffffffffffffffff16610b82610c1c565b73ffffffffffffffffffffffffffffffffffffffff1614610bd8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bcf906141cc565b60405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60068585905010610c8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8290614238565b60405180910390fd5b6000805b86869050811015610efe5736878783818110610cae57610cad614258565b5b9050602002810190610cc09190614296565b9050600081600001351415610cfd57610ceb818060200190610ce291906142be565b85898989611dd1565b83610cf69190614350565b9250610eea565b600181600001351415610d3857610d26818060200190610d1d91906142be565b888887896122b3565b83610d319190614350565b9250610ee9565b600281600001351415610d7357610d61818060200190610d5891906142be565b888887896126bd565b83610d6c9190614350565b9250610ee8565b600381600001351415610e6b576004888860018b8b9050610d9491906143a6565b818110610da457610da3614258565b5b9050602002810190610db69190614296565b600001351415610ddc576000600460006101000a81548160ff0219169083151502179055505b610dfd818060200190610def91906142be565b600089899050148688611894565b83610e089190614350565b92506004888860018b8b9050610e1e91906143a6565b818110610e2e57610e2d614258565b5b9050602002810190610e409190614296565b600001351415610e66576001600460006101000a81548160ff0219169083151502179055505b610ee7565b600481600001351415610eab57610e99818060200190610e8b91906142be565b60008989905014868861144f565b83610ea49190614350565b9250610ee6565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610edd90614426565b60405180910390fd5b5b5b5b5b508080610ef690614446565b915050610c8f565b50505050505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000610f64868686866000876122b3565b905095945050505050565b6000610f80868686866000876126bd565b905095945050505050565b6000610f9c86866000878787611dd1565b905095945050505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610fd561188c565b73ffffffffffffffffffffffffffffffffffffffff16610ff3610c1c565b73ffffffffffffffffffffffffffffffffffffffff1614611049576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611040906141cc565b60405180910390fd5b81600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600460016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180602001604052806040518060400160405280600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600460019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250815250600690600161119a929190613825565b505050565b6111a761188c565b73ffffffffffffffffffffffffffffffffffffffff166111c5610c1c565b73ffffffffffffffffffffffffffffffffffffffff161461121b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611212906141cc565b60405180910390fd5b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61126761188c565b73ffffffffffffffffffffffffffffffffffffffff16611285610c1c565b73ffffffffffffffffffffffffffffffffffffffff16146112db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112d2906141cc565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561134b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161134290614501565b60405180910390fd5b61135481611d0d565b50565b61135f61188c565b73ffffffffffffffffffffffffffffffffffffffff1661137d610c1c565b73ffffffffffffffffffffffffffffffffffffffff16146113d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113ca906141cc565b60405180910390fd5b60c88161ffff16111561141b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161141290614593565b60405180910390fd5b80600360146101000a81548161ffff021916908361ffff16021790555050565b600360149054906101000a900461ffff1681565b6000804790506001600860146101000a81548160ff02191690831515021790555060005b87879050811015611592573688888381811061149257611491614258565b5b90506020028101906114a491906145b3565b9050600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ac473c8a478360000160208101906114f89190613df8565b846020013585806040019061150d91906145db565b87806060019061151d919061463e565b89608001358e8b60c001356040518b63ffffffff1660e01b815260040161154c999897969594939291906147e3565b6000604051808303818588803b15801561156557600080fd5b505af1158015611579573d6000803e3d6000fd5b505050505050808061158a90614446565b915050611473565b506000600360169054906101000a900461ffff1661ffff16600360149054906101000a900461ffff1661ffff1647846115cb91906143a6565b6115d59190614864565b6115df91906148ed565b905060001515861515141561172c5761172381600660008154811061160757611606614258565b5b9060005260206000200160008154811061162457611623614258565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16876006805480602002602001604051908101604052809291908181526020016000905b8282101561171a5783829060005260206000200180548060200260200160405190810160405280929190818152602001828054801561170657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116116bc575b505050505081526020019060010190611672565b50505050612a3e565b80965081925050505b8047101561176f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161176690614990565b60405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156117b5573d6000803e3d6000fd5b5060003373ffffffffffffffffffffffffffffffffffffffff16476040516117dc906149e1565b60006040518083038185875af1925050503d8060008114611819576040519150601f19603f3d011682016040523d82523d6000602084013e61181e565b606091505b5050905080611862576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161185990614a68565b60405180910390fd5b6000600860146101000a81548160ff02191690831515021790555085935050505095945050505050565b600033905090565b6000806000905060005b87879050811015611a1a57368888838181106118bd576118bc614258565b5b90506020028101906118cf91906145b3565b9050806080013581602001356118e59190614350565b471015611927576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161191e90614ad4565b60405180910390fd5b8060200135836119379190614350565b9250600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b868980b8260800135836020013561198b9190614350565b83600001602081019061199e9190613df8565b8480606001906119ae919061463e565b86608001358b6040518763ffffffff1660e01b81526004016119d4959493929190614b03565b6000604051808303818588803b1580156119ed57600080fd5b505af1158015611a01573d6000803e3d6000fd5b5050505050508080611a1290614446565b91505061189e565b50600360169054906101000a900461ffff1661ffff16600360149054906101000a900461ffff1661ffff1682611a509190614864565b611a5a91906148ed565b9050600015158515151415611ba757611b9e816006600081548110611a8257611a81614258565b5b90600052602060002001600081548110611a9f57611a9e614258565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16866006805480602002602001604051908101604052809291908181526020016000905b82821015611b9557838290600052602060002001805480602002602001604051908101604052809291908181526020018280548015611b8157602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611b37575b505050505081526020019060010190611aed565b50505050612a3e565b80955081925050505b80471015611bea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be190614b9d565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611c30573d6000803e3d6000fd5b50600460009054906101000a900460ff168015611c4d5750600047115b15611d005760003373ffffffffffffffffffffffffffffffffffffffff1647604051611c78906149e1565b60006040518083038185875af1925050503d8060008114611cb5576040519150601f19603f3d011682016040523d82523d6000602084013e611cba565b606091505b5050905080611cfe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cf590614a68565b60405180910390fd5b505b8391505095945050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080611dde8888612d60565b9050600080600090505b825181108015611e1657506000838281518110611e0857611e07614258565b5b602002602001015160200151115b15611f3957600360169054906101000a900461ffff1661ffff16600360149054906101000a900461ffff1661ffff16848381518110611e5857611e57614258565b5b602002602001015160200151611e6e9190614864565b611e7891906148ed565b838281518110611e8b57611e8a614258565b5b60200260200101516040018181525050828181518110611eae57611ead614258565b5b6020026020010151600001519150611f2682848381518110611ed357611ed2614258565b5b602002602001015160200151858481518110611ef257611ef1614258565b5b602002602001015160400151600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16613152565b8080611f3190614446565b915050611de8565b5060005b8989905081101561206157368a8a83818110611f5c57611f5b614258565b5b9050602002810190611f6e91906145b3565b9050600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633af2c012826000016020810190611fc19190613df8565b8360200135848060400190611fd691906145db565b868060600190611fe6919061463e565b88608001358e8a60a001358b60c001356040518b63ffffffff1660e01b815260040161201b9a99989796959493929190614bbd565b600060405180830381600087803b15801561203557600080fd5b505af1158015612049573d6000803e3d6000fd5b5050505050808061205990614446565b915050611f3d565b5060005b8251811080156120935750600083828151811061208557612084614258565b5b602002602001015160200151115b156122a3578281815181106120ab576120aa614258565b5b602002602001015160000151915060008273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016120f49190613a61565b60206040518083038186803b15801561210c57600080fd5b505afa158015612120573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121449190614c62565b9050600081111561217c5761217a33828573ffffffffffffffffffffffffffffffffffffffff166133e29092919063ffffffff16565b505b6000600360169054906101000a900461ffff1661ffff16600360149054906101000a900461ffff1661ffff16838786815181106121bc576121bb614258565b5b6020026020010151602001516121d291906143a6565b6121dc9190614864565b6121e691906148ed565b905061221e818685815181106121ff576121fe614258565b5b6020026020010151600001518c8c8c906122199190614e80565b612a3e565b809b50819250505061224f85848151811061223c5761223b614258565b5b6020026020010151600001518883613516565b61228e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161228590614ee1565b60405180910390fd5b5050808061229b90614446565b915050612065565b5086925050509695505050505050565b600080600090506000805b8989905081101561237b578989828181106122dc576122db614258565b5b90506020028101906122ee91906145b3565b608001358a8a8381811061230557612304614258565b5b905060200281019061231791906145b3565b602001356123259190614350565b836123309190614350565b925089898281811061234557612344614258565b5b905060200281019061235791906145b3565b60200135826123669190614350565b9150808061237390614446565b9150506122be565b50600360169054906101000a900461ffff1661ffff16600360149054906101000a900461ffff1661ffff16826123b19190614864565b6123bb91906148ed565b9050612430818a8a60008181106123d5576123d4614258565b5b90506020028101906123e791906145b3565b80604001906123f691906145db565b600081811061240857612407614258565b5b905060200201602081019061241d9190613df8565b878a8a9061242b9190614e80565b612a3e565b809650819250505060008989600081811061244e5761244d614258565b5b905060200281019061246091906145b3565b806040019061246f91906145db565b600081811061248157612480614258565b5b90506020020160208101906124969190613df8565b90506124c6818484600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16613152565b61252c8a8a60008181106124dd576124dc614258565b5b90506020028101906124ef91906145b3565b80604001906124fe91906145db565b60008181106125105761250f614258565b5b90506020020160208101906125259190613df8565b8684613516565b61256b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161256290614ee1565b60405180910390fd5b60005b8a8a90508110156126ac57368b8b8381811061258d5761258c614258565b5b905060200281019061259f91906145b3565b9050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c219a14d8280604001906125ef91906145db565b600081811061260157612600614258565b5b90506020020160208101906126169190613df8565b8360000160208101906126299190613df8565b846020013585806060019061263e919061463e565b87608001358e6040518863ffffffff1660e01b81526004016126669796959493929190614f01565b600060405180830381600087803b15801561268057600080fd5b505af1158015612694573d6000803e3d6000fd5b505050505080806126a490614446565b91505061256e565b508593505050509695505050505050565b6000806126ca8888612d60565b905060005b8151811080156126fd575060008282815181106126ef576126ee614258565b5b602002602001015160200151115b156128ed57600360169054906101000a900461ffff1661ffff16600360149054906101000a900461ffff1661ffff1683838151811061273f5761273e614258565b5b6020026020010151604001516127559190614864565b61275f91906148ed565b82828151811061277257612771614258565b5b60200260200101516040018181525050600082828151811061279757612796614258565b5b602002602001015160000151905061280f818484815181106127bc576127bb614258565b5b6020026020010151602001518585815181106127db576127da614258565b5b602002602001015160400151600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16613152565b600083838151811061282457612823614258565b5b60200260200101516040015190506128688185858151811061284957612848614258565b5b602002602001015160000151898c8c906128639190614e80565b612a3e565b809850819250505061289984848151811061288657612885614258565b5b6020026020010151600001518783613516565b6128d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128cf90614ee1565b60405180910390fd5b505080806128e590614446565b9150506126cf565b5060005b88889050811015612a2f57368989838181106129105761290f614258565b5b905060200281019061292291906145b3565b9050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c219a14d82806040019061297291906145db565b600081811061298457612983614258565b5b90506020020160208101906129999190613df8565b8360000160208101906129ac9190613df8565b84602001358580606001906129c1919061463e565b87608001358c6040518863ffffffff1660e01b81526004016129e99796959493929190614f01565b600060405180830381600087803b158015612a0357600080fd5b505af1158015612a17573d6000803e3d6000fd5b50505050508080612a2790614446565b9150506128f1565b50839150509695505050505050565b60008060008351148015612a715750600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff1684105b15612a8157858491509150612d57565b600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff16841015612d4b5760005b8351811015612d45578573ffffffffffffffffffffffffffffffffffffffff16848281518110612adf57612ade614258565b5b6020026020010151600081518110612afa57612af9614258565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16148015612bcd5750600460019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16848281518110612b6c57612b6b614258565b5b60200260200101516001868481518110612b8957612b88614258565b5b602002602001015151612b9c91906143a6565b81518110612bad57612bac614258565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16145b15612d32576000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fbd4122a89878581518110612c2657612c25614258565b5b60200260200101516040518363ffffffff1660e01b8152600401612c4b929190614ff1565b604080518083038186803b158015612c6257600080fd5b505afa158015612c76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c9a9190615021565b5090506000819050600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff168188612ccf9190614350565b1115612d1d5786600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff16612d0191906143a6565b905081818a612d109190614864565b612d1a91906148ed565b98505b8087612d299190614350565b96505050612d45565b8080612d3d90614446565b915050612aac565b50612d50565b600095505b8584915091505b94509492505050565b60608282905067ffffffffffffffff811115612d7f57612d7e614c8f565b5b604051908082528060200260200182016040528015612db857816020015b612da5613880565b815260200190600190039081612d9d5790505b50905060005b8383905081101561314b5760005b848490508110156131375736858584818110612deb57612dea614258565b5b9050602002810190612dfd91906145b3565b9050808060400190612e0f91906145db565b6001838060400190612e2191906145db565b9050612e2d91906143a6565b818110612e3d57612e3c614258565b5b9050602002016020810190612e529190613df8565b73ffffffffffffffffffffffffffffffffffffffff16848381518110612e7b57612e7a614258565b5b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff161415612f7d576001818060400190612eb591906145db565b90501115612ef9578060a00135848381518110612ed557612ed4614258565b5b6020026020010151602001818151612eed9190614350565b91508181525050612f77565b80608001358160200135612f0d9190614350565b848381518110612f2057612f1f614258565b5b6020026020010151602001818151612f389190614350565b915081815250508060200135848381518110612f5757612f56614258565b5b6020026020010151604001818151612f6f9190614350565b915081815250505b50613137565b6000848381518110612f9257612f91614258565b5b602002602001015160200151148015612fcd575060008160a001351180612fcc5750600081608001358260200135612fca9190614350565b115b5b1561312357808060400190612fe291906145db565b6001838060400190612ff491906145db565b905061300091906143a6565b8181106130105761300f614258565b5b90506020020160208101906130259190613df8565b84838151811061303857613037614258565b5b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600181806040019061308891906145db565b905011156130bd578060a001358483815181106130a8576130a7614258565b5b6020026020010151602001818152505061311d565b806080013581602001356130d19190614350565b8483815181106130e4576130e3614258565b5b60200260200101516020018181525050806020013584838151811061310c5761310b614258565b5b602002602001015160400181815250505b50613137565b50808061312f90614446565b915050612dcc565b50808061314390614446565b915050612dbe565b5092915050565b828473ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e33306040518363ffffffff1660e01b815260040161318e929190615061565b60206040518083038186803b1580156131a657600080fd5b505afa1580156131ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131de9190614c62565b101561321f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613216906150fc565b60405180910390fd5b818361322b9190614350565b8473ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b81526004016132649190613a61565b60206040518083038186803b15801561327c57600080fd5b505afa158015613290573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132b49190614c62565b10156132f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132ec90615168565b60405180910390fd5b613300843085613516565b61333f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613336906151d4565b60405180910390fd5b828473ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30846040518363ffffffff1660e01b815260040161337b929190615061565b60206040518083038186803b15801561339357600080fd5b505afa1580156133a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133cb9190614c62565b10156133dc576133db8482613695565b5b50505050565b60008060008573ffffffffffffffffffffffffffffffffffffffff1685856040516024016134119291906151f4565b6040516020818303038152906040527fa9059cbb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161349b919061528c565b6000604051808303816000865af19150503d80600081146134d8576040519150601f19603f3d011682016040523d82523d6000602084013e6134dd565b606091505b509150915081801561350b575060008151148061350a57508080602001905181019061350991906152b8565b5b5b925050509392505050565b6000833b61352357600080fd5b60008473ffffffffffffffffffffffffffffffffffffffff16338585604051602401613551939291906152e5565b6040516020818303038152906040527f23b872dd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516135db919061528c565b6000604051808303816000865af19150503d8060008114613618576040519150601f19603f3d011682016040523d82523d6000602084013e61361d565b606091505b505090503d60008114613637576020811461364057600080fd5b6001925061364c565b60206000803e60005192505b508061368d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161368490615368565b60405180910390fd5b509392505050565b600082905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90506136ea83828473ffffffffffffffffffffffffffffffffffffffff166136f19092919063ffffffff16565b5050505050565b60008060008573ffffffffffffffffffffffffffffffffffffffff1685856040516024016137209291906151f4565b6040516020818303038152906040527f095ea7b3000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516137aa919061528c565b6000604051808303816000865af19150503d80600081146137e7576040519150601f19603f3d011682016040523d82523d6000602084013e6137ec565b606091505b509150915081801561381a575060008151148061381957508080602001905181019061381891906152b8565b5b5b925050509392505050565b82805482825590600052602060002090810192821561386f579160200282015b8281111561386e5782518290600261385e9291906138b7565b5091602001919060010190613845565b5b50905061387c9190613941565b5090565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081525090565b828054828255906000526020600020908101928215613930579160200282015b8281111561392f5782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906138d7565b5b50905061393d9190613965565b5090565b5b8082111561396157600081816139589190613982565b50600101613942565b5090565b5b8082111561397e576000816000905550600101613966565b5090565b50805460008255906000526020600020908101906139a09190613965565b50565b600082825260208201905092915050565b7f4e6f6e2d70617961626c65000000000000000000000000000000000000000000600082015250565b60006139ea600b836139a3565b91506139f5826139b4565b602082019050919050565b60006020820190508181036000830152613a19816139dd565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613a4b82613a20565b9050919050565b613a5b81613a40565b82525050565b6000602082019050613a766000830184613a52565b92915050565b6000819050919050565b6000613aa1613a9c613a9784613a20565b613a7c565b613a20565b9050919050565b6000613ab382613a86565b9050919050565b6000613ac582613aa8565b9050919050565b613ad581613aba565b82525050565b6000602082019050613af06000830184613acc565b92915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f840112613b2f57613b2e613b0a565b5b8235905067ffffffffffffffff811115613b4c57613b4b613b0f565b5b602083019150836020820283011115613b6857613b67613b14565b5b9250929050565b60008115159050919050565b613b8481613b6f565b8114613b8f57600080fd5b50565b600081359050613ba181613b7b565b92915050565b6000613bb282613a20565b9050919050565b613bc281613ba7565b8114613bcd57600080fd5b50565b600081359050613bdf81613bb9565b92915050565b60008060008060608587031215613bff57613bfe613b00565b5b600085013567ffffffffffffffff811115613c1d57613c1c613b05565b5b613c2987828801613b19565b94509450506020613c3c87828801613b92565b9250506040613c4d87828801613bd0565b91505092959194509250565b6000819050919050565b613c6c81613c59565b82525050565b6000602082019050613c876000830184613c63565b92915050565b600067ffffffffffffffff82169050919050565b613caa81613c8d565b8114613cb557600080fd5b50565b600081359050613cc781613ca1565b92915050565b600060208284031215613ce357613ce2613b00565b5b6000613cf184828501613cb8565b91505092915050565b6000613d0582613aa8565b9050919050565b613d1581613cfa565b82525050565b6000602082019050613d306000830184613d0c565b92915050565b613d3f81613c8d565b82525050565b6000602082019050613d5a6000830184613d36565b92915050565b613d6981613c59565b8114613d7457600080fd5b50565b600081359050613d8681613d60565b92915050565b60008060408385031215613da357613da2613b00565b5b6000613db185828601613d77565b9250506020613dc285828601613d77565b9150509250929050565b613dd581613a40565b8114613de057600080fd5b50565b600081359050613df281613dcc565b92915050565b600060208284031215613e0e57613e0d613b00565b5b6000613e1c84828501613de3565b91505092915050565b6000613e3082613aa8565b9050919050565b613e4081613e25565b82525050565b6000602082019050613e5b6000830184613e37565b92915050565b60008083601f840112613e7757613e76613b0a565b5b8235905067ffffffffffffffff811115613e9457613e93613b0f565b5b602083019150836020820283011115613eb057613eaf613b14565b5b9250929050565b60008083601f840112613ecd57613ecc613b0a565b5b8235905067ffffffffffffffff811115613eea57613ee9613b0f565b5b602083019150836020820283011115613f0657613f05613b14565b5b9250929050565b600080600080600060608688031215613f2957613f28613b00565b5b600086013567ffffffffffffffff811115613f4757613f46613b05565b5b613f5388828901613e61565b9550955050602086013567ffffffffffffffff811115613f7657613f75613b05565b5b613f8288828901613eb7565b93509350506040613f9588828901613de3565b9150509295509295909350565b6000613fad82613aa8565b9050919050565b613fbd81613fa2565b82525050565b6000602082019050613fd86000830184613fb4565b92915050565b600080600080600060608688031215613ffa57613ff9613b00565b5b600086013567ffffffffffffffff81111561401857614017613b05565b5b61402488828901613b19565b9550955050602086013567ffffffffffffffff81111561404757614046613b05565b5b61405388828901613eb7565b9350935050604061406688828901613de3565b9150509295509295909350565b600061407e82613aa8565b9050919050565b61408e81614073565b82525050565b60006020820190506140a96000830184614085565b92915050565b600080604083850312156140c6576140c5613b00565b5b60006140d485828601613de3565b92505060206140e585828601613de3565b9150509250929050565b600061ffff82169050919050565b614106816140ef565b811461411157600080fd5b50565b600081359050614123816140fd565b92915050565b60006020828403121561413f5761413e613b00565b5b600061414d84828501614114565b91505092915050565b61415f816140ef565b82525050565b600060208201905061417a6000830184614156565b92915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006141b66020836139a3565b91506141c182614180565b602082019050919050565b600060208201905081810360008301526141e5816141a9565b9050919050565b7f6d6f7265207468616e2035206d65746144657461696c73000000000000000000600082015250565b60006142226017836139a3565b915061422d826141ec565b602082019050919050565b6000602082019050818103600083015261425181614215565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b600080fd5b600080fd5b6000823560016040038336030381126142b2576142b1614287565b5b80830191505092915050565b600080833560016020038436030381126142db576142da614287565b5b80840192508235915067ffffffffffffffff8211156142fd576142fc61428c565b5b60208301925060208202360383131561431957614318614291565b5b509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061435b82613c59565b915061436683613c59565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561439b5761439a614321565b5b828201905092915050565b60006143b182613c59565b91506143bc83613c59565b9250828210156143cf576143ce614321565b5b828203905092915050565b7f57726f6e67207061796d656e744e6574776f726b496400000000000000000000600082015250565b60006144106016836139a3565b915061441b826143da565b602082019050919050565b6000602082019050818103600083015261443f81614403565b9050919050565b600061445182613c59565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561448457614483614321565b5b600182019050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006144eb6026836139a3565b91506144f68261448f565b604082019050919050565b6000602082019050818103600083015261451a816144de565b9050919050565b7f546865206261746368206665652076616c756520697320746f6f20686967683a60008201527f203e203225000000000000000000000000000000000000000000000000000000602082015250565b600061457d6025836139a3565b915061458882614521565b604082019050919050565b600060208201905081810360008301526145ac81614570565b9050919050565b60008235600160e0038336030381126145cf576145ce614287565b5b80830191505092915050565b600080833560016020038436030381126145f8576145f7614287565b5b80840192508235915067ffffffffffffffff82111561461a5761461961428c565b5b60208301925060208202360383131561463657614635614291565b5b509250929050565b6000808335600160200384360303811261465b5761465a614287565b5b80840192508235915067ffffffffffffffff82111561467d5761467c61428c565b5b60208301925060018202360383131561469957614698614291565b5b509250929050565b60006146ac82613aa8565b9050919050565b6146bc816146a1565b82525050565b600082825260208201905092915050565b6000819050919050565b6146e681613a40565b82525050565b60006146f883836146dd565b60208301905092915050565b60006147136020840184613de3565b905092915050565b6000602082019050919050565b600061473483856146c2565b935061473f826146d3565b8060005b85811015614778576147558284614704565b61475f88826146ec565b975061476a8361471b565b925050600181019050614743565b5085925050509392505050565b600082825260208201905092915050565b82818337600083830152505050565b6000601f19601f8301169050919050565b60006147c28385614785565b93506147cf838584614796565b6147d8836147a5565b840190509392505050565b600060e0820190506147f8600083018c6146b3565b614805602083018b613c63565b818103604083015261481881898b614728565b9050818103606083015261482d8187896147b6565b905061483c6080830186613c63565b61484960a08301856146b3565b61485660c0830184613c63565b9a9950505050505050505050565b600061486f82613c59565b915061487a83613c59565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156148b3576148b2614321565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006148f882613c59565b915061490383613c59565b925082614913576149126148be565b5b828204905092915050565b7f4e6f7420656e6f7567682066756e647320666f7220626174636820636f6e766560008201527f7273696f6e206665657300000000000000000000000000000000000000000000602082015250565b600061497a602a836139a3565b91506149858261491e565b604082019050919050565b600060208201905081810360008301526149a98161496d565b9050919050565b600081905092915050565b50565b60006149cb6000836149b0565b91506149d6826149bb565b600082019050919050565b60006149ec826149be565b9150819050919050565b7f436f756c64206e6f742073656e642072656d61696e696e672066756e6473207460008201527f6f20746865207061796572000000000000000000000000000000000000000000602082015250565b6000614a52602b836139a3565b9150614a5d826149f6565b604082019050919050565b60006020820190508181036000830152614a8181614a45565b9050919050565b7f4e6f7420656e6f7567682066756e647300000000000000000000000000000000600082015250565b6000614abe6010836139a3565b9150614ac982614a88565b602082019050919050565b60006020820190508181036000830152614aed81614ab1565b9050919050565b614afd81613ba7565b82525050565b6000608082019050614b186000830188614af4565b8181036020830152614b2b8186886147b6565b9050614b3a6040830185613c63565b614b476060830184614af4565b9695505050505050565b7f4e6f7420656e6f7567682066756e647320666f72206261746368206665650000600082015250565b6000614b87601e836139a3565b9150614b9282614b51565b602082019050919050565b60006020820190508181036000830152614bb681614b7a565b9050919050565b600061010082019050614bd3600083018d613a52565b614be0602083018c613c63565b8181036040830152614bf3818a8c614728565b90508181036060830152614c0881888a6147b6565b9050614c176080830187613c63565b614c2460a0830186613a52565b614c3160c0830185613c63565b614c3e60e0830184613c63565b9b9a5050505050505050505050565b600081519050614c5c81613d60565b92915050565b600060208284031215614c7857614c77613b00565b5b6000614c8684828501614c4d565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614cc7826147a5565b810181811067ffffffffffffffff82111715614ce657614ce5614c8f565b5b80604052505050565b6000614cf9613af6565b9050614d058282614cbe565b919050565b600067ffffffffffffffff821115614d2557614d24614c8f565b5b602082029050602081019050919050565b600067ffffffffffffffff821115614d5157614d50614c8f565b5b602082029050602081019050919050565b6000614d75614d7084614d36565b614cef565b90508083825260208201905060208402830185811115614d9857614d97613b14565b5b835b81811015614dc15780614dad8882613de3565b845260208401935050602081019050614d9a565b5050509392505050565b600082601f830112614de057614ddf613b0a565b5b8135614df0848260208601614d62565b91505092915050565b6000614e0c614e0784614d0a565b614cef565b90508083825260208201905060208402830185811115614e2f57614e2e613b14565b5b835b81811015614e7657803567ffffffffffffffff811115614e5457614e53613b0a565b5b808601614e618982614dcb565b85526020850194505050602081019050614e31565b5050509392505050565b6000614e8d368484614df9565b905092915050565b7f426174636820666565207472616e7366657246726f6d2829206661696c656400600082015250565b6000614ecb601f836139a3565b9150614ed682614e95565b602082019050919050565b60006020820190508181036000830152614efa81614ebe565b9050919050565b600060c082019050614f16600083018a613a52565b614f236020830189613a52565b614f306040830188613c63565b8181036060830152614f438186886147b6565b9050614f526080830185613c63565b614f5f60a0830184613a52565b98975050505050505050565b600081519050919050565b6000819050602082019050919050565b6000602082019050919050565b6000614f9e82614f6b565b614fa881856146c2565b9350614fb383614f76565b8060005b83811015614fe4578151614fcb88826146ec565b9750614fd683614f86565b925050600181019050614fb7565b5085935050505092915050565b60006040820190506150066000830185613c63565b81810360208301526150188184614f93565b90509392505050565b6000806040838503121561503857615037613b00565b5b600061504685828601614c4d565b925050602061505785828601614c4d565b9150509250929050565b60006040820190506150766000830185613a52565b6150836020830184613a52565b9392505050565b7f496e73756666696369656e7420616c6c6f77616e636520666f7220626174636860008201527f20746f2070617900000000000000000000000000000000000000000000000000602082015250565b60006150e66027836139a3565b91506150f18261508a565b604082019050919050565b60006020820190508181036000830152615115816150d9565b9050919050565b7f4e6f7420656e6f7567682066756e64732c20696e636c7564696e672066656573600082015250565b60006151526020836139a3565b915061515d8261511c565b602082019050919050565b6000602082019050818103600083015261518181615145565b9050919050565b7f7061796d656e74207472616e7366657246726f6d2829206661696c6564000000600082015250565b60006151be601d836139a3565b91506151c982615188565b602082019050919050565b600060208201905081810360008301526151ed816151b1565b9050919050565b60006040820190506152096000830185613a52565b6152166020830184613c63565b9392505050565b600081519050919050565b60005b8381101561524657808201518184015260208101905061522b565b83811115615255576000848401525b50505050565b60006152668261521d565b61527081856149b0565b9350615280818560208601615228565b80840191505092915050565b6000615298828461525b565b915081905092915050565b6000815190506152b281613b7b565b92915050565b6000602082840312156152ce576152cd613b00565b5b60006152dc848285016152a3565b91505092915050565b60006060820190506152fa6000830186613a52565b6153076020830185613a52565b6153146040830184613c63565b949350505050565b7f7472616e7366657246726f6d282920686173206265656e207265766572746564600082015250565b60006153526020836139a3565b915061535d8261531c565b602082019050919050565b6000602082019050818103600083015261538181615345565b905091905056fea26469706673582212207a94adaf919c0e13cce412e4c26773542b3f55f9201a267be3de328ccc8ec67e64736f6c63430008090033000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e64c2d06d19d13061e62e291b2c4e9fe5679b93
Deployed Bytecode
0x6080604052600436106101a05760003560e01c80638da2f6d8116100ec578063b677bf0e1161008a578063e695f75c11610064578063e695f75c14610606578063f2fde38b1461062f578063f4d0841214610658578063f8b823e41461068157610201565b8063b677bf0e14610575578063dae3d6bb146105b2578063df6557ec146105dd57610201565b8063946647f1116100c6578063946647f1146104a557806397aa096e146104d05780639af8a581146104fb578063a4b519ff1461053857610201565b80638da2f6d8146104355780638da5cb5b1461045e57806392cddb911461048957610201565b80633085df631161015957806360be74e61161013357806360be74e6146103a1578063715018a6146103cc5780637abff543146103e357806381fe66ce1461040c57610201565b80633085df631461030b578063333ec062146103485780634465549a1461037857610201565b80630917377f146102065780630a9157c4146102315780630e48b8db1461025c57806316ac30a91461028c5780632e2f0ca0146102b55780632fae95bf146102e057610201565b3661020157600860149054906101000a900460ff16806101c05750600034145b6101ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101f690613a00565b60405180910390fd5b005b600080fd5b34801561021257600080fd5b5061021b6106ac565b6040516102289190613a61565b60405180910390f35b34801561023d57600080fd5b506102466106d2565b6040516102539190613adb565b60405180910390f35b61027660048036038101906102719190613be5565b6106f8565b6040516102839190613c72565b60405180910390f35b34801561029857600080fd5b506102b360048036038101906102ae9190613ccd565b610712565b005b3480156102c157600080fd5b506102ca6107ba565b6040516102d79190613d1b565b60405180910390f35b3480156102ec57600080fd5b506102f56107e0565b6040516103029190613d45565b60405180910390f35b34801561031757600080fd5b50610332600480360381019061032d9190613d8c565b6107fa565b60405161033f9190613a61565b60405180910390f35b610362600480360381019061035d9190613be5565b610854565b60405161036f9190613c72565b60405180910390f35b34801561038457600080fd5b5061039f600480360381019061039a9190613df8565b61086e565b005b3480156103ad57600080fd5b506103b661092e565b6040516103c39190613e46565b60405180910390f35b3480156103d857600080fd5b506103e1610954565b005b3480156103ef57600080fd5b5061040a60048036038101906104059190613df8565b6109dc565b005b34801561041857600080fd5b50610433600480360381019061042e9190613df8565b610a9c565b005b34801561044157600080fd5b5061045c60048036038101906104579190613df8565b610b5c565b005b34801561046a57600080fd5b50610473610c1c565b6040516104809190613a61565b60405180910390f35b6104a3600480360381019061049e9190613f0d565b610c45565b005b3480156104b157600080fd5b506104ba610f07565b6040516104c79190613fc3565b60405180910390f35b3480156104dc57600080fd5b506104e5610f2d565b6040516104f29190613a61565b60405180910390f35b34801561050757600080fd5b50610522600480360381019061051d9190613fde565b610f53565b60405161052f9190613c72565b60405180910390f35b34801561054457600080fd5b5061055f600480360381019061055a9190613fde565b610f6f565b60405161056c9190613c72565b60405180910390f35b34801561058157600080fd5b5061059c60048036038101906105979190613fde565b610f8b565b6040516105a99190613c72565b60405180910390f35b3480156105be57600080fd5b506105c7610fa7565b6040516105d49190614094565b60405180910390f35b3480156105e957600080fd5b5061060460048036038101906105ff91906140af565b610fcd565b005b34801561061257600080fd5b5061062d60048036038101906106289190613df8565b61119f565b005b34801561063b57600080fd5b5061065660048036038101906106519190613df8565b61125f565b005b34801561066457600080fd5b5061067f600480360381019061067a9190614129565b611357565b005b34801561068d57600080fd5b5061069661143b565b6040516106a39190614165565b60405180910390f35b600460019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600061070885858560008661144f565b9050949350505050565b61071a61188c565b73ffffffffffffffffffffffffffffffffffffffff16610738610c1c565b73ffffffffffffffffffffffffffffffffffffffff161461078e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610785906141cc565b60405180910390fd5b80600360186101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600360189054906101000a900467ffffffffffffffff1681565b6006828154811061080a57600080fd5b90600052602060002001818154811061082257600080fd5b906000526020600020016000915091509054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000610864858585600086611894565b9050949350505050565b61087661188c565b73ffffffffffffffffffffffffffffffffffffffff16610894610c1c565b73ffffffffffffffffffffffffffffffffffffffff16146108ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906141cc565b60405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61095c61188c565b73ffffffffffffffffffffffffffffffffffffffff1661097a610c1c565b73ffffffffffffffffffffffffffffffffffffffff16146109d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109c7906141cc565b60405180910390fd5b6109da6000611d0d565b565b6109e461188c565b73ffffffffffffffffffffffffffffffffffffffff16610a02610c1c565b73ffffffffffffffffffffffffffffffffffffffff1614610a58576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a4f906141cc565b60405180910390fd5b80600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b610aa461188c565b73ffffffffffffffffffffffffffffffffffffffff16610ac2610c1c565b73ffffffffffffffffffffffffffffffffffffffff1614610b18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b0f906141cc565b60405180910390fd5b80600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b610b6461188c565b73ffffffffffffffffffffffffffffffffffffffff16610b82610c1c565b73ffffffffffffffffffffffffffffffffffffffff1614610bd8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bcf906141cc565b60405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60068585905010610c8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8290614238565b60405180910390fd5b6000805b86869050811015610efe5736878783818110610cae57610cad614258565b5b9050602002810190610cc09190614296565b9050600081600001351415610cfd57610ceb818060200190610ce291906142be565b85898989611dd1565b83610cf69190614350565b9250610eea565b600181600001351415610d3857610d26818060200190610d1d91906142be565b888887896122b3565b83610d319190614350565b9250610ee9565b600281600001351415610d7357610d61818060200190610d5891906142be565b888887896126bd565b83610d6c9190614350565b9250610ee8565b600381600001351415610e6b576004888860018b8b9050610d9491906143a6565b818110610da457610da3614258565b5b9050602002810190610db69190614296565b600001351415610ddc576000600460006101000a81548160ff0219169083151502179055505b610dfd818060200190610def91906142be565b600089899050148688611894565b83610e089190614350565b92506004888860018b8b9050610e1e91906143a6565b818110610e2e57610e2d614258565b5b9050602002810190610e409190614296565b600001351415610e66576001600460006101000a81548160ff0219169083151502179055505b610ee7565b600481600001351415610eab57610e99818060200190610e8b91906142be565b60008989905014868861144f565b83610ea49190614350565b9250610ee6565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610edd90614426565b60405180910390fd5b5b5b5b5b508080610ef690614446565b915050610c8f565b50505050505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000610f64868686866000876122b3565b905095945050505050565b6000610f80868686866000876126bd565b905095945050505050565b6000610f9c86866000878787611dd1565b905095945050505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610fd561188c565b73ffffffffffffffffffffffffffffffffffffffff16610ff3610c1c565b73ffffffffffffffffffffffffffffffffffffffff1614611049576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611040906141cc565b60405180910390fd5b81600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600460016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180602001604052806040518060400160405280600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600460019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250815250600690600161119a929190613825565b505050565b6111a761188c565b73ffffffffffffffffffffffffffffffffffffffff166111c5610c1c565b73ffffffffffffffffffffffffffffffffffffffff161461121b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611212906141cc565b60405180910390fd5b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61126761188c565b73ffffffffffffffffffffffffffffffffffffffff16611285610c1c565b73ffffffffffffffffffffffffffffffffffffffff16146112db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112d2906141cc565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561134b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161134290614501565b60405180910390fd5b61135481611d0d565b50565b61135f61188c565b73ffffffffffffffffffffffffffffffffffffffff1661137d610c1c565b73ffffffffffffffffffffffffffffffffffffffff16146113d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113ca906141cc565b60405180910390fd5b60c88161ffff16111561141b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161141290614593565b60405180910390fd5b80600360146101000a81548161ffff021916908361ffff16021790555050565b600360149054906101000a900461ffff1681565b6000804790506001600860146101000a81548160ff02191690831515021790555060005b87879050811015611592573688888381811061149257611491614258565b5b90506020028101906114a491906145b3565b9050600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ac473c8a478360000160208101906114f89190613df8565b846020013585806040019061150d91906145db565b87806060019061151d919061463e565b89608001358e8b60c001356040518b63ffffffff1660e01b815260040161154c999897969594939291906147e3565b6000604051808303818588803b15801561156557600080fd5b505af1158015611579573d6000803e3d6000fd5b505050505050808061158a90614446565b915050611473565b506000600360169054906101000a900461ffff1661ffff16600360149054906101000a900461ffff1661ffff1647846115cb91906143a6565b6115d59190614864565b6115df91906148ed565b905060001515861515141561172c5761172381600660008154811061160757611606614258565b5b9060005260206000200160008154811061162457611623614258565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16876006805480602002602001604051908101604052809291908181526020016000905b8282101561171a5783829060005260206000200180548060200260200160405190810160405280929190818152602001828054801561170657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116116bc575b505050505081526020019060010190611672565b50505050612a3e565b80965081925050505b8047101561176f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161176690614990565b60405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156117b5573d6000803e3d6000fd5b5060003373ffffffffffffffffffffffffffffffffffffffff16476040516117dc906149e1565b60006040518083038185875af1925050503d8060008114611819576040519150601f19603f3d011682016040523d82523d6000602084013e61181e565b606091505b5050905080611862576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161185990614a68565b60405180910390fd5b6000600860146101000a81548160ff02191690831515021790555085935050505095945050505050565b600033905090565b6000806000905060005b87879050811015611a1a57368888838181106118bd576118bc614258565b5b90506020028101906118cf91906145b3565b9050806080013581602001356118e59190614350565b471015611927576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161191e90614ad4565b60405180910390fd5b8060200135836119379190614350565b9250600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b868980b8260800135836020013561198b9190614350565b83600001602081019061199e9190613df8565b8480606001906119ae919061463e565b86608001358b6040518763ffffffff1660e01b81526004016119d4959493929190614b03565b6000604051808303818588803b1580156119ed57600080fd5b505af1158015611a01573d6000803e3d6000fd5b5050505050508080611a1290614446565b91505061189e565b50600360169054906101000a900461ffff1661ffff16600360149054906101000a900461ffff1661ffff1682611a509190614864565b611a5a91906148ed565b9050600015158515151415611ba757611b9e816006600081548110611a8257611a81614258565b5b90600052602060002001600081548110611a9f57611a9e614258565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16866006805480602002602001604051908101604052809291908181526020016000905b82821015611b9557838290600052602060002001805480602002602001604051908101604052809291908181526020018280548015611b8157602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611b37575b505050505081526020019060010190611aed565b50505050612a3e565b80955081925050505b80471015611bea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be190614b9d565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611c30573d6000803e3d6000fd5b50600460009054906101000a900460ff168015611c4d5750600047115b15611d005760003373ffffffffffffffffffffffffffffffffffffffff1647604051611c78906149e1565b60006040518083038185875af1925050503d8060008114611cb5576040519150601f19603f3d011682016040523d82523d6000602084013e611cba565b606091505b5050905080611cfe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cf590614a68565b60405180910390fd5b505b8391505095945050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080611dde8888612d60565b9050600080600090505b825181108015611e1657506000838281518110611e0857611e07614258565b5b602002602001015160200151115b15611f3957600360169054906101000a900461ffff1661ffff16600360149054906101000a900461ffff1661ffff16848381518110611e5857611e57614258565b5b602002602001015160200151611e6e9190614864565b611e7891906148ed565b838281518110611e8b57611e8a614258565b5b60200260200101516040018181525050828181518110611eae57611ead614258565b5b6020026020010151600001519150611f2682848381518110611ed357611ed2614258565b5b602002602001015160200151858481518110611ef257611ef1614258565b5b602002602001015160400151600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16613152565b8080611f3190614446565b915050611de8565b5060005b8989905081101561206157368a8a83818110611f5c57611f5b614258565b5b9050602002810190611f6e91906145b3565b9050600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633af2c012826000016020810190611fc19190613df8565b8360200135848060400190611fd691906145db565b868060600190611fe6919061463e565b88608001358e8a60a001358b60c001356040518b63ffffffff1660e01b815260040161201b9a99989796959493929190614bbd565b600060405180830381600087803b15801561203557600080fd5b505af1158015612049573d6000803e3d6000fd5b5050505050808061205990614446565b915050611f3d565b5060005b8251811080156120935750600083828151811061208557612084614258565b5b602002602001015160200151115b156122a3578281815181106120ab576120aa614258565b5b602002602001015160000151915060008273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016120f49190613a61565b60206040518083038186803b15801561210c57600080fd5b505afa158015612120573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121449190614c62565b9050600081111561217c5761217a33828573ffffffffffffffffffffffffffffffffffffffff166133e29092919063ffffffff16565b505b6000600360169054906101000a900461ffff1661ffff16600360149054906101000a900461ffff1661ffff16838786815181106121bc576121bb614258565b5b6020026020010151602001516121d291906143a6565b6121dc9190614864565b6121e691906148ed565b905061221e818685815181106121ff576121fe614258565b5b6020026020010151600001518c8c8c906122199190614e80565b612a3e565b809b50819250505061224f85848151811061223c5761223b614258565b5b6020026020010151600001518883613516565b61228e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161228590614ee1565b60405180910390fd5b5050808061229b90614446565b915050612065565b5086925050509695505050505050565b600080600090506000805b8989905081101561237b578989828181106122dc576122db614258565b5b90506020028101906122ee91906145b3565b608001358a8a8381811061230557612304614258565b5b905060200281019061231791906145b3565b602001356123259190614350565b836123309190614350565b925089898281811061234557612344614258565b5b905060200281019061235791906145b3565b60200135826123669190614350565b9150808061237390614446565b9150506122be565b50600360169054906101000a900461ffff1661ffff16600360149054906101000a900461ffff1661ffff16826123b19190614864565b6123bb91906148ed565b9050612430818a8a60008181106123d5576123d4614258565b5b90506020028101906123e791906145b3565b80604001906123f691906145db565b600081811061240857612407614258565b5b905060200201602081019061241d9190613df8565b878a8a9061242b9190614e80565b612a3e565b809650819250505060008989600081811061244e5761244d614258565b5b905060200281019061246091906145b3565b806040019061246f91906145db565b600081811061248157612480614258565b5b90506020020160208101906124969190613df8565b90506124c6818484600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16613152565b61252c8a8a60008181106124dd576124dc614258565b5b90506020028101906124ef91906145b3565b80604001906124fe91906145db565b60008181106125105761250f614258565b5b90506020020160208101906125259190613df8565b8684613516565b61256b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161256290614ee1565b60405180910390fd5b60005b8a8a90508110156126ac57368b8b8381811061258d5761258c614258565b5b905060200281019061259f91906145b3565b9050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c219a14d8280604001906125ef91906145db565b600081811061260157612600614258565b5b90506020020160208101906126169190613df8565b8360000160208101906126299190613df8565b846020013585806060019061263e919061463e565b87608001358e6040518863ffffffff1660e01b81526004016126669796959493929190614f01565b600060405180830381600087803b15801561268057600080fd5b505af1158015612694573d6000803e3d6000fd5b505050505080806126a490614446565b91505061256e565b508593505050509695505050505050565b6000806126ca8888612d60565b905060005b8151811080156126fd575060008282815181106126ef576126ee614258565b5b602002602001015160200151115b156128ed57600360169054906101000a900461ffff1661ffff16600360149054906101000a900461ffff1661ffff1683838151811061273f5761273e614258565b5b6020026020010151604001516127559190614864565b61275f91906148ed565b82828151811061277257612771614258565b5b60200260200101516040018181525050600082828151811061279757612796614258565b5b602002602001015160000151905061280f818484815181106127bc576127bb614258565b5b6020026020010151602001518585815181106127db576127da614258565b5b602002602001015160400151600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16613152565b600083838151811061282457612823614258565b5b60200260200101516040015190506128688185858151811061284957612848614258565b5b602002602001015160000151898c8c906128639190614e80565b612a3e565b809850819250505061289984848151811061288657612885614258565b5b6020026020010151600001518783613516565b6128d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128cf90614ee1565b60405180910390fd5b505080806128e590614446565b9150506126cf565b5060005b88889050811015612a2f57368989838181106129105761290f614258565b5b905060200281019061292291906145b3565b9050600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c219a14d82806040019061297291906145db565b600081811061298457612983614258565b5b90506020020160208101906129999190613df8565b8360000160208101906129ac9190613df8565b84602001358580606001906129c1919061463e565b87608001358c6040518863ffffffff1660e01b81526004016129e99796959493929190614f01565b600060405180830381600087803b158015612a0357600080fd5b505af1158015612a17573d6000803e3d6000fd5b50505050508080612a2790614446565b9150506128f1565b50839150509695505050505050565b60008060008351148015612a715750600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff1684105b15612a8157858491509150612d57565b600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff16841015612d4b5760005b8351811015612d45578573ffffffffffffffffffffffffffffffffffffffff16848281518110612adf57612ade614258565b5b6020026020010151600081518110612afa57612af9614258565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16148015612bcd5750600460019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16848281518110612b6c57612b6b614258565b5b60200260200101516001868481518110612b8957612b88614258565b5b602002602001015151612b9c91906143a6565b81518110612bad57612bac614258565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16145b15612d32576000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fbd4122a89878581518110612c2657612c25614258565b5b60200260200101516040518363ffffffff1660e01b8152600401612c4b929190614ff1565b604080518083038186803b158015612c6257600080fd5b505afa158015612c76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c9a9190615021565b5090506000819050600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff168188612ccf9190614350565b1115612d1d5786600360189054906101000a900467ffffffffffffffff1667ffffffffffffffff16612d0191906143a6565b905081818a612d109190614864565b612d1a91906148ed565b98505b8087612d299190614350565b96505050612d45565b8080612d3d90614446565b915050612aac565b50612d50565b600095505b8584915091505b94509492505050565b60608282905067ffffffffffffffff811115612d7f57612d7e614c8f565b5b604051908082528060200260200182016040528015612db857816020015b612da5613880565b815260200190600190039081612d9d5790505b50905060005b8383905081101561314b5760005b848490508110156131375736858584818110612deb57612dea614258565b5b9050602002810190612dfd91906145b3565b9050808060400190612e0f91906145db565b6001838060400190612e2191906145db565b9050612e2d91906143a6565b818110612e3d57612e3c614258565b5b9050602002016020810190612e529190613df8565b73ffffffffffffffffffffffffffffffffffffffff16848381518110612e7b57612e7a614258565b5b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff161415612f7d576001818060400190612eb591906145db565b90501115612ef9578060a00135848381518110612ed557612ed4614258565b5b6020026020010151602001818151612eed9190614350565b91508181525050612f77565b80608001358160200135612f0d9190614350565b848381518110612f2057612f1f614258565b5b6020026020010151602001818151612f389190614350565b915081815250508060200135848381518110612f5757612f56614258565b5b6020026020010151604001818151612f6f9190614350565b915081815250505b50613137565b6000848381518110612f9257612f91614258565b5b602002602001015160200151148015612fcd575060008160a001351180612fcc5750600081608001358260200135612fca9190614350565b115b5b1561312357808060400190612fe291906145db565b6001838060400190612ff491906145db565b905061300091906143a6565b8181106130105761300f614258565b5b90506020020160208101906130259190613df8565b84838151811061303857613037614258565b5b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600181806040019061308891906145db565b905011156130bd578060a001358483815181106130a8576130a7614258565b5b6020026020010151602001818152505061311d565b806080013581602001356130d19190614350565b8483815181106130e4576130e3614258565b5b60200260200101516020018181525050806020013584838151811061310c5761310b614258565b5b602002602001015160400181815250505b50613137565b50808061312f90614446565b915050612dcc565b50808061314390614446565b915050612dbe565b5092915050565b828473ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e33306040518363ffffffff1660e01b815260040161318e929190615061565b60206040518083038186803b1580156131a657600080fd5b505afa1580156131ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131de9190614c62565b101561321f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613216906150fc565b60405180910390fd5b818361322b9190614350565b8473ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b81526004016132649190613a61565b60206040518083038186803b15801561327c57600080fd5b505afa158015613290573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132b49190614c62565b10156132f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132ec90615168565b60405180910390fd5b613300843085613516565b61333f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613336906151d4565b60405180910390fd5b828473ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30846040518363ffffffff1660e01b815260040161337b929190615061565b60206040518083038186803b15801561339357600080fd5b505afa1580156133a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133cb9190614c62565b10156133dc576133db8482613695565b5b50505050565b60008060008573ffffffffffffffffffffffffffffffffffffffff1685856040516024016134119291906151f4565b6040516020818303038152906040527fa9059cbb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161349b919061528c565b6000604051808303816000865af19150503d80600081146134d8576040519150601f19603f3d011682016040523d82523d6000602084013e6134dd565b606091505b509150915081801561350b575060008151148061350a57508080602001905181019061350991906152b8565b5b5b925050509392505050565b6000833b61352357600080fd5b60008473ffffffffffffffffffffffffffffffffffffffff16338585604051602401613551939291906152e5565b6040516020818303038152906040527f23b872dd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516135db919061528c565b6000604051808303816000865af19150503d8060008114613618576040519150601f19603f3d011682016040523d82523d6000602084013e61361d565b606091505b505090503d60008114613637576020811461364057600080fd5b6001925061364c565b60206000803e60005192505b508061368d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161368490615368565b60405180910390fd5b509392505050565b600082905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90506136ea83828473ffffffffffffffffffffffffffffffffffffffff166136f19092919063ffffffff16565b5050505050565b60008060008573ffffffffffffffffffffffffffffffffffffffff1685856040516024016137209291906151f4565b6040516020818303038152906040527f095ea7b3000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516137aa919061528c565b6000604051808303816000865af19150503d80600081146137e7576040519150601f19603f3d011682016040523d82523d6000602084013e6137ec565b606091505b509150915081801561381a575060008151148061381957508080602001905181019061381891906152b8565b5b5b925050509392505050565b82805482825590600052602060002090810192821561386f579160200282015b8281111561386e5782518290600261385e9291906138b7565b5091602001919060010190613845565b5b50905061387c9190613941565b5090565b6040518060600160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081525090565b828054828255906000526020600020908101928215613930579160200282015b8281111561392f5782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906138d7565b5b50905061393d9190613965565b5090565b5b8082111561396157600081816139589190613982565b50600101613942565b5090565b5b8082111561397e576000816000905550600101613966565b5090565b50805460008255906000526020600020908101906139a09190613965565b50565b600082825260208201905092915050565b7f4e6f6e2d70617961626c65000000000000000000000000000000000000000000600082015250565b60006139ea600b836139a3565b91506139f5826139b4565b602082019050919050565b60006020820190508181036000830152613a19816139dd565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613a4b82613a20565b9050919050565b613a5b81613a40565b82525050565b6000602082019050613a766000830184613a52565b92915050565b6000819050919050565b6000613aa1613a9c613a9784613a20565b613a7c565b613a20565b9050919050565b6000613ab382613a86565b9050919050565b6000613ac582613aa8565b9050919050565b613ad581613aba565b82525050565b6000602082019050613af06000830184613acc565b92915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f840112613b2f57613b2e613b0a565b5b8235905067ffffffffffffffff811115613b4c57613b4b613b0f565b5b602083019150836020820283011115613b6857613b67613b14565b5b9250929050565b60008115159050919050565b613b8481613b6f565b8114613b8f57600080fd5b50565b600081359050613ba181613b7b565b92915050565b6000613bb282613a20565b9050919050565b613bc281613ba7565b8114613bcd57600080fd5b50565b600081359050613bdf81613bb9565b92915050565b60008060008060608587031215613bff57613bfe613b00565b5b600085013567ffffffffffffffff811115613c1d57613c1c613b05565b5b613c2987828801613b19565b94509450506020613c3c87828801613b92565b9250506040613c4d87828801613bd0565b91505092959194509250565b6000819050919050565b613c6c81613c59565b82525050565b6000602082019050613c876000830184613c63565b92915050565b600067ffffffffffffffff82169050919050565b613caa81613c8d565b8114613cb557600080fd5b50565b600081359050613cc781613ca1565b92915050565b600060208284031215613ce357613ce2613b00565b5b6000613cf184828501613cb8565b91505092915050565b6000613d0582613aa8565b9050919050565b613d1581613cfa565b82525050565b6000602082019050613d306000830184613d0c565b92915050565b613d3f81613c8d565b82525050565b6000602082019050613d5a6000830184613d36565b92915050565b613d6981613c59565b8114613d7457600080fd5b50565b600081359050613d8681613d60565b92915050565b60008060408385031215613da357613da2613b00565b5b6000613db185828601613d77565b9250506020613dc285828601613d77565b9150509250929050565b613dd581613a40565b8114613de057600080fd5b50565b600081359050613df281613dcc565b92915050565b600060208284031215613e0e57613e0d613b00565b5b6000613e1c84828501613de3565b91505092915050565b6000613e3082613aa8565b9050919050565b613e4081613e25565b82525050565b6000602082019050613e5b6000830184613e37565b92915050565b60008083601f840112613e7757613e76613b0a565b5b8235905067ffffffffffffffff811115613e9457613e93613b0f565b5b602083019150836020820283011115613eb057613eaf613b14565b5b9250929050565b60008083601f840112613ecd57613ecc613b0a565b5b8235905067ffffffffffffffff811115613eea57613ee9613b0f565b5b602083019150836020820283011115613f0657613f05613b14565b5b9250929050565b600080600080600060608688031215613f2957613f28613b00565b5b600086013567ffffffffffffffff811115613f4757613f46613b05565b5b613f5388828901613e61565b9550955050602086013567ffffffffffffffff811115613f7657613f75613b05565b5b613f8288828901613eb7565b93509350506040613f9588828901613de3565b9150509295509295909350565b6000613fad82613aa8565b9050919050565b613fbd81613fa2565b82525050565b6000602082019050613fd86000830184613fb4565b92915050565b600080600080600060608688031215613ffa57613ff9613b00565b5b600086013567ffffffffffffffff81111561401857614017613b05565b5b61402488828901613b19565b9550955050602086013567ffffffffffffffff81111561404757614046613b05565b5b61405388828901613eb7565b9350935050604061406688828901613de3565b9150509295509295909350565b600061407e82613aa8565b9050919050565b61408e81614073565b82525050565b60006020820190506140a96000830184614085565b92915050565b600080604083850312156140c6576140c5613b00565b5b60006140d485828601613de3565b92505060206140e585828601613de3565b9150509250929050565b600061ffff82169050919050565b614106816140ef565b811461411157600080fd5b50565b600081359050614123816140fd565b92915050565b60006020828403121561413f5761413e613b00565b5b600061414d84828501614114565b91505092915050565b61415f816140ef565b82525050565b600060208201905061417a6000830184614156565b92915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006141b66020836139a3565b91506141c182614180565b602082019050919050565b600060208201905081810360008301526141e5816141a9565b9050919050565b7f6d6f7265207468616e2035206d65746144657461696c73000000000000000000600082015250565b60006142226017836139a3565b915061422d826141ec565b602082019050919050565b6000602082019050818103600083015261425181614215565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b600080fd5b600080fd5b6000823560016040038336030381126142b2576142b1614287565b5b80830191505092915050565b600080833560016020038436030381126142db576142da614287565b5b80840192508235915067ffffffffffffffff8211156142fd576142fc61428c565b5b60208301925060208202360383131561431957614318614291565b5b509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061435b82613c59565b915061436683613c59565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561439b5761439a614321565b5b828201905092915050565b60006143b182613c59565b91506143bc83613c59565b9250828210156143cf576143ce614321565b5b828203905092915050565b7f57726f6e67207061796d656e744e6574776f726b496400000000000000000000600082015250565b60006144106016836139a3565b915061441b826143da565b602082019050919050565b6000602082019050818103600083015261443f81614403565b9050919050565b600061445182613c59565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561448457614483614321565b5b600182019050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006144eb6026836139a3565b91506144f68261448f565b604082019050919050565b6000602082019050818103600083015261451a816144de565b9050919050565b7f546865206261746368206665652076616c756520697320746f6f20686967683a60008201527f203e203225000000000000000000000000000000000000000000000000000000602082015250565b600061457d6025836139a3565b915061458882614521565b604082019050919050565b600060208201905081810360008301526145ac81614570565b9050919050565b60008235600160e0038336030381126145cf576145ce614287565b5b80830191505092915050565b600080833560016020038436030381126145f8576145f7614287565b5b80840192508235915067ffffffffffffffff82111561461a5761461961428c565b5b60208301925060208202360383131561463657614635614291565b5b509250929050565b6000808335600160200384360303811261465b5761465a614287565b5b80840192508235915067ffffffffffffffff82111561467d5761467c61428c565b5b60208301925060018202360383131561469957614698614291565b5b509250929050565b60006146ac82613aa8565b9050919050565b6146bc816146a1565b82525050565b600082825260208201905092915050565b6000819050919050565b6146e681613a40565b82525050565b60006146f883836146dd565b60208301905092915050565b60006147136020840184613de3565b905092915050565b6000602082019050919050565b600061473483856146c2565b935061473f826146d3565b8060005b85811015614778576147558284614704565b61475f88826146ec565b975061476a8361471b565b925050600181019050614743565b5085925050509392505050565b600082825260208201905092915050565b82818337600083830152505050565b6000601f19601f8301169050919050565b60006147c28385614785565b93506147cf838584614796565b6147d8836147a5565b840190509392505050565b600060e0820190506147f8600083018c6146b3565b614805602083018b613c63565b818103604083015261481881898b614728565b9050818103606083015261482d8187896147b6565b905061483c6080830186613c63565b61484960a08301856146b3565b61485660c0830184613c63565b9a9950505050505050505050565b600061486f82613c59565b915061487a83613c59565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156148b3576148b2614321565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006148f882613c59565b915061490383613c59565b925082614913576149126148be565b5b828204905092915050565b7f4e6f7420656e6f7567682066756e647320666f7220626174636820636f6e766560008201527f7273696f6e206665657300000000000000000000000000000000000000000000602082015250565b600061497a602a836139a3565b91506149858261491e565b604082019050919050565b600060208201905081810360008301526149a98161496d565b9050919050565b600081905092915050565b50565b60006149cb6000836149b0565b91506149d6826149bb565b600082019050919050565b60006149ec826149be565b9150819050919050565b7f436f756c64206e6f742073656e642072656d61696e696e672066756e6473207460008201527f6f20746865207061796572000000000000000000000000000000000000000000602082015250565b6000614a52602b836139a3565b9150614a5d826149f6565b604082019050919050565b60006020820190508181036000830152614a8181614a45565b9050919050565b7f4e6f7420656e6f7567682066756e647300000000000000000000000000000000600082015250565b6000614abe6010836139a3565b9150614ac982614a88565b602082019050919050565b60006020820190508181036000830152614aed81614ab1565b9050919050565b614afd81613ba7565b82525050565b6000608082019050614b186000830188614af4565b8181036020830152614b2b8186886147b6565b9050614b3a6040830185613c63565b614b476060830184614af4565b9695505050505050565b7f4e6f7420656e6f7567682066756e647320666f72206261746368206665650000600082015250565b6000614b87601e836139a3565b9150614b9282614b51565b602082019050919050565b60006020820190508181036000830152614bb681614b7a565b9050919050565b600061010082019050614bd3600083018d613a52565b614be0602083018c613c63565b8181036040830152614bf3818a8c614728565b90508181036060830152614c0881888a6147b6565b9050614c176080830187613c63565b614c2460a0830186613a52565b614c3160c0830185613c63565b614c3e60e0830184613c63565b9b9a5050505050505050505050565b600081519050614c5c81613d60565b92915050565b600060208284031215614c7857614c77613b00565b5b6000614c8684828501614c4d565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b614cc7826147a5565b810181811067ffffffffffffffff82111715614ce657614ce5614c8f565b5b80604052505050565b6000614cf9613af6565b9050614d058282614cbe565b919050565b600067ffffffffffffffff821115614d2557614d24614c8f565b5b602082029050602081019050919050565b600067ffffffffffffffff821115614d5157614d50614c8f565b5b602082029050602081019050919050565b6000614d75614d7084614d36565b614cef565b90508083825260208201905060208402830185811115614d9857614d97613b14565b5b835b81811015614dc15780614dad8882613de3565b845260208401935050602081019050614d9a565b5050509392505050565b600082601f830112614de057614ddf613b0a565b5b8135614df0848260208601614d62565b91505092915050565b6000614e0c614e0784614d0a565b614cef565b90508083825260208201905060208402830185811115614e2f57614e2e613b14565b5b835b81811015614e7657803567ffffffffffffffff811115614e5457614e53613b0a565b5b808601614e618982614dcb565b85526020850194505050602081019050614e31565b5050509392505050565b6000614e8d368484614df9565b905092915050565b7f426174636820666565207472616e7366657246726f6d2829206661696c656400600082015250565b6000614ecb601f836139a3565b9150614ed682614e95565b602082019050919050565b60006020820190508181036000830152614efa81614ebe565b9050919050565b600060c082019050614f16600083018a613a52565b614f236020830189613a52565b614f306040830188613c63565b8181036060830152614f438186886147b6565b9050614f526080830185613c63565b614f5f60a0830184613a52565b98975050505050505050565b600081519050919050565b6000819050602082019050919050565b6000602082019050919050565b6000614f9e82614f6b565b614fa881856146c2565b9350614fb383614f76565b8060005b83811015614fe4578151614fcb88826146ec565b9750614fd683614f86565b925050600181019050614fb7565b5085935050505092915050565b60006040820190506150066000830185613c63565b81810360208301526150188184614f93565b90509392505050565b6000806040838503121561503857615037613b00565b5b600061504685828601614c4d565b925050602061505785828601614c4d565b9150509250929050565b60006040820190506150766000830185613a52565b6150836020830184613a52565b9392505050565b7f496e73756666696369656e7420616c6c6f77616e636520666f7220626174636860008201527f20746f2070617900000000000000000000000000000000000000000000000000602082015250565b60006150e66027836139a3565b91506150f18261508a565b604082019050919050565b60006020820190508181036000830152615115816150d9565b9050919050565b7f4e6f7420656e6f7567682066756e64732c20696e636c7564696e672066656573600082015250565b60006151526020836139a3565b915061515d8261511c565b602082019050919050565b6000602082019050818103600083015261518181615145565b9050919050565b7f7061796d656e74207472616e7366657246726f6d2829206661696c6564000000600082015250565b60006151be601d836139a3565b91506151c982615188565b602082019050919050565b600060208201905081810360008301526151ed816151b1565b9050919050565b60006040820190506152096000830185613a52565b6152166020830184613c63565b9392505050565b600081519050919050565b60005b8381101561524657808201518184015260208101905061522b565b83811115615255576000848401525b50505050565b60006152668261521d565b61527081856149b0565b9350615280818560208601615228565b80840191505092915050565b6000615298828461525b565b915081905092915050565b6000815190506152b281613b7b565b92915050565b6000602082840312156152ce576152cd613b00565b5b60006152dc848285016152a3565b91505092915050565b60006060820190506152fa6000830186613a52565b6153076020830185613a52565b6153146040830184613c63565b949350505050565b7f7472616e7366657246726f6d282920686173206265656e207265766572746564600082015250565b60006153526020836139a3565b915061535d8261531c565b602082019050919050565b6000602082019050818103600083015261538181615345565b905091905056fea26469706673582212207a94adaf919c0e13cce412e4c26773542b3f55f9201a267be3de328ccc8ec67e64736f6c63430008090033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e64c2d06d19d13061e62e291b2c4e9fe5679b93
-----Decoded View---------------
Arg [0] : _paymentErc20Proxy (address): 0x0000000000000000000000000000000000000000
Arg [1] : _paymentNativeProxy (address): 0x0000000000000000000000000000000000000000
Arg [2] : _paymentErc20ConversionProxy (address): 0x0000000000000000000000000000000000000000
Arg [3] : _paymentNativeConversionFeeProxy (address): 0x0000000000000000000000000000000000000000
Arg [4] : _chainlinkConversionPath (address): 0x0000000000000000000000000000000000000000
Arg [5] : _owner (address): 0x4E64C2d06d19D13061e62E291b2C4e9fe5679b93
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000004e64c2d06d19d13061e62e291b2c4e9fe5679b93
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
BASE | 100.00% | $3,106.79 | 0.00586318 | $18.22 |
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.