More Info
Private Name Tags
ContractCreator
Multichain Info
4 addresses found via
Latest 25 from a total of 706 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Execute | 13054932 | 121 days ago | IN | 0.00228872 ETH | 0.00000087 | ||||
Execute | 13047850 | 121 days ago | IN | 0.00410233 ETH | 0.00000091 | ||||
Execute | 13047373 | 121 days ago | IN | 0.0040542 ETH | 0.00000083 | ||||
Execute | 12949559 | 123 days ago | IN | 0.00410217 ETH | 0.00000062 | ||||
Execute | 12938291 | 124 days ago | IN | 0.00161299 ETH | 0.00000062 | ||||
Execute | 12928564 | 124 days ago | IN | 0.00595604 ETH | 0.00004788 | ||||
Execute | 12920225 | 124 days ago | IN | 0.00219187 ETH | 0.00000112 | ||||
Execute | 12920209 | 124 days ago | IN | 0.00990983 ETH | 0.00000023 | ||||
Execute | 12889585 | 125 days ago | IN | 0.00098555 ETH | 0.00000011 | ||||
Execute | 12837519 | 126 days ago | IN | 0.00170424 ETH | 0.00000082 | ||||
Execute | 12486900 | 134 days ago | IN | 0.00293234 ETH | 0.00000291 | ||||
Execute | 12480334 | 134 days ago | IN | 0.00277614 ETH | 0.00000046 | ||||
Execute | 12480133 | 134 days ago | IN | 0.00367115 ETH | 0.00000099 | ||||
Execute | 12479911 | 134 days ago | IN | 0.00356211 ETH | 0.00000102 | ||||
Execute | 12479837 | 134 days ago | IN | 0.0035662 ETH | 0.00000098 | ||||
Execute | 12477154 | 134 days ago | IN | 0.00356123 ETH | 0.00000091 | ||||
Execute | 12477126 | 134 days ago | IN | 0.00356123 ETH | 0.00000092 | ||||
Execute | 12464727 | 135 days ago | IN | 0.01997598 ETH | 0.00000141 | ||||
Execute | 12306749 | 138 days ago | IN | 3.03276544 ETH | 0.00000563 | ||||
Execute | 12300335 | 138 days ago | IN | 0.00277237 ETH | 0.00000093 | ||||
Execute | 12264977 | 139 days ago | IN | 1.30182057 ETH | 0.00000044 | ||||
Execute | 12238349 | 140 days ago | IN | 0.0012984 ETH | 0.00000038 | ||||
Execute | 11907242 | 147 days ago | IN | 0.00594322 ETH | 0.00000029 | ||||
Execute | 11831176 | 149 days ago | IN | 0.05509715 ETH | 0.00000219 | ||||
Execute | 11814184 | 150 days ago | IN | 0.02005111 ETH | 0.00000234 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
17567967 | 16 days ago | 0.00001 ETH | ||||
17567967 | 16 days ago | 0.00001 ETH | ||||
16889101 | 32 days ago | 0.02686986 ETH | ||||
16889101 | 32 days ago | 0.02686986 ETH | ||||
15136119 | 73 days ago | 0.12384427 ETH | ||||
15136119 | 73 days ago | 0.12384427 ETH | ||||
14975531 | 76 days ago | 0.0012 ETH | ||||
14975531 | 76 days ago | 0.0012 ETH | ||||
14768740 | 81 days ago | 0.05466549 ETH | ||||
14768740 | 81 days ago | 0.05466549 ETH | ||||
14402675 | 90 days ago | 0.03598598 ETH | ||||
14402675 | 90 days ago | 0.03598598 ETH | ||||
14348173 | 91 days ago | 0.01271857 ETH | ||||
14348173 | 91 days ago | 0.01271857 ETH | ||||
14010841 | 99 days ago | 0.03721583 ETH | ||||
14010841 | 99 days ago | 0.03721583 ETH | ||||
13720273 | 105 days ago | 0.08800281 ETH | ||||
13720273 | 105 days ago | 0.08800281 ETH | ||||
13227182 | 117 days ago | 0.013 ETH | ||||
13227182 | 117 days ago | 0.013 ETH | ||||
13115544 | 119 days ago | 0.04741638 ETH | ||||
13115544 | 119 days ago | 0.04741638 ETH | ||||
13089692 | 120 days ago | 0.00498371 ETH | ||||
13089692 | 120 days ago | 0.00498371 ETH | ||||
13054932 | 121 days ago | 0.00228872 ETH |
Loading...
Loading
Contract Name:
ActionExecutor_Blast
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { IRegistry } from '../interfaces/IRegistry.sol'; import { IVariableBalanceRecords } from '../interfaces/IVariableBalanceRecords.sol'; import { ActionExecutor } from '../ActionExecutor.sol'; import { BlastConfig } from './blast-config/BlastConfig.sol'; /** * @title ActionExecutor_Blast * @notice The main contract for cross-chain swaps */ contract ActionExecutor_Blast is ActionExecutor, BlastConfig { /** * @notice Initializes the contract * @param _registry The address of the action settings registry contract * @param _variableBalanceRecords The address of the variable balance records contract * @param _actionIdOffset The initial offset of the action ID value * @param _owner The address of the initial owner of the contract * @param _managers The addresses of initial managers of the contract * @param _addOwnerToManagers The flag to optionally add the owner to the list of managers */ constructor( IRegistry _registry, IVariableBalanceRecords _variableBalanceRecords, uint256 _actionIdOffset, address _owner, address[] memory _managers, bool _addOwnerToManagers ) ActionExecutor( _registry, _variableBalanceRecords, _actionIdOffset, _owner, _managers, _addOwnerToManagers ) { blastConfigureClaimableAssets(); } function _isBlastConfigAuthorized() internal view override returns (bool) { return isManager(msg.sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (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 Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// 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: AGPL-3.0-only pragma solidity 0.8.19; import { ReentrancyGuard } from '@openzeppelin/contracts/security/ReentrancyGuard.sol'; import { IActionDataStructures } from './interfaces/IActionDataStructures.sol'; import { IGateway } from './crosschain/interfaces/IGateway.sol'; import { IGatewayClient } from './crosschain/interfaces/IGatewayClient.sol'; import { IRegistry } from './interfaces/IRegistry.sol'; import { ISettings } from './interfaces/ISettings.sol'; import { ITokenMint } from './interfaces/ITokenMint.sol'; import { IVariableBalanceRecords } from './interfaces/IVariableBalanceRecords.sol'; import { IVault } from './interfaces/IVault.sol'; import { BalanceManagement } from './BalanceManagement.sol'; import { CallerGuard } from './CallerGuard.sol'; import { Pausable } from './Pausable.sol'; import { SystemVersionId } from './SystemVersionId.sol'; import { TokenMintError, ZeroAddressError } from './Errors.sol'; import './helpers/AddressHelper.sol' as AddressHelper; import './helpers/DecimalsHelper.sol' as DecimalsHelper; import './helpers/GasReserveHelper.sol' as GasReserveHelper; import './helpers/RefundHelper.sol' as RefundHelper; import './helpers/TransferHelper.sol' as TransferHelper; import './Constants.sol' as Constants; /** * @title ActionExecutor * @notice The main contract for cross-chain swaps */ contract ActionExecutor is SystemVersionId, Pausable, ReentrancyGuard, CallerGuard, BalanceManagement, IGatewayClient, ISettings, IActionDataStructures { /** * @dev The contract for action settings */ IRegistry public registry; /** * @dev The contract for variable balance storage */ IVariableBalanceRecords public variableBalanceRecords; uint256 private lastActionId = block.chainid * 1e7 + 555 ** 2; /** * @notice Emitted when source chain action is performed * @param actionId The ID of the action * @param targetChainId The ID of the target chain * @param sourceSender The address of the user on the source chain * @param targetRecipient The address of the recipient on the target chain * @param gatewayType The type of cross-chain gateway * @param sourceToken The address of the input token on the source chain * @param targetToken The address of the output token on the target chain * @param amount The amount of the vault asset used for the action, with decimals set to 18 * @param fee The fee amount, measured in vault asset with decimals set to 18 * @param timestamp The timestamp of the action (in seconds) */ event ActionSource( uint256 indexed actionId, uint256 indexed targetChainId, address indexed sourceSender, address targetRecipient, uint256 gatewayType, address sourceToken, address targetToken, uint256 amount, uint256 fee, uint256 timestamp ); /** * @notice Emitted when target chain action is performed * @param actionId The ID of the action * @param sourceChainId The ID of the source chain * @param isSuccess The status of the action execution * @param timestamp The timestamp of the action (in seconds) */ event ActionTarget( uint256 indexed actionId, uint256 indexed sourceChainId, bool indexed isSuccess, uint256 timestamp ); /** * @notice Emitted when single-chain action is performed * @param actionId The ID of the action * @param sender The address of the user * @param recipient The address of the recipient * @param fromToken The address of the input token * @param toToken The address of the output token * @param fromAmount The input token amount * @param toAmount The output token amount * @param toTokenFee The fee amount, measured in the output token * @param timestamp The timestamp of the action (in seconds) */ event ActionLocal( uint256 indexed actionId, address indexed sender, address recipient, address fromToken, address toToken, uint256 fromAmount, uint256 toAmount, uint256 toTokenFee, uint256 timestamp ); /** * @notice Emitted for source chain and single-chain actions when user's funds processing is completed * @param actionId The ID of the action * @param isLocal The action type flag, is true for single-chain actions * @param sender The address of the user * @param routerType The type of the swap router * @param fromTokenAddress The address of the swap input token * @param toTokenAddress The address of the swap output token * @param fromAmount The input token amount * @param resultAmount The swap result token amount */ event SourceProcessed( uint256 indexed actionId, bool indexed isLocal, address indexed sender, uint256 routerType, address fromTokenAddress, address toTokenAddress, uint256 fromAmount, uint256 resultAmount ); /** * @notice Emitted for target chain actions when the user's funds processing is completed * @param actionId The ID of the action * @param recipient The address of the recipient * @param routerType The type of the swap router * @param fromTokenAddress The address of the swap input token * @param toTokenAddress The address of the swap output token * @param fromAmount The input token amount * @param resultAmount The swap result token amount */ event TargetProcessed( uint256 indexed actionId, address indexed recipient, uint256 routerType, address fromTokenAddress, address toTokenAddress, uint256 fromAmount, uint256 resultAmount ); /** * @notice Emitted when the variable balance is allocated on the target chain * @param actionId The ID of the action * @param recipient The address of the variable balance recipient * @param vaultType The type of the corresponding vault * @param amount The allocated variable balance amount */ event VariableBalanceAllocated( uint256 indexed actionId, address indexed recipient, uint256 vaultType, uint256 amount ); /** * @notice Emitted when the Registry contract address is updated * @param registryAddress The address of the Registry contract */ event SetRegistry(address indexed registryAddress); /** * @notice Emitted when the VariableBalanceRecords contract address is updated * @param recordsAddress The address of the VariableBalanceRecords contract */ event SetVariableBalanceRecords(address indexed recordsAddress); /** * @notice Emitted when the caller is not a registered cross-chain gateway */ error OnlyGatewayError(); /** * @notice Emitted when the call is not from the current contract */ error OnlySelfError(); /** * @notice Emitted when a cross-chain swap is attempted with the target chain ID matching the current chain */ error SameChainIdError(); /** * @notice Emitted when a single-chain swap is attempted with the same token as input and output */ error SameTokenError(); /** * @notice Emitted when the native token value of the transaction does not correspond to the swap amount */ error NativeTokenValueError(); /** * @notice Emitted when the requested cross-chain gateway type is not set */ error GatewayNotSetError(); /** * @notice Emitted when the requested swap router type is not set */ error RouterNotSetError(); /** * @notice Emitted when the requested vault type is not set */ error VaultNotSetError(); /** * @notice Emitted when the provided call value is not sufficient for the cross-chain message sending */ error MessageFeeError(); /** * @notice Emitted when the swap amount is greater than the allowed maximum */ error SwapAmountMaxError(); /** * @notice Emitted when the swap amount is less than the allowed minimum */ error SwapAmountMinError(); /** * @notice Emitted when the swap process results in an error */ error SwapError(); /** * @notice Emitted when there is no matching target swap info option */ error TargetSwapInfoError(); /** * @dev Modifier to check if the caller is a registered cross-chain gateway */ modifier onlyGateway() { if (!registry.isGatewayAddress(msg.sender)) { revert OnlyGatewayError(); } _; } /** * @dev Modifier to check if the caller is the current contract */ modifier onlySelf() { if (msg.sender != address(this)) { revert OnlySelfError(); } _; } /** * @notice Deploys the ActionExecutor contract * @param _registry The address of the action settings registry contract * @param _variableBalanceRecords The address of the variable balance records contract * @param _actionIdOffset The initial offset of the action ID value * @param _owner The address of the initial owner of the contract * @param _managers The addresses of initial managers of the contract * @param _addOwnerToManagers The flag to optionally add the owner to the list of managers */ constructor( IRegistry _registry, IVariableBalanceRecords _variableBalanceRecords, uint256 _actionIdOffset, address _owner, address[] memory _managers, bool _addOwnerToManagers ) { _setRegistry(_registry); _setVariableBalanceRecords(_variableBalanceRecords); lastActionId += _actionIdOffset; _initRoles(_owner, _managers, _addOwnerToManagers); } /** * @notice The standard "receive" function * @dev Is payable to allow receiving native token funds from a target swap router */ receive() external payable {} /** * @notice Sets the address of the action settings registry contract * @param _registry The address of the action settings registry contract */ function setRegistry(IRegistry _registry) external onlyManager { _setRegistry(_registry); } /** * @notice Executes a single-chain action * @param _localAction The parameters of the action */ function executeLocal( LocalAction calldata _localAction ) external payable whenNotPaused nonReentrant checkCaller returns (uint256 actionId) { if (_localAction.fromTokenAddress == _localAction.toTokenAddress) { revert SameTokenError(); } // For single-chain swaps of the native token, // the value of the transaction should be equal to the swap amount if ( _localAction.fromTokenAddress == Constants.NATIVE_TOKEN_ADDRESS && msg.value != _localAction.swapInfo.fromAmount ) { revert NativeTokenValueError(); } uint256 initialBalance = address(this).balance - msg.value; lastActionId++; actionId = lastActionId; LocalSettings memory settings = registry.localSettings( msg.sender, _localAction.swapInfo.routerType ); (uint256 processedAmount, ) = _processSource( actionId, true, _localAction.fromTokenAddress, _localAction.toTokenAddress, _localAction.swapInfo, settings.router, settings.routerTransfer ); address recipient = _localAction.recipient == address(0) ? msg.sender : _localAction.recipient; uint256 recipientAmount = _calculateLocalAmount( processedAmount, true, settings.systemFeeLocal, settings.isWhitelist ); if (_localAction.toTokenAddress == Constants.NATIVE_TOKEN_ADDRESS) { TransferHelper.safeTransferNative(recipient, recipientAmount); } else { TransferHelper.safeTransfer(_localAction.toTokenAddress, recipient, recipientAmount); } // - - - System fee transfer - - - uint256 systemFeeAmount = processedAmount - recipientAmount; if (systemFeeAmount > 0) { address feeCollector = settings.feeCollectorLocal; if (feeCollector != address(0)) { if (_localAction.toTokenAddress == Constants.NATIVE_TOKEN_ADDRESS) { TransferHelper.safeTransferNative(feeCollector, systemFeeAmount); } else { TransferHelper.safeTransfer( _localAction.toTokenAddress, feeCollector, systemFeeAmount ); } } else if (_localAction.toTokenAddress == Constants.NATIVE_TOKEN_ADDRESS) { initialBalance += systemFeeAmount; // Keep at the contract address } } // - - - // - - - Extra balance transfer - - - RefundHelper.refundExtraBalance(address(this), initialBalance, payable(msg.sender)); // - - - emit ActionLocal( actionId, msg.sender, recipient, _localAction.fromTokenAddress, _localAction.toTokenAddress, _localAction.swapInfo.fromAmount, recipientAmount, systemFeeAmount, block.timestamp ); } /** * @notice Executes a cross-chain action * @param _action The parameters of the action */ function execute( Action calldata _action ) external payable whenNotPaused nonReentrant checkCaller returns (uint256 actionId) { if (_action.targetChainId == block.chainid) { revert SameChainIdError(); } // For cross-chain swaps of the native token, // the value of the transaction should be greater or equal to the swap amount if ( _action.sourceTokenAddress == Constants.NATIVE_TOKEN_ADDRESS && msg.value < _action.sourceSwapInfo.fromAmount ) { revert NativeTokenValueError(); } uint256 initialBalance = address(this).balance - msg.value; lastActionId++; actionId = lastActionId; SourceSettings memory settings = registry.sourceSettings( msg.sender, _action.targetChainId, _action.gatewayType, _action.sourceSwapInfo.routerType, _action.vaultType ); if (settings.vault == address(0)) { revert VaultNotSetError(); } address vaultAsset = IVault(settings.vault).asset(); (uint256 processedAmount, uint256 nativeTokenSpent) = _processSource( actionId, false, _action.sourceTokenAddress, vaultAsset, _action.sourceSwapInfo, settings.router, settings.routerTransfer ); uint256 targetVaultAmountMax = _calculateVaultAmount( settings.sourceVaultDecimals, settings.targetVaultDecimals, processedAmount, true, settings.systemFee, settings.isWhitelist ); SwapInfo memory targetSwapInfo; uint256 targetOptionsLength = _action.targetSwapInfoOptions.length; if (targetOptionsLength == 0) { targetSwapInfo = SwapInfo({ fromAmount: targetVaultAmountMax, routerType: uint256(0), routerData: new bytes(0) }); } else { for (uint256 index; index < targetOptionsLength; index++) { SwapInfo memory targetSwapInfoOption = _action.targetSwapInfoOptions[index]; if (targetSwapInfoOption.fromAmount <= targetVaultAmountMax) { targetSwapInfo = targetSwapInfoOption; break; } } if (targetSwapInfo.fromAmount == 0) { revert TargetSwapInfoError(); } } uint256 sourceVaultAmount = DecimalsHelper.convertDecimals( settings.targetVaultDecimals, settings.sourceVaultDecimals, targetSwapInfo.fromAmount ); uint256 normalizedAmount = DecimalsHelper.convertDecimals( settings.sourceVaultDecimals, Constants.DECIMALS_DEFAULT, sourceVaultAmount ); if (!settings.isWhitelist) { _checkSwapAmountLimits( normalizedAmount, settings.swapAmountMin, settings.swapAmountMax ); } // - - - Transfer to vault - - - TransferHelper.safeTransfer(vaultAsset, settings.vault, sourceVaultAmount); // - - - bytes memory targetMessageData = abi.encode( TargetMessage({ actionId: actionId, sourceSender: msg.sender, vaultType: _action.vaultType, targetTokenAddress: _action.targetTokenAddress, targetSwapInfo: targetSwapInfo, targetRecipient: _action.targetRecipient == address(0) ? msg.sender : _action.targetRecipient }) ); _sendMessage(settings, _action, targetMessageData, msg.value - nativeTokenSpent); // - - - System fee transfer - - - uint256 systemFeeAmount = processedAmount - sourceVaultAmount; if (systemFeeAmount > 0 && settings.feeCollector != address(0)) { TransferHelper.safeTransfer(vaultAsset, settings.feeCollector, systemFeeAmount); } // - - - // - - - Extra balance transfer - - - RefundHelper.refundExtraBalance(address(this), initialBalance, payable(msg.sender)); // - - - _emitActionSourceEvent( actionId, _action, normalizedAmount, DecimalsHelper.convertDecimals( settings.sourceVaultDecimals, Constants.DECIMALS_DEFAULT, systemFeeAmount ) ); } /** * @notice Variable token claim by user's variable balance * @param _vaultType The type of the variable balance vault */ function claimVariableToken( uint256 _vaultType ) external whenNotPaused nonReentrant checkCaller { _processVariableBalanceRepayment(_vaultType, false); } /** * @notice Vault asset claim by user's variable balance * @param _vaultType The type of the variable balance vault */ function convertVariableBalanceToVaultAsset( uint256 _vaultType ) external whenNotPaused nonReentrant checkCaller { _processVariableBalanceRepayment(_vaultType, true); } /** * @notice Cross-chain message fee estimation * @param _gatewayType The type of the cross-chain gateway * @param _targetChainId The ID of the target chain * @param _targetRouterDataOptions The array of transaction data options for the target chain * @param _gatewaySettings The settings specific to the selected cross-chain gateway */ function messageFeeEstimate( uint256 _gatewayType, uint256 _targetChainId, bytes[] calldata _targetRouterDataOptions, bytes calldata _gatewaySettings ) external view returns (uint256) { if (_targetChainId == block.chainid) { return 0; } MessageFeeEstimateSettings memory settings = registry.messageFeeEstimateSettings( _gatewayType ); if (settings.gateway == address(0)) { revert GatewayNotSetError(); } uint256 result = 0; if (_targetRouterDataOptions.length == 0) { result = IGateway(settings.gateway).messageFee( _targetChainId, _blankMessage(new bytes(0)), _gatewaySettings ); } else { for (uint256 index; index < _targetRouterDataOptions.length; index++) { bytes memory messageData = _blankMessage(_targetRouterDataOptions[index]); uint256 value = IGateway(settings.gateway).messageFee( _targetChainId, messageData, _gatewaySettings ); if (value > result) { result = value; } } } return result; } /** * @notice Swap result amount for single-chain actions, taking the system fee into account * @param _fromAmount The amount before the calculation * @param _isForward The direction of the calculation */ function calculateLocalAmount( uint256 _fromAmount, bool _isForward ) external view returns (uint256 result) { LocalAmountCalculationSettings memory settings = registry.localAmountCalculationSettings( msg.sender ); return _calculateLocalAmount( _fromAmount, _isForward, settings.systemFeeLocal, settings.isWhitelist ); } /** * @notice Swap result amount for cross-chain actions, taking the system fee into account * @param _vaultType The type of the vault * @param _fromChainId The ID of the source chain * @param _toChainId The ID of the target chain * @param _fromAmount The amount before the calculation * @param _isForward The direction of the calculation */ function calculateVaultAmount( uint256 _vaultType, uint256 _fromChainId, uint256 _toChainId, uint256 _fromAmount, bool _isForward ) external view returns (uint256 result) { VaultAmountCalculationSettings memory settings = registry.vaultAmountCalculationSettings( msg.sender, _vaultType, _fromChainId, _toChainId ); return _calculateVaultAmount( settings.fromDecimals, settings.toDecimals, _fromAmount, _isForward, settings.systemFee, settings.isWhitelist ); } /** * @notice The variable balance of the account * @param _account The address of the variable balance owner * @param _vaultType The type of the vault */ function variableBalance(address _account, uint256 _vaultType) external view returns (uint256) { return variableBalanceRecords.getAccountBalance(_account, _vaultType); } /** * @notice Cross-chain message handler on the target chain * @dev The function is called by cross-chain gateways * @param _messageSourceChainId The ID of the message source chain * @param _payloadData The content of the cross-chain message */ function handleExecutionPayload( uint256 _messageSourceChainId, bytes calldata _payloadData ) external whenNotPaused onlyGateway { TargetMessage memory targetMessage = abi.decode(_payloadData, (TargetMessage)); TargetSettings memory settings = registry.targetSettings( targetMessage.vaultType, targetMessage.targetSwapInfo.routerType ); bool selfCallSuccess; (bool hasGasReserve, uint256 gasAllowed) = GasReserveHelper.checkGasReserve( settings.gasReserve ); if (hasGasReserve) { try this.selfCallTarget{ gas: gasAllowed }(settings, targetMessage) { selfCallSuccess = true; } catch {} } if (!selfCallSuccess) { _targetAllocateVariableBalance(targetMessage); } emit ActionTarget( targetMessage.actionId, _messageSourceChainId, selfCallSuccess, block.timestamp ); } /** * @notice Controllable processing of the target chain logic * @dev Is called by the current contract to enable error handling * @param _settings Target action settings * @param _targetMessage The content of the cross-chain message */ function selfCallTarget( TargetSettings calldata _settings, TargetMessage calldata _targetMessage ) external onlySelf { if (_settings.vault == address(0)) { revert VaultNotSetError(); } // - - - Transfer from vault - - - address assetAddress = IVault(_settings.vault).requestAsset( _targetMessage.targetSwapInfo.fromAmount, address(this), false ); // - - - _processTarget( _settings, _targetMessage.actionId, assetAddress, _targetMessage.targetTokenAddress, _targetMessage.targetSwapInfo, _targetMessage.targetRecipient ); } function _processSource( uint256 _actionId, bool _isLocal, address _fromTokenAddress, address _toTokenAddress, SwapInfo memory _sourceSwapInfo, address _routerAddress, address _routerTransferAddress ) private returns (uint256 resultAmount, uint256 nativeTokenSpent) { uint256 toTokenBalanceBefore = tokenBalance(_toTokenAddress); if (_fromTokenAddress == Constants.NATIVE_TOKEN_ADDRESS) { if (_routerAddress == address(0)) { revert RouterNotSetError(); } // - - - Source swap (native token) - - - (bool routerCallSuccess, ) = payable(_routerAddress).call{ value: _sourceSwapInfo.fromAmount }(_sourceSwapInfo.routerData); if (!routerCallSuccess) { revert SwapError(); } // - - - nativeTokenSpent = _sourceSwapInfo.fromAmount; } else { TransferHelper.safeTransferFrom( _fromTokenAddress, msg.sender, address(this), _sourceSwapInfo.fromAmount ); if (_fromTokenAddress != _toTokenAddress) { if (_routerAddress == address(0)) { revert RouterNotSetError(); } // - - - Source swap (non-native token) - - - TransferHelper.safeApprove( _fromTokenAddress, _routerTransferAddress, _sourceSwapInfo.fromAmount ); (bool routerCallSuccess, ) = _routerAddress.call(_sourceSwapInfo.routerData); if (!routerCallSuccess) { revert SwapError(); } TransferHelper.safeApprove(_fromTokenAddress, _routerTransferAddress, 0); // - - - } nativeTokenSpent = 0; } resultAmount = tokenBalance(_toTokenAddress) - toTokenBalanceBefore; emit SourceProcessed( _actionId, _isLocal, msg.sender, _sourceSwapInfo.routerType, _fromTokenAddress, _toTokenAddress, _sourceSwapInfo.fromAmount, resultAmount ); } function _processTarget( TargetSettings memory settings, uint256 _actionId, address _fromTokenAddress, address _toTokenAddress, SwapInfo memory _targetSwapInfo, address _targetRecipient ) private { uint256 resultAmount; if (_toTokenAddress == _fromTokenAddress) { resultAmount = _targetSwapInfo.fromAmount; } else { if (settings.router == address(0)) { revert RouterNotSetError(); } uint256 toTokenBalanceBefore = tokenBalance(_toTokenAddress); // - - - Target swap - - - TransferHelper.safeApprove( _fromTokenAddress, settings.routerTransfer, _targetSwapInfo.fromAmount ); (bool success, ) = settings.router.call(_targetSwapInfo.routerData); if (!success) { revert SwapError(); } TransferHelper.safeApprove(_fromTokenAddress, settings.routerTransfer, 0); // - - - resultAmount = tokenBalance(_toTokenAddress) - toTokenBalanceBefore; } if (_toTokenAddress == Constants.NATIVE_TOKEN_ADDRESS) { TransferHelper.safeTransferNative(_targetRecipient, resultAmount); } else { TransferHelper.safeTransfer(_toTokenAddress, _targetRecipient, resultAmount); } emit TargetProcessed( _actionId, _targetRecipient, _targetSwapInfo.routerType, _fromTokenAddress, _toTokenAddress, _targetSwapInfo.fromAmount, resultAmount ); } function _targetAllocateVariableBalance(TargetMessage memory _targetMessage) private { address tokenRecipient = _targetMessage.targetRecipient; uint256 vaultType = _targetMessage.vaultType; uint256 tokenAmount = _targetMessage.targetSwapInfo.fromAmount; variableBalanceRecords.increaseBalance(tokenRecipient, vaultType, tokenAmount); emit VariableBalanceAllocated( _targetMessage.actionId, tokenRecipient, vaultType, tokenAmount ); } function _processVariableBalanceRepayment( uint256 _vaultType, bool _convertToVaultAsset ) private { VariableBalanceRepaymentSettings memory settings = registry .variableBalanceRepaymentSettings(_vaultType); if (settings.vault == address(0)) { revert VaultNotSetError(); } uint256 tokenAmount = variableBalanceRecords.getAccountBalance(msg.sender, _vaultType); variableBalanceRecords.clearBalance(msg.sender, _vaultType); if (tokenAmount > 0) { if (_convertToVaultAsset) { IVault(settings.vault).requestAsset(tokenAmount, msg.sender, true); } else { address variableTokenAddress = IVault(settings.vault).checkVariableTokenState(); bool mintSuccess = ITokenMint(variableTokenAddress).mint(msg.sender, tokenAmount); if (!mintSuccess) { revert TokenMintError(); } } } } function _setRegistry(IRegistry _registry) private { AddressHelper.requireContract(address(_registry)); registry = _registry; emit SetRegistry(address(_registry)); } function _setVariableBalanceRecords(IVariableBalanceRecords _variableBalanceRecords) private { AddressHelper.requireContract(address(_variableBalanceRecords)); variableBalanceRecords = _variableBalanceRecords; emit SetVariableBalanceRecords(address(_variableBalanceRecords)); } function _sendMessage( SourceSettings memory settings, Action calldata _action, bytes memory _messageData, uint256 _availableValue ) private { if (settings.gateway == address(0)) { revert GatewayNotSetError(); } uint256 messageFee = IGateway(settings.gateway).messageFee( _action.targetChainId, _messageData, _action.gatewaySettings ); if (_availableValue < messageFee) { revert MessageFeeError(); } IGateway(settings.gateway).sendMessage{ value: messageFee }( _action.targetChainId, _messageData, _action.gatewaySettings ); } function _emitActionSourceEvent( uint256 _actionId, Action calldata _action, uint256 _amount, uint256 _fee ) private { emit ActionSource( _actionId, _action.targetChainId, msg.sender, _action.targetRecipient, _action.gatewayType, _action.sourceTokenAddress, _action.targetTokenAddress, _amount, _fee, block.timestamp ); } function _checkSwapAmountLimits( uint256 _normalizedAmount, uint256 _swapAmountMin, uint256 _swapAmountMax ) private pure { if (_normalizedAmount < _swapAmountMin) { revert SwapAmountMinError(); } if (_normalizedAmount > _swapAmountMax) { revert SwapAmountMaxError(); } } function _calculateLocalAmount( uint256 _fromAmount, bool _isForward, uint256 _systemFeeLocal, bool _isWhitelist ) private pure returns (uint256 result) { if (_isWhitelist || _systemFeeLocal == 0) { return _fromAmount; } return _isForward ? (_fromAmount * (Constants.MILLIPERCENT_FACTOR - _systemFeeLocal)) / Constants.MILLIPERCENT_FACTOR : (_fromAmount * Constants.MILLIPERCENT_FACTOR) / (Constants.MILLIPERCENT_FACTOR - _systemFeeLocal); } function _calculateVaultAmount( uint256 _fromDecimals, uint256 _toDecimals, uint256 _fromAmount, bool _isForward, uint256 _systemFee, bool _isWhitelist ) private pure returns (uint256 result) { bool isZeroFee = _isWhitelist || _systemFee == 0; uint256 amountToConvert = (!_isForward || isZeroFee) ? _fromAmount : (_fromAmount * (Constants.MILLIPERCENT_FACTOR - _systemFee)) / Constants.MILLIPERCENT_FACTOR; uint256 convertedAmount = DecimalsHelper.convertDecimals( _fromDecimals, _toDecimals, amountToConvert ); result = (_isForward || isZeroFee) ? convertedAmount : (convertedAmount * Constants.MILLIPERCENT_FACTOR) / (Constants.MILLIPERCENT_FACTOR - _systemFee); } function _blankMessage(bytes memory _targetRouterData) private pure returns (bytes memory) { bytes memory messageData = abi.encode( TargetMessage({ actionId: uint256(0), sourceSender: address(0), vaultType: uint256(0), targetTokenAddress: address(0), targetSwapInfo: SwapInfo({ fromAmount: uint256(0), routerType: uint256(0), routerData: _targetRouterData }), targetRecipient: address(0) }) ); return messageData; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { ITokenBalance } from './interfaces/ITokenBalance.sol'; import { ManagerRole } from './roles/ManagerRole.sol'; import './helpers/TransferHelper.sol' as TransferHelper; import './Constants.sol' as Constants; /** * @title BalanceManagement * @notice Base contract for the withdrawal of tokens, except for reserved ones */ abstract contract BalanceManagement is ManagerRole { /** * @notice Emitted when the specified token is reserved */ error ReservedTokenError(); /** * @notice Performs the withdrawal of tokens, except for reserved ones * @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token * @param _tokenAddress The address of the token * @param _tokenAmount The amount of the token */ function cleanup(address _tokenAddress, uint256 _tokenAmount) external onlyManager { if (isReservedToken(_tokenAddress)) { revert ReservedTokenError(); } if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) { TransferHelper.safeTransferNative(msg.sender, _tokenAmount); } else { TransferHelper.safeTransfer(_tokenAddress, msg.sender, _tokenAmount); } } /** * @notice Getter of the token balance of the current contract * @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token * @param _tokenAddress The address of the token * @return The token balance of the current contract */ function tokenBalance(address _tokenAddress) public view returns (uint256) { if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) { return address(this).balance; } else { return ITokenBalance(_tokenAddress).balanceOf(address(this)); } } /** * @notice Getter of the reserved token flag * @dev Override to add reserved token addresses * @param _tokenAddress The address of the token * @return The reserved token flag */ function isReservedToken(address _tokenAddress) public view virtual returns (bool) { // The function returns false by default. // The explicit return statement is omitted to avoid the unused parameter warning. // See https://github.com/ethereum/solidity/issues/5295 } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { IBlast, IERC20Rebasing, YieldMode, GasMode } from './interfaces/IBlast.sol'; import { BlastContracts } from './BlastContracts.sol'; abstract contract BlastConfig is BlastContracts { /** * @dev Modifier to check if the caller is authorized to perform Blast configuration */ modifier onlyBlastConfigAuthorized(bool _initAllowed) { require( (_initAllowed && address(this).code.length == 0) || _isBlastConfigAuthorized(), 'BlastConfig: Unauthorized' ); _; } /** * @notice Blast: claimable assets configuration */ function blastConfigureClaimableAssets() public virtual onlyBlastConfigAuthorized(true) { BLAST.configureClaimableYield(); // The default is YieldMode.VOID BLAST.configureClaimableGas(); // The default is GasMode.VOID USDB.configure(YieldMode.CLAIMABLE); // The default is YieldMode.AUTOMATIC WETH.configure(YieldMode.CLAIMABLE); // The default is YieldMode.AUTOMATIC } /** * @notice Blast: token yield configuration * @param _token Token reference * @param _yieldMode Yield mode */ function blastConfigureTokenYield( IERC20Rebasing _token, YieldMode _yieldMode ) public virtual onlyBlastConfigAuthorized(true) { _token.configure(_yieldMode); } /** * @notice Blast: governor configuration * @param _governor Governor address */ function blastConfigureGovernor( address _governor ) public virtual onlyBlastConfigAuthorized(true) { BLAST.configureGovernor(_governor); } /** * @notice Blast: points operator configuration * @param _pointsOperator Blast points operator address */ function blastConfigurePointsOperator( address _pointsOperator ) public virtual onlyBlastConfigAuthorized(true) { BLAST_POINTS.configurePointsOperator(_pointsOperator); } /** * @notice Blast: token yield claim * @param _token Token reference * @param _recipient Recipient address * @param _amount Token amount */ function blastClaimTokenYield( IERC20Rebasing _token, address _recipient, uint256 _amount ) public virtual onlyBlastConfigAuthorized(false) { _token.claim(_recipient, _amount); } function _isBlastConfigAuthorized() internal virtual returns (bool); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { IBlast, IERC20Rebasing, IBlastPoints } from './interfaces/IBlast.sol'; contract BlastContracts { /** * @dev Blast gas fees and ETH yield contract reference * @dev Gas fees: https://docs.blast.io/building/guides/gas-fees * @dev ETH yield: https://docs.blast.io/building/guides/eth-yield */ IBlast public constant BLAST = IBlast(0x4300000000000000000000000000000000000002); /** * @dev Blast USDB contract reference * @dev See https://docs.blast.io/building/guides/weth-yield */ IERC20Rebasing public constant USDB = IERC20Rebasing(0x4300000000000000000000000000000000000003); /** * @dev Blast WETH contract reference * @dev See https://docs.blast.io/building/guides/weth-yield */ IERC20Rebasing public constant WETH = IERC20Rebasing(0x4300000000000000000000000000000000000004); /** * @dev Blast points contract reference * @dev See https://docs.blast.io/airdrop/api */ IBlastPoints public constant BLAST_POINTS = IBlastPoints(0x2536FE9ab3F511540F2f9e2eC2A805005C3Dd800); }
// SPDX-License-Identifier: BSL 1.1 - Copyright 2024 MetaLayer Labs Ltd. pragma solidity 0.8.19; enum YieldMode { AUTOMATIC, VOID, CLAIMABLE } enum GasMode { VOID, CLAIMABLE } interface IBlast { // configure function configureContract( address contractAddress, YieldMode _yield, GasMode gasMode, address governor ) external; function configure(YieldMode _yield, GasMode gasMode, address governor) external; // base configuration options function configureClaimableYield() external; function configureClaimableYieldOnBehalf(address contractAddress) external; function configureAutomaticYield() external; function configureAutomaticYieldOnBehalf(address contractAddress) external; function configureVoidYield() external; function configureVoidYieldOnBehalf(address contractAddress) external; function configureClaimableGas() external; function configureClaimableGasOnBehalf(address contractAddress) external; function configureVoidGas() external; function configureVoidGasOnBehalf(address contractAddress) external; function configureGovernor(address _governor) external; function configureGovernorOnBehalf(address _newGovernor, address contractAddress) external; // claim yield function claimYield( address contractAddress, address recipientOfYield, uint256 amount ) external returns (uint256); function claimAllYield( address contractAddress, address recipientOfYield ) external returns (uint256); // claim gas function claimAllGas( address contractAddress, address recipientOfGas ) external returns (uint256); function claimGasAtMinClaimRate( address contractAddress, address recipientOfGas, uint256 minClaimRateBips ) external returns (uint256); function claimMaxGas( address contractAddress, address recipientOfGas ) external returns (uint256); function claimGas( address contractAddress, address recipientOfGas, uint256 gasToClaim, uint256 gasSecondsToConsume ) external returns (uint256); // read functions function readClaimableYield(address contractAddress) external view returns (uint256); function readYieldConfiguration(address contractAddress) external view returns (uint8); function readGasParams( address contractAddress ) external view returns (uint256 etherSeconds, uint256 etherBalance, uint256 lastUpdated, GasMode); } interface IERC20Rebasing { // changes the yield mode of the caller and update the balance // to reflect the configuration function configure(YieldMode) external returns (uint256); // "claimable" yield mode accounts can call this this claim their yield // to another address function claim(address recipient, uint256 amount) external returns (uint256); // read the claimable amount for an account function getClaimableAmount(address account) external view returns (uint256); } interface IBlastPoints { function configurePointsOperator(address operator) external; }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { ManagerRole } from './roles/ManagerRole.sol'; import './helpers/AddressHelper.sol' as AddressHelper; import './Constants.sol' as Constants; import './DataStructures.sol' as DataStructures; /** * @title CallerGuard * @notice Base contract to control access from other contracts */ abstract contract CallerGuard is ManagerRole { /** * @dev Caller guard mode enumeration */ enum CallerGuardMode { ContractForbidden, ContractList, ContractAllowed } /** * @dev Caller guard mode value */ CallerGuardMode public callerGuardMode = CallerGuardMode.ContractForbidden; /** * @dev Registered contract list for "ContractList" mode */ address[] public listedCallerGuardContractList; /** * @dev Registered contract list indices for "ContractList" mode */ mapping(address /*account*/ => DataStructures.OptionalValue /*index*/) public listedCallerGuardContractIndexMap; /** * @notice Emitted when the caller guard mode is set * @param callerGuardMode The caller guard mode */ event SetCallerGuardMode(CallerGuardMode indexed callerGuardMode); /** * @notice Emitted when a registered contract for "ContractList" mode is added or removed * @param contractAddress The contract address * @param isListed The registered contract list inclusion flag */ event SetListedCallerGuardContract(address indexed contractAddress, bool indexed isListed); /** * @notice Emitted when the caller is not allowed to perform the intended action */ error CallerGuardError(address caller); /** * @dev Modifier to check if the caller is allowed to perform the intended action */ modifier checkCaller() { if (msg.sender != tx.origin) { bool condition = (callerGuardMode == CallerGuardMode.ContractAllowed || (callerGuardMode == CallerGuardMode.ContractList && isListedCallerGuardContract(msg.sender))); if (!condition) { revert CallerGuardError(msg.sender); } } _; } /** * @notice Sets the caller guard mode * @param _callerGuardMode The caller guard mode */ function setCallerGuardMode(CallerGuardMode _callerGuardMode) external onlyManager { callerGuardMode = _callerGuardMode; emit SetCallerGuardMode(_callerGuardMode); } /** * @notice Updates the list of registered contracts for the "ContractList" mode * @param _items The addresses and flags for the contracts */ function setListedCallerGuardContracts( DataStructures.AccountToFlag[] calldata _items ) external onlyManager { for (uint256 index; index < _items.length; index++) { DataStructures.AccountToFlag calldata item = _items[index]; if (item.flag) { AddressHelper.requireContract(item.account); } DataStructures.uniqueAddressListUpdate( listedCallerGuardContractList, listedCallerGuardContractIndexMap, item.account, item.flag, Constants.LIST_SIZE_LIMIT_DEFAULT ); emit SetListedCallerGuardContract(item.account, item.flag); } } /** * @notice Getter of the registered contract count * @return The registered contract count */ function listedCallerGuardContractCount() external view returns (uint256) { return listedCallerGuardContractList.length; } /** * @notice Getter of the complete list of registered contracts * @return The complete list of registered contracts */ function fullListedCallerGuardContractList() external view returns (address[] memory) { return listedCallerGuardContractList; } /** * @notice Getter of a listed contract flag * @param _account The contract address * @return The listed contract flag */ function isListedCallerGuardContract(address _account) public view returns (bool) { return listedCallerGuardContractIndexMap[_account].isSet; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @dev The default token decimals value */ uint256 constant DECIMALS_DEFAULT = 18; /** * @dev The maximum uint256 value for swap amount limit settings */ uint256 constant INFINITY = type(uint256).max; /** * @dev The default limit of account list size */ uint256 constant LIST_SIZE_LIMIT_DEFAULT = 100; /** * @dev The limit of swap router list size */ uint256 constant LIST_SIZE_LIMIT_ROUTERS = 200; /** * @dev The factor for percentage settings. Example: 100 is 0.1% */ uint256 constant MILLIPERCENT_FACTOR = 100_000; /** * @dev The de facto standard address to denote the native token */ address constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @title IGateway * @notice Cross-chain gateway interface */ interface IGateway { /** * @notice Send a cross-chain message * @param _targetChainId The message target chain ID * @param _message The message content * @param _settings The gateway-specific settings */ function sendMessage( uint256 _targetChainId, bytes calldata _message, bytes calldata _settings ) external payable; /** * @notice Cross-chain message fee estimation * @param _targetChainId The ID of the target chain * @param _message The message content * @param _settings The gateway-specific settings */ function messageFee( uint256 _targetChainId, bytes calldata _message, bytes calldata _settings ) external view returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @title IGatewayClient * @notice Cross-chain gateway client interface */ interface IGatewayClient { /** * @notice Cross-chain message handler on the target chain * @dev The function is called by cross-chain gateways * @param _messageSourceChainId The ID of the message source chain * @param _payloadData The content of the cross-chain message */ function handleExecutionPayload( uint256 _messageSourceChainId, bytes calldata _payloadData ) external; /** * @notice The standard "receive" function */ receive() external payable; }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @notice Optional value structure * @dev Is used in mappings to allow zero values * @param isSet Value presence flag * @param value Numeric value */ struct OptionalValue { bool isSet; uint256 value; } /** * @notice Key-to-value structure * @dev Is used as an array parameter item to perform multiple key-value settings * @param key Numeric key * @param value Numeric value */ struct KeyToValue { uint256 key; uint256 value; } /** * @notice Key-to-value structure for address values * @dev Is used as an array parameter item to perform multiple key-value settings with address values * @param key Numeric key * @param value Address value */ struct KeyToAddressValue { uint256 key; address value; } /** * @notice Address-to-flag structure * @dev Is used as an array parameter item to perform multiple settings * @param account Account address * @param flag Flag value */ struct AccountToFlag { address account; bool flag; } /** * @notice Emitted when a list exceeds the size limit */ error ListSizeLimitError(); /** * @notice Sets or updates a value in a combined map (a mapping with a key list and key index mapping) * @param _map The mapping reference * @param _keyList The key list reference * @param _keyIndexMap The key list index mapping reference * @param _key The numeric key * @param _value The address value * @param _sizeLimit The map and list size limit * @return isNewKey True if the key was just added, otherwise false */ function combinedMapSet( mapping(uint256 => address) storage _map, uint256[] storage _keyList, mapping(uint256 => OptionalValue) storage _keyIndexMap, uint256 _key, address _value, uint256 _sizeLimit ) returns (bool isNewKey) { isNewKey = !_keyIndexMap[_key].isSet; if (isNewKey) { uniqueListAdd(_keyList, _keyIndexMap, _key, _sizeLimit); } _map[_key] = _value; } /** * @notice Removes a value from a combined map (a mapping with a key list and key index mapping) * @param _map The mapping reference * @param _keyList The key list reference * @param _keyIndexMap The key list index mapping reference * @param _key The numeric key * @return isChanged True if the combined map was changed, otherwise false */ function combinedMapRemove( mapping(uint256 => address) storage _map, uint256[] storage _keyList, mapping(uint256 => OptionalValue) storage _keyIndexMap, uint256 _key ) returns (bool isChanged) { isChanged = _keyIndexMap[_key].isSet; if (isChanged) { delete _map[_key]; uniqueListRemove(_keyList, _keyIndexMap, _key); } } /** * @notice Adds a value to a unique value list (a list with value index mapping) * @param _list The list reference * @param _indexMap The value index mapping reference * @param _value The numeric value * @param _sizeLimit The list size limit * @return isChanged True if the list was changed, otherwise false */ function uniqueListAdd( uint256[] storage _list, mapping(uint256 => OptionalValue) storage _indexMap, uint256 _value, uint256 _sizeLimit ) returns (bool isChanged) { isChanged = !_indexMap[_value].isSet; if (isChanged) { if (_list.length >= _sizeLimit) { revert ListSizeLimitError(); } _indexMap[_value] = OptionalValue(true, _list.length); _list.push(_value); } } /** * @notice Removes a value from a unique value list (a list with value index mapping) * @param _list The list reference * @param _indexMap The value index mapping reference * @param _value The numeric value * @return isChanged True if the list was changed, otherwise false */ function uniqueListRemove( uint256[] storage _list, mapping(uint256 => OptionalValue) storage _indexMap, uint256 _value ) returns (bool isChanged) { OptionalValue storage indexItem = _indexMap[_value]; isChanged = indexItem.isSet; if (isChanged) { uint256 itemIndex = indexItem.value; uint256 lastIndex = _list.length - 1; if (itemIndex != lastIndex) { uint256 lastValue = _list[lastIndex]; _list[itemIndex] = lastValue; _indexMap[lastValue].value = itemIndex; } _list.pop(); delete _indexMap[_value]; } } /** * @notice Adds a value to a unique address value list (a list with value index mapping) * @param _list The list reference * @param _indexMap The value index mapping reference * @param _value The address value * @param _sizeLimit The list size limit * @return isChanged True if the list was changed, otherwise false */ function uniqueAddressListAdd( address[] storage _list, mapping(address => OptionalValue) storage _indexMap, address _value, uint256 _sizeLimit ) returns (bool isChanged) { isChanged = !_indexMap[_value].isSet; if (isChanged) { if (_list.length >= _sizeLimit) { revert ListSizeLimitError(); } _indexMap[_value] = OptionalValue(true, _list.length); _list.push(_value); } } /** * @notice Removes a value from a unique address value list (a list with value index mapping) * @param _list The list reference * @param _indexMap The value index mapping reference * @param _value The address value * @return isChanged True if the list was changed, otherwise false */ function uniqueAddressListRemove( address[] storage _list, mapping(address => OptionalValue) storage _indexMap, address _value ) returns (bool isChanged) { OptionalValue storage indexItem = _indexMap[_value]; isChanged = indexItem.isSet; if (isChanged) { uint256 itemIndex = indexItem.value; uint256 lastIndex = _list.length - 1; if (itemIndex != lastIndex) { address lastValue = _list[lastIndex]; _list[itemIndex] = lastValue; _indexMap[lastValue].value = itemIndex; } _list.pop(); delete _indexMap[_value]; } } /** * @notice Adds or removes a value to/from a unique address value list (a list with value index mapping) * @dev The list size limit is checked on items adding only * @param _list The list reference * @param _indexMap The value index mapping reference * @param _value The address value * @param _flag The value inclusion flag * @param _sizeLimit The list size limit * @return isChanged True if the list was changed, otherwise false */ function uniqueAddressListUpdate( address[] storage _list, mapping(address => OptionalValue) storage _indexMap, address _value, bool _flag, uint256 _sizeLimit ) returns (bool isChanged) { return _flag ? uniqueAddressListAdd(_list, _indexMap, _value, _sizeLimit) : uniqueAddressListRemove(_list, _indexMap, _value); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @notice Emitted when an attempt to burn a token fails */ error TokenBurnError(); /** * @notice Emitted when an attempt to mint a token fails */ error TokenMintError(); /** * @notice Emitted when a zero address is specified where it is not allowed */ error ZeroAddressError();
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @notice Emitted when the account is not a contract * @param account The account address */ error NonContractAddressError(address account); /** * @notice Function to check if the account is a contract * @return The account contract status flag */ function isContract(address _account) view returns (bool) { return _account.code.length > 0; } /** * @notice Function to require an account to be a contract */ function requireContract(address _account) view { if (!isContract(_account)) { revert NonContractAddressError(_account); } } /** * @notice Function to require an account to be a contract or a zero address */ function requireContractOrZeroAddress(address _account) view { if (_account != address(0)) { requireContract(_account); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @notice Function to perform decimals conversion * @param _fromDecimals Source value decimals * @param _toDecimals Target value decimals * @param _fromAmount Source value * @return Target value */ function convertDecimals( uint256 _fromDecimals, uint256 _toDecimals, uint256 _fromAmount ) pure returns (uint256) { if (_toDecimals == _fromDecimals) { return _fromAmount; } else if (_toDecimals > _fromDecimals) { return _fromAmount * 10 ** (_toDecimals - _fromDecimals); } else { return _fromAmount / 10 ** (_fromDecimals - _toDecimals); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @notice Function to check if the available gas matches the specified gas reserve value * @param _gasReserve Gas reserve value * @return hasGasReserve Flag of gas reserve availability * @return gasAllowed The remaining gas quantity taking the reserve into account */ function checkGasReserve( uint256 _gasReserve ) view returns (bool hasGasReserve, uint256 gasAllowed) { uint256 gasLeft = gasleft(); hasGasReserve = gasLeft >= _gasReserve; gasAllowed = hasGasReserve ? gasLeft - _gasReserve : 0; }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import './TransferHelper.sol' as TransferHelper; /** * @notice Refunds the extra balance of the native token * @dev Reverts on subtraction if the actual balance is less than expected * @param _self The address of the executing contract * @param _expectedBalance The expected native token balance value * @param _to The refund receiver's address */ function refundExtraBalance(address _self, uint256 _expectedBalance, address payable _to) { uint256 extraBalance = _self.balance - _expectedBalance; if (extraBalance > 0) { TransferHelper.safeTransferNative(_to, extraBalance); } } /** * @notice Refunds the extra balance of the native token * @dev Reverts on subtraction if the actual balance is less than expected * @param _self The address of the executing contract * @param _expectedBalance The expected native token balance value * @param _to The refund receiver's address * @return extraBalance The extra balance of the native token */ function refundExtraBalanceWithResult( address _self, uint256 _expectedBalance, address payable _to ) returns (uint256 extraBalance) { extraBalance = _self.balance - _expectedBalance; if (extraBalance > 0) { TransferHelper.safeTransferNative(_to, extraBalance); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @notice Emitted when an approval action fails */ error SafeApproveError(); /** * @notice Emitted when a transfer action fails */ error SafeTransferError(); /** * @notice Emitted when a transferFrom action fails */ error SafeTransferFromError(); /** * @notice Emitted when a transfer of the native token fails */ error SafeTransferNativeError(); /** * @notice Safely approve the token to the account * @param _token The token address * @param _to The token approval recipient address * @param _value The token approval amount */ function safeApprove(address _token, address _to, uint256 _value) { // 0x095ea7b3 is the selector for "approve(address,uint256)" (bool success, bytes memory data) = _token.call( abi.encodeWithSelector(0x095ea7b3, _to, _value) ); bool condition = success && (data.length == 0 || abi.decode(data, (bool))); if (!condition) { revert SafeApproveError(); } } /** * @notice Safely transfer the token to the account * @param _token The token address * @param _to The token transfer recipient address * @param _value The token transfer amount */ function safeTransfer(address _token, address _to, uint256 _value) { // 0xa9059cbb is the selector for "transfer(address,uint256)" (bool success, bytes memory data) = _token.call( abi.encodeWithSelector(0xa9059cbb, _to, _value) ); bool condition = success && (data.length == 0 || abi.decode(data, (bool))); if (!condition) { revert SafeTransferError(); } } /** * @notice Safely transfer the token between the accounts * @param _token The token address * @param _from The token transfer source address * @param _to The token transfer recipient address * @param _value The token transfer amount */ function safeTransferFrom(address _token, address _from, address _to, uint256 _value) { // 0x23b872dd is the selector for "transferFrom(address,address,uint256)" (bool success, bytes memory data) = _token.call( abi.encodeWithSelector(0x23b872dd, _from, _to, _value) ); bool condition = success && (data.length == 0 || abi.decode(data, (bool))); if (!condition) { revert SafeTransferFromError(); } } /** * @notice Safely transfer the native token to the account * @param _to The native token transfer recipient address * @param _value The native token transfer amount */ function safeTransferNative(address _to, uint256 _value) { (bool success, ) = _to.call{ value: _value }(new bytes(0)); if (!success) { revert SafeTransferNativeError(); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @title IActionDataStructures * @notice Action data structure declarations */ interface IActionDataStructures { /** * @notice Single-chain action data structure * @param fromTokenAddress The address of the input token * @param toTokenAddress The address of the output token * @param swapInfo The data for the single-chain swap * @param recipient The address of the recipient */ struct LocalAction { address fromTokenAddress; address toTokenAddress; SwapInfo swapInfo; address recipient; } /** * @notice Cross-chain action data structure * @param gatewayType The numeric type of the cross-chain gateway * @param vaultType The numeric type of the vault * @param sourceTokenAddress The address of the input token on the source chain * @param sourceSwapInfo The data for the source chain swap * @param targetChainId The action target chain ID * @param targetTokenAddress The address of the output token on the destination chain * @param targetSwapInfoOptions The list of data options for the target chain swap * @param targetRecipient The address of the recipient on the target chain * @param gatewaySettings The gateway-specific settings data */ struct Action { uint256 gatewayType; uint256 vaultType; address sourceTokenAddress; SwapInfo sourceSwapInfo; uint256 targetChainId; address targetTokenAddress; SwapInfo[] targetSwapInfoOptions; address targetRecipient; bytes gatewaySettings; } /** * @notice Token swap data structure * @param fromAmount The quantity of the token * @param routerType The numeric type of the swap router * @param routerData The data for the swap router call */ struct SwapInfo { uint256 fromAmount; uint256 routerType; bytes routerData; } /** * @notice Cross-chain message data structure * @param actionId The unique identifier of the cross-chain action * @param sourceSender The address of the sender on the source chain * @param vaultType The numeric type of the vault * @param targetTokenAddress The address of the output token on the target chain * @param targetSwapInfo The data for the target chain swap * @param targetRecipient The address of the recipient on the target chain */ struct TargetMessage { uint256 actionId; address sourceSender; uint256 vaultType; address targetTokenAddress; SwapInfo targetSwapInfo; address targetRecipient; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { ISettings } from './ISettings.sol'; interface IRegistry is ISettings { /** * @notice Getter of the registered gateway flag by the account address * @param _account The account address * @return The registered gateway flag */ function isGatewayAddress(address _account) external view returns (bool); /** * @notice Settings for a single-chain swap * @param _caller The user's account address * @param _routerType The type of the swap router * @return Settings for a single-chain swap */ function localSettings( address _caller, uint256 _routerType ) external view returns (LocalSettings memory); /** * @notice Getter of source chain settings for a cross-chain swap * @param _caller The user's account address * @param _targetChainId The target chain ID * @param _gatewayType The type of the cross-chain gateway * @param _routerType The type of the swap router * @param _vaultType The type of the vault * @return Source chain settings for a cross-chain swap */ function sourceSettings( address _caller, uint256 _targetChainId, uint256 _gatewayType, uint256 _routerType, uint256 _vaultType ) external view returns (SourceSettings memory); /** * @notice Getter of target chain settings for a cross-chain swap * @param _vaultType The type of the vault * @param _routerType The type of the swap router * @return Target chain settings for a cross-chain swap */ function targetSettings( uint256 _vaultType, uint256 _routerType ) external view returns (TargetSettings memory); /** * @notice Getter of variable balance repayment settings * @param _vaultType The type of the vault * @return Variable balance repayment settings */ function variableBalanceRepaymentSettings( uint256 _vaultType ) external view returns (VariableBalanceRepaymentSettings memory); /** * @notice Getter of cross-chain message fee estimation settings * @param _gatewayType The type of the cross-chain gateway * @return Cross-chain message fee estimation settings */ function messageFeeEstimateSettings( uint256 _gatewayType ) external view returns (MessageFeeEstimateSettings memory); /** * @notice Getter of swap result calculation settings for a single-chain swap * @param _caller The user's account address * @return Swap result calculation settings for a single-chain swap */ function localAmountCalculationSettings( address _caller ) external view returns (LocalAmountCalculationSettings memory); /** * @notice Getter of swap result calculation settings for a cross-chain swap * @param _caller The user's account address * @param _vaultType The type of the vault * @param _fromChainId The ID of the swap source chain * @param _toChainId The ID of the swap target chain * @return Swap result calculation settings for a cross-chain swap */ function vaultAmountCalculationSettings( address _caller, uint256 _vaultType, uint256 _fromChainId, uint256 _toChainId ) external view returns (VaultAmountCalculationSettings memory); /** * @notice Getter of amount limits in USD for cross-chain swaps * @param _vaultType The type of the vault * @return min Minimum cross-chain swap amount in USD, with decimals = 18 * @return max Maximum cross-chain swap amount in USD, with decimals = 18 */ function swapAmountLimits(uint256 _vaultType) external view returns (uint256 min, uint256 max); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @title ISettings * @notice Settings data structure declarations */ interface ISettings { /** * @notice Settings for a single-chain swap * @param router The swap router contract address * @param routerTransfer The swap router transfer contract address * @param systemFeeLocal The system fee value in milli-percent, e.g., 100 is 0.1% * @param feeCollectorLocal The address of the single-chain action fee collector * @param isWhitelist The whitelist flag */ struct LocalSettings { address router; address routerTransfer; uint256 systemFeeLocal; address feeCollectorLocal; bool isWhitelist; } /** * @notice Source chain settings for a cross-chain swap * @param gateway The cross-chain gateway contract address * @param router The swap router contract address * @param routerTransfer The swap router transfer contract address * @param vault The vault contract address * @param sourceVaultDecimals The value of the vault decimals on the source chain * @param targetVaultDecimals The value of the vault decimals on the target chain * @param systemFee The system fee value in milli-percent, e.g., 100 is 0.1% * @param feeCollector The address of the cross-chain action fee collector * @param isWhitelist The whitelist flag * @param swapAmountMin The minimum cross-chain swap amount in USD, with decimals = 18 * @param swapAmountMax The maximum cross-chain swap amount in USD, with decimals = 18 */ struct SourceSettings { address gateway; address router; address routerTransfer; address vault; uint256 sourceVaultDecimals; uint256 targetVaultDecimals; uint256 systemFee; address feeCollector; bool isWhitelist; uint256 swapAmountMin; uint256 swapAmountMax; } /** * @notice Target chain settings for a cross-chain swap * @param router The swap router contract address * @param routerTransfer The swap router transfer contract address * @param vault The vault contract address * @param gasReserve The target chain gas reserve value */ struct TargetSettings { address router; address routerTransfer; address vault; uint256 gasReserve; } /** * @notice Variable balance repayment settings * @param vault The vault contract address */ struct VariableBalanceRepaymentSettings { address vault; } /** * @notice Cross-chain message fee estimation settings * @param gateway The cross-chain gateway contract address */ struct MessageFeeEstimateSettings { address gateway; } /** * @notice Swap result calculation settings for a single-chain swap * @param systemFee The system fee value in milli-percent, e.g., 100 is 0.1% * @param isWhitelist The whitelist flag */ struct LocalAmountCalculationSettings { uint256 systemFeeLocal; bool isWhitelist; } /** * @notice Swap result calculation settings for a cross-chain swap * @param fromDecimals The value of the vault decimals on the source chain * @param toDecimals The value of the vault decimals on the target chain * @param systemFee The system fee value in milli-percent, e.g., 100 is 0.1% * @param isWhitelist The whitelist flag */ struct VaultAmountCalculationSettings { uint256 fromDecimals; uint256 toDecimals; uint256 systemFee; bool isWhitelist; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @title ITokenBalance * @notice Token balance interface */ interface ITokenBalance { /** * @notice Getter of the token balance by the account * @param _account The account address * @return Token balance */ function balanceOf(address _account) external view returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @title ITokenMint * @notice Token minting interface */ interface ITokenMint { /** * @notice Mints tokens to the account, increasing the total supply * @param _to The token receiver account address * @param _amount The number of tokens to mint * @return Token burning success status */ function mint(address _to, uint256 _amount) external returns (bool); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @title IVariableBalanceRecords * @notice Variable balance records interface */ interface IVariableBalanceRecords { /** * @notice Increases the variable balance for the account * @param _account The account address * @param _vaultType The vault type * @param _amount The amount by which to increase the variable balance */ function increaseBalance(address _account, uint256 _vaultType, uint256 _amount) external; /** * @notice Clears the variable balance for the account * @param _account The account address * @param _vaultType The vault type */ function clearBalance(address _account, uint256 _vaultType) external; /** * @notice Getter of the variable balance by the account * @param _account The account address * @param _vaultType The vault type */ function getAccountBalance( address _account, uint256 _vaultType ) external view returns (uint256); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @title IVault * @notice Vault interface */ interface IVault { /** * @notice The getter of the vault asset address */ function asset() external view returns (address); /** * @notice Checks the status of the variable token and balance actions and the variable token address * @return The address of the variable token */ function checkVariableTokenState() external view returns (address); /** * @notice Requests the vault asset tokens * @param _amount The amount of the vault asset tokens * @param _to The address of the vault asset tokens receiver * @param _forVariableBalance True if the request is made for a variable balance repayment, otherwise false * @return assetAddress The address of the vault asset token */ function requestAsset( uint256 _amount, address _to, bool _forVariableBalance ) external returns (address assetAddress); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { Pausable as PausableBase } from '@openzeppelin/contracts/security/Pausable.sol'; import { ManagerRole } from './roles/ManagerRole.sol'; /** * @title Pausable * @notice Base contract that implements the emergency pause mechanism */ abstract contract Pausable is PausableBase, ManagerRole { /** * @notice Enter pause state */ function pause() external onlyManager whenNotPaused { _pause(); } /** * @notice Exit pause state */ function unpause() external onlyManager whenPaused { _unpause(); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import { Ownable } from '@openzeppelin/contracts/access/Ownable.sol'; import { RoleBearers } from './RoleBearers.sol'; /** * @title ManagerRole * @notice Base contract that implements the Manager role. * The manager role is a high-permission role for core team members only. * Managers can set vaults and routers addresses, fees, cross-chain protocols, * and other parameters for Interchain (cross-chain) swaps and single-network swaps. * Please note, the manager role is unique for every contract, * hence different addresses may be assigned as managers for different contracts. */ abstract contract ManagerRole is Ownable, RoleBearers { bytes32 private constant ROLE_KEY = keccak256('Manager'); /** * @notice Emitted when the Manager role status for the account is updated * @param account The account address * @param value The Manager role status flag */ event SetManager(address indexed account, bool indexed value); /** * @notice Emitted when the Manager role status for the account is renounced * @param account The account address */ event RenounceManagerRole(address indexed account); /** * @notice Emitted when the caller is not a Manager role bearer */ error OnlyManagerError(); /** * @dev Modifier to check if the caller is a Manager role bearer */ modifier onlyManager() { if (!isManager(msg.sender)) { revert OnlyManagerError(); } _; } /** * @notice Updates the Manager role status for the account * @param _account The account address * @param _value The Manager role status flag */ function setManager(address _account, bool _value) public onlyOwner { _setRoleBearer(ROLE_KEY, _account, _value); emit SetManager(_account, _value); } /** * @notice Renounces the Manager role */ function renounceManagerRole() external onlyManager { _setRoleBearer(ROLE_KEY, msg.sender, false); emit RenounceManagerRole(msg.sender); } /** * @notice Getter of the Manager role bearer count * @return The Manager role bearer count */ function managerCount() external view returns (uint256) { return _roleBearerCount(ROLE_KEY); } /** * @notice Getter of the complete list of the Manager role bearers * @return The complete list of the Manager role bearers */ function fullManagerList() external view returns (address[] memory) { return _fullRoleBearerList(ROLE_KEY); } /** * @notice Getter of the Manager role bearer status * @param _account The account address */ function isManager(address _account) public view returns (bool) { return _isRoleBearer(ROLE_KEY, _account); } function _initRoles( address _owner, address[] memory _managers, bool _addOwnerToManagers ) internal { address ownerAddress = _owner == address(0) ? msg.sender : _owner; for (uint256 index; index < _managers.length; index++) { setManager(_managers[index], true); } if (_addOwnerToManagers && !isManager(ownerAddress)) { setManager(ownerAddress, true); } if (ownerAddress != msg.sender) { transferOwnership(ownerAddress); } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; import '../Constants.sol' as Constants; import '../DataStructures.sol' as DataStructures; /** * @title RoleBearers * @notice Base contract that implements role-based access control * @dev A custom implementation providing full role bearer lists */ abstract contract RoleBearers { mapping(bytes32 /*roleKey*/ => address[] /*roleBearers*/) private roleBearerTable; mapping(bytes32 /*roleKey*/ => mapping(address /*account*/ => DataStructures.OptionalValue /*status*/)) private roleBearerIndexTable; function _setRoleBearer(bytes32 _roleKey, address _account, bool _value) internal { DataStructures.uniqueAddressListUpdate( roleBearerTable[_roleKey], roleBearerIndexTable[_roleKey], _account, _value, Constants.LIST_SIZE_LIMIT_DEFAULT ); } function _isRoleBearer(bytes32 _roleKey, address _account) internal view returns (bool) { return roleBearerIndexTable[_roleKey][_account].isSet; } function _roleBearerCount(bytes32 _roleKey) internal view returns (uint256) { return roleBearerTable[_roleKey].length; } function _fullRoleBearerList(bytes32 _roleKey) internal view returns (address[] memory) { return roleBearerTable[_roleKey]; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; /** * @title SystemVersionId * @notice Base contract providing the system version identifier */ abstract contract SystemVersionId { /** * @dev The system version identifier */ uint256 public constant SYSTEM_VERSION_ID = uint256(keccak256('Initial')); }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IRegistry","name":"_registry","type":"address"},{"internalType":"contract IVariableBalanceRecords","name":"_variableBalanceRecords","type":"address"},{"internalType":"uint256","name":"_actionIdOffset","type":"uint256"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address[]","name":"_managers","type":"address[]"},{"internalType":"bool","name":"_addOwnerToManagers","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"CallerGuardError","type":"error"},{"inputs":[],"name":"GatewayNotSetError","type":"error"},{"inputs":[],"name":"ListSizeLimitError","type":"error"},{"inputs":[],"name":"MessageFeeError","type":"error"},{"inputs":[],"name":"NativeTokenValueError","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NonContractAddressError","type":"error"},{"inputs":[],"name":"OnlyGatewayError","type":"error"},{"inputs":[],"name":"OnlyManagerError","type":"error"},{"inputs":[],"name":"OnlySelfError","type":"error"},{"inputs":[],"name":"ReservedTokenError","type":"error"},{"inputs":[],"name":"RouterNotSetError","type":"error"},{"inputs":[],"name":"SafeApproveError","type":"error"},{"inputs":[],"name":"SafeTransferError","type":"error"},{"inputs":[],"name":"SafeTransferFromError","type":"error"},{"inputs":[],"name":"SafeTransferNativeError","type":"error"},{"inputs":[],"name":"SameChainIdError","type":"error"},{"inputs":[],"name":"SameTokenError","type":"error"},{"inputs":[],"name":"SwapAmountMaxError","type":"error"},{"inputs":[],"name":"SwapAmountMinError","type":"error"},{"inputs":[],"name":"SwapError","type":"error"},{"inputs":[],"name":"TargetSwapInfoError","type":"error"},{"inputs":[],"name":"TokenMintError","type":"error"},{"inputs":[],"name":"VaultNotSetError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"fromToken","type":"address"},{"indexed":false,"internalType":"address","name":"toToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"fromAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ActionLocal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"targetChainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sourceSender","type":"address"},{"indexed":false,"internalType":"address","name":"targetRecipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"gatewayType","type":"uint256"},{"indexed":false,"internalType":"address","name":"sourceToken","type":"address"},{"indexed":false,"internalType":"address","name":"targetToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ActionSource","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"sourceChainId","type":"uint256"},{"indexed":true,"internalType":"bool","name":"isSuccess","type":"bool"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ActionTarget","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"RenounceManagerRole","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum CallerGuard.CallerGuardMode","name":"callerGuardMode","type":"uint8"}],"name":"SetCallerGuardMode","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"bool","name":"isListed","type":"bool"}],"name":"SetListedCallerGuardContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"bool","name":"value","type":"bool"}],"name":"SetManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"registryAddress","type":"address"}],"name":"SetRegistry","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recordsAddress","type":"address"}],"name":"SetVariableBalanceRecords","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":true,"internalType":"bool","name":"isLocal","type":"bool"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"routerType","type":"uint256"},{"indexed":false,"internalType":"address","name":"fromTokenAddress","type":"address"},{"indexed":false,"internalType":"address","name":"toTokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"fromAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"resultAmount","type":"uint256"}],"name":"SourceProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"routerType","type":"uint256"},{"indexed":false,"internalType":"address","name":"fromTokenAddress","type":"address"},{"indexed":false,"internalType":"address","name":"toTokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"fromAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"resultAmount","type":"uint256"}],"name":"TargetProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"actionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"vaultType","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"VariableBalanceAllocated","type":"event"},{"inputs":[],"name":"BLAST","outputs":[{"internalType":"contract IBlast","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BLAST_POINTS","outputs":[{"internalType":"contract IBlastPoints","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SYSTEM_VERSION_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDB","outputs":[{"internalType":"contract IERC20Rebasing","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"contract IERC20Rebasing","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Rebasing","name":"_token","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"blastClaimTokenYield","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"blastConfigureClaimableAssets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_governor","type":"address"}],"name":"blastConfigureGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pointsOperator","type":"address"}],"name":"blastConfigurePointsOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Rebasing","name":"_token","type":"address"},{"internalType":"enum YieldMode","name":"_yieldMode","type":"uint8"}],"name":"blastConfigureTokenYield","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fromAmount","type":"uint256"},{"internalType":"bool","name":"_isForward","type":"bool"}],"name":"calculateLocalAmount","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultType","type":"uint256"},{"internalType":"uint256","name":"_fromChainId","type":"uint256"},{"internalType":"uint256","name":"_toChainId","type":"uint256"},{"internalType":"uint256","name":"_fromAmount","type":"uint256"},{"internalType":"bool","name":"_isForward","type":"bool"}],"name":"calculateVaultAmount","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"callerGuardMode","outputs":[{"internalType":"enum CallerGuard.CallerGuardMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultType","type":"uint256"}],"name":"claimVariableToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"cleanup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultType","type":"uint256"}],"name":"convertVariableBalanceToVaultAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"gatewayType","type":"uint256"},{"internalType":"uint256","name":"vaultType","type":"uint256"},{"internalType":"address","name":"sourceTokenAddress","type":"address"},{"components":[{"internalType":"uint256","name":"fromAmount","type":"uint256"},{"internalType":"uint256","name":"routerType","type":"uint256"},{"internalType":"bytes","name":"routerData","type":"bytes"}],"internalType":"struct IActionDataStructures.SwapInfo","name":"sourceSwapInfo","type":"tuple"},{"internalType":"uint256","name":"targetChainId","type":"uint256"},{"internalType":"address","name":"targetTokenAddress","type":"address"},{"components":[{"internalType":"uint256","name":"fromAmount","type":"uint256"},{"internalType":"uint256","name":"routerType","type":"uint256"},{"internalType":"bytes","name":"routerData","type":"bytes"}],"internalType":"struct IActionDataStructures.SwapInfo[]","name":"targetSwapInfoOptions","type":"tuple[]"},{"internalType":"address","name":"targetRecipient","type":"address"},{"internalType":"bytes","name":"gatewaySettings","type":"bytes"}],"internalType":"struct IActionDataStructures.Action","name":"_action","type":"tuple"}],"name":"execute","outputs":[{"internalType":"uint256","name":"actionId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"components":[{"internalType":"uint256","name":"fromAmount","type":"uint256"},{"internalType":"uint256","name":"routerType","type":"uint256"},{"internalType":"bytes","name":"routerData","type":"bytes"}],"internalType":"struct IActionDataStructures.SwapInfo","name":"swapInfo","type":"tuple"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct IActionDataStructures.LocalAction","name":"_localAction","type":"tuple"}],"name":"executeLocal","outputs":[{"internalType":"uint256","name":"actionId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"fullListedCallerGuardContractList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fullManagerList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_messageSourceChainId","type":"uint256"},{"internalType":"bytes","name":"_payloadData","type":"bytes"}],"name":"handleExecutionPayload","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isListedCallerGuardContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"isReservedToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"listedCallerGuardContractCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"listedCallerGuardContractIndexMap","outputs":[{"internalType":"bool","name":"isSet","type":"bool"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"listedCallerGuardContractList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"managerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gatewayType","type":"uint256"},{"internalType":"uint256","name":"_targetChainId","type":"uint256"},{"internalType":"bytes[]","name":"_targetRouterDataOptions","type":"bytes[]"},{"internalType":"bytes","name":"_gatewaySettings","type":"bytes"}],"name":"messageFeeEstimate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract IRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceManagerRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"routerTransfer","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"gasReserve","type":"uint256"}],"internalType":"struct ISettings.TargetSettings","name":"_settings","type":"tuple"},{"components":[{"internalType":"uint256","name":"actionId","type":"uint256"},{"internalType":"address","name":"sourceSender","type":"address"},{"internalType":"uint256","name":"vaultType","type":"uint256"},{"internalType":"address","name":"targetTokenAddress","type":"address"},{"components":[{"internalType":"uint256","name":"fromAmount","type":"uint256"},{"internalType":"uint256","name":"routerType","type":"uint256"},{"internalType":"bytes","name":"routerData","type":"bytes"}],"internalType":"struct IActionDataStructures.SwapInfo","name":"targetSwapInfo","type":"tuple"},{"internalType":"address","name":"targetRecipient","type":"address"}],"internalType":"struct IActionDataStructures.TargetMessage","name":"_targetMessage","type":"tuple"}],"name":"selfCallTarget","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum CallerGuard.CallerGuardMode","name":"_callerGuardMode","type":"uint8"}],"name":"setCallerGuardMode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"flag","type":"bool"}],"internalType":"struct AccountToFlag[]","name":"_items","type":"tuple[]"}],"name":"setListedCallerGuardContracts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_value","type":"bool"}],"name":"setManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IRegistry","name":"_registry","type":"address"}],"name":"setRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"tokenBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_vaultType","type":"uint256"}],"name":"variableBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"variableBalanceRecords","outputs":[{"internalType":"contract IVariableBalanceRecords","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040526004805460ff191690556200001d46629896806200090f565b6200002c906204b33962000929565b6009553480156200003c57600080fd5b50604051620054e6380380620054e68339810160408190526200005f916200098e565b6000805460ff191690558585858585856200007a33620000de565b60016003556200008a8662000137565b62000095856200018c565b8360096000828254620000a9919062000929565b90915550620000bc9050838383620001e1565b505050505050620000d26200029b60201b60201c565b50505050505062000b60565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b6200014281620004da565b600780546001600160a01b0319166001600160a01b0383169081179091556040517f278c70ced5f3e0e5eeb385b5ff9cb735748ba00a625147e66065ed48fc1562cd90600090a250565b6200019781620004da565b600880546001600160a01b0319166001600160a01b0383169081179091556040517fd3f42b09987a9b16fb77c8731fc1acfc8c124f7fac825d558856665ae1f68f5990600090a250565b60006001600160a01b03841615620001fa5783620001fc565b335b905060005b83518110156200024f576200023a84828151811062000224576200022462000abf565b602002602001015160016200051260201b60201c565b80620002468162000ad5565b91505062000201565b50818015620002665750620002648162000585565b155b1562000279576200027981600162000512565b6001600160a01b038116331462000295576200029581620005c7565b50505050565b6001303b1580620002b15750620002b162000643565b620003035760405162461bcd60e51b815260206004820152601960248201527f426c617374436f6e6669673a20556e617574686f72697a65640000000000000060448201526064015b60405180910390fd5b7343000000000000000000000000000000000000026001600160a01b031663f098767a6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156200035357600080fd5b505af115801562000368573d6000803e3d6000fd5b505050507343000000000000000000000000000000000000026001600160a01b0316634e606c476040518163ffffffff1660e01b8152600401600060405180830381600087803b158015620003bc57600080fd5b505af1158015620003d1573d6000803e3d6000fd5b5050604051631a33757d60e01b81527343000000000000000000000000000000000000039250631a33757d91506200040f9060029060040162000af1565b6020604051808303816000875af11580156200042f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000455919062000b1a565b50604051631a33757d60e01b815273430000000000000000000000000000000000000490631a33757d90620004909060029060040162000af1565b6020604051808303816000875af1158015620004b0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004d6919062000b1a565b5050565b6001600160a01b0381163b6200050f57604051638c50d7cd60e01b81526001600160a01b0382166004820152602401620002fa565b50565b6200051c62000655565b620005497f6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6f8383620006b9565b604051811515906001600160a01b038416907fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028690600090a35050565b6001600160a01b03811660009081527f260b29b219d450563ddb0e5ca806bdadb1e125f7e8c506de0443797dd7122728602052604081205460ff165b92915050565b620005d162000655565b6001600160a01b038116620006385760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620002fa565b6200050f81620000de565b6000620006503362000585565b905090565b6000546001600160a01b03610100909104163314620006b75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620002fa565b565b6000838152600160209081526040808320600290925290912062000295919084846064600082620006f757620006f18686866200070f565b62000705565b620007058686868562000844565b9695505050505050565b6001600160a01b0381166000908152602083905260409020805460ff169081156200083c57600180820154865490916000916200074d919062000b34565b9050808214620007e15760008782815481106200076e576200076e62000abf565b9060005260206000200160009054906101000a90046001600160a01b0316905080888481548110620007a457620007a462000abf565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815290879052604090206001018290555b86805480620007f457620007f462000b4a565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038716825287905260408120805460ff191681556001015550505b509392505050565b6001600160a01b03821660009081526020849052604090205460ff16158015620008f157845482116200088a5760405163b1655e3360e01b815260040160405180910390fd5b6040805180820182526001808252875460208084019182526001600160a01b03881660008181528a83529586209451855460ff1916901515178555915193830193909355885491820189558884529190922090910180546001600160a01b03191690911790555b949350505050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417620005c157620005c1620008f9565b80820180821115620005c157620005c1620008f9565b6001600160a01b03811681146200050f57600080fd5b805162000962816200093f565b919050565b634e487b7160e01b600052604160045260246000fd5b805180151581146200096257600080fd5b60008060008060008060c08789031215620009a857600080fd5b8651620009b5816200093f565b80965050602080880151620009ca816200093f565b604089015160608a01519197509550620009e4816200093f565b60808901519094506001600160401b038082111562000a0257600080fd5b818a0191508a601f83011262000a1757600080fd5b81518181111562000a2c5762000a2c62000967565b8060051b604051601f19603f8301168101818110858211171562000a545762000a5462000967565b60405291825284820192508381018501918d83111562000a7357600080fd5b938501935b8285101562000a9c5762000a8c8562000955565b8452938501939285019262000a78565b80975050505050505062000ab360a088016200097d565b90509295509295509295565b634e487b7160e01b600052603260045260246000fd5b60006001820162000aea5762000aea620008f9565b5060010190565b602081016003831062000b1457634e487b7160e01b600052602160045260246000fd5b91905290565b60006020828403121562000b2d57600080fd5b5051919050565b81810381811115620005c157620005c1620008f9565b634e487b7160e01b600052603160045260246000fd5b6149768062000b706000396000f3fe6080604052600436106102765760003560e01c80637734095e1161014f578063ad530409116100c1578063f2fde38b1161007a578063f2fde38b146107aa578063f3ae2415146107ca578063f4162167146107ea578063f6b3fe1d1461080a578063f977350c1461082a578063fe14e8c31461084a57600080fd5b8063ad53040914610705578063ad5c464814610725578063b20f563914610740578063c2c518e114610760578063e3725b1514610775578063eedc966a1461078a57600080fd5b80638da5cb5b116101135780638da5cb5b14610654578063964236941461067757806397d75776146106975780639f487685146106b2578063a5e90eee146106c5578063a91ee0dc146106e557600080fd5b80637734095e146105cc5780637b103999146105ec5780637b25b4d41461060c578063819bc4b91461062c5780638456cb591461063f57600080fd5b806338d9e86f116101e85780634b8f9025116101ac5780634b8f90251461051b5780635c975abb14610543578063607ab5e51461055b578063655a79e0146105825780636b56a691146105a2578063715018a6146105b757600080fd5b806338d9e86f146104855780633d5439a5146104a55780633f4ba83a146104c5578063440d7248146104da57806348db6d77146104fb57600080fd5b806317daf0b41161023a57806317daf0b41461037157806327b25749146103a157806330eb1278146103c157806331a0edec146103e1578063341328c51461041457806338405ec31461046557600080fd5b806304e535e21461028257806305275651146102ad578063093f0e27146102db578063103b73971461030f5780631581c5bf1461035a57600080fd5b3661027d57005b600080fd5b34801561028e57600080fd5b5061029761086a565b6040516102a49190613a2f565b60405180910390f35b3480156102b957600080fd5b506102cd6102c8366004613a8a565b6108cc565b6040519081526020016102a4565b3480156102e757600080fd5b506102cd7f22ad9585a395edc8067b50da4778cafbb7fa2c4bbd7619fad6aeba403857fd7481565b34801561031b57600080fd5b5060008051602061492183398151915260005260016020527f3c2285c553468ca8f30447b24bb463c127f1b840e23a0cafa23caa79d906669a546102cd565b34801561036657600080fd5b5061036f610982565b005b34801561037d57600080fd5b5061039161038c366004613aec565b610b4f565b60405190151581526020016102a4565b3480156103ad57600080fd5b5061036f6103bc366004613aec565b610b6d565b3480156103cd57600080fd5b5061036f6103dc366004613b09565b610c0e565b3480156103ed57600080fd5b506103fc6003604360981b0181565b6040516001600160a01b0390911681526020016102a4565b34801561042057600080fd5b5061044e61042f366004613aec565b6006602052600090815260409020805460019091015460ff9091169082565b6040805192151583526020830191909152016102a4565b34801561047157600080fd5b5061036f610480366004613b35565b610c6e565b34801561049157600080fd5b506102cd6104a0366004613b09565b610d0e565b3480156104b157600080fd5b5061036f6104c0366004613b76565b610d8d565b3480156104d157600080fd5b5061036f610e2c565b3480156104e657600080fd5b506103916104f5366004613aec565b50600090565b34801561050757600080fd5b5061036f610516366004613b76565b610e64565b34801561052757600080fd5b506103fc732536fe9ab3f511540f2f9e2ec2a805005c3dd80081565b34801561054f57600080fd5b5060005460ff16610391565b34801561056757600080fd5b506004546105759060ff1681565b6040516102a49190613bc3565b34801561058e57600080fd5b5061036f61059d366004613c1e565b610ef6565b3480156105ae57600080fd5b506005546102cd565b3480156105c357600080fd5b5061036f6110f0565b3480156105d857600080fd5b5061036f6105e7366004613c81565b611102565b3480156105f857600080fd5b506007546103fc906001600160a01b031681565b34801561061857600080fd5b506103fc610627366004613b76565b61124d565b6102cd61063a366004613cd6565b611277565b34801561064b57600080fd5b5061036f61184c565b34801561066057600080fd5b5060005461010090046001600160a01b03166103fc565b34801561068357600080fd5b5061036f610692366004613aec565b611882565b3480156106a357600080fd5b506103fc6002604360981b0181565b6102cd6106c0366004613d11565b6118e4565b3480156106d157600080fd5b5061036f6106e0366004613d45565b611d4a565b3480156106f157600080fd5b5061036f610700366004613aec565b611da7565b34801561071157600080fd5b5061036f610720366004613d80565b611dd6565b34801561073157600080fd5b506103fc6004604360981b0181565b34801561074c57600080fd5b506102cd61075b366004613dae565b611e7a565b34801561076c57600080fd5b5061036f6120e0565b34801561078157600080fd5b5061029761214d565b34801561079657600080fd5b506102cd6107a5366004613aec565b612166565b3480156107b657600080fd5b5061036f6107c5366004613aec565b6121fc565b3480156107d657600080fd5b506103916107e5366004613aec565b612272565b3480156107f657600080fd5b506102cd610805366004613e61565b6122b2565b34801561081657600080fd5b506008546103fc906001600160a01b031681565b34801561083657600080fd5b5061036f610845366004613e86565b612340565b34801561085657600080fd5b5061036f610865366004613ea3565b6123c8565b606060058054806020026020016040519081016040528092919081815260200182805480156108c257602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116108a4575b5050505050905090565b600754604051631771177960e11b815233600482015260248101879052604481018690526064810185905260009182916001600160a01b0390911690632ee22ef290608401608060405180830381865afa15801561092e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109529190613ff7565b9050610972816000015182602001518686856040015186606001516124d4565b979650505050505050565b905090565b6001303b15806109955750610995612573565b6109ba5760405162461bcd60e51b81526004016109b190614043565b60405180910390fd5b6002604360981b016001600160a01b031663f098767a6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156109fc57600080fd5b505af1158015610a10573d6000803e3d6000fd5b505050506002604360981b016001600160a01b0316634e606c476040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610a5657600080fd5b505af1158015610a6a573d6000803e3d6000fd5b5050604051631a33757d60e01b81526003604360981b019250631a33757d9150610a9990600290600401613bc3565b6020604051808303816000875af1158015610ab8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610adc919061407a565b50604051631a33757d60e01b81526004604360981b0190631a33757d90610b0890600290600401613bc3565b6020604051808303816000875af1158015610b27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4b919061407a565b5050565b6001600160a01b031660009081526006602052604090205460ff1690565b6001303b1580610b805750610b80612573565b610b9c5760405162461bcd60e51b81526004016109b190614043565b6040516336b91f2b60e01b81526001600160a01b0383166004820152732536fe9ab3f511540f2f9e2ec2a805005c3dd800906336b91f2b906024015b600060405180830381600087803b158015610bf257600080fd5b505af1158015610c06573d6000803e3d6000fd5b505050505050565b610c1733612272565b610c3457604051637c3ea23f60e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601610c6357610b4b338261257e565b610b4b82338361260c565b6000610c78612573565b610c945760405162461bcd60e51b81526004016109b190614043565b604051635569f64b60e11b81526001600160a01b0384811660048301526024820184905285169063aad3ec96906044016020604051808303816000875af1158015610ce3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d07919061407a565b5050505050565b600854604051638758e33960e01b81526001600160a01b038481166004830152602482018490526000921690638758e33990604401602060405180830381865afa158015610d60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d84919061407a565b90505b92915050565b610d956126f6565b610d9d61273c565b333214610e14576000600260045460ff166002811115610dbf57610dbf613b8f565b1480610df05750600160045460ff166002811115610ddf57610ddf613b8f565b148015610df05750610df033610b4f565b905080610e1257604051630fa0970d60e11b81523360048201526024016109b1565b505b610e1f816001612795565b610e296001600355565b50565b610e3533612272565b610e5257604051637c3ea23f60e01b815260040160405180910390fd5b610e5a612a95565b610e62612ade565b565b610e6c6126f6565b610e7461273c565b333214610eeb576000600260045460ff166002811115610e9657610e96613b8f565b1480610ec75750600160045460ff166002811115610eb657610eb6613b8f565b148015610ec75750610ec733610b4f565b905080610ee957604051630fa0970d60e11b81523360048201526024016109b1565b505b610e1f816000612795565b610efe6126f6565b6007546040516307f9220960e41b81523360048201526001600160a01b0390911690637f92209090602401602060405180830381865afa158015610f46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f6a9190614093565b610f8757604051635d3da26d60e01b815260040160405180910390fd5b6000610f9582840184614162565b60075460408083015160808401516020015191516308f59d7960e21b81529394506000936001600160a01b03909316926323d675e492610fe19291600401918252602082015260400190565b608060405180830381865afa158015610ffe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611022919061422a565b905060008060006110368460600151612b30565b91509150811561109d57604051633b9a04af60e11b81523090637734095e9083906110679088908a90600401614362565b600060405180830381600088803b15801561108157600080fd5b5087f193505050508015611093575060015b1561109d57600192505b826110ab576110ab85612b5c565b8451604051428152841515918a917fc678724853e8a8ed1f6ed64e9efc05afa8c6826d63a2c42e33fbd4697ff458459060200160405180910390a45050505050505050565b6110f8612c2b565b610e626000612c8b565b333014611122576040516328a2ea3b60e01b815260040160405180910390fd5b60006111346060840160408501613aec565b6001600160a01b03160361115b57604051630b24de4b60e01b815260040160405180910390fd5b600061116d6060840160408501613aec565b6001600160a01b0316634b15b2a961118860808501856143a8565b60405160e083901b6001600160e01b031916815290356004820152306024820152600060448201526064016020604051808303816000875af11580156111d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f691906143c8565b905061124861120a368590038501856143e5565b83358361121d6080870160608801613aec565b61122a60808801886143a8565b61123390614445565b61124360c0890160a08a01613aec565b612ce4565b505050565b6005818154811061125d57600080fd5b6000918252602090912001546001600160a01b0316905081565b60006112816126f6565b61128961273c565b333214611300576000600260045460ff1660028111156112ab576112ab613b8f565b14806112dc5750600160045460ff1660028111156112cb576112cb613b8f565b1480156112dc57506112dc33610b4f565b9050806112fe57604051630fa0970d60e11b81523360048201526024016109b1565b505b468260800135036113245760405163785a29dd60e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6113496060840160408501613aec565b6001600160a01b031614801561136b575061136760608301836143a8565b3534105b1561138957604051637dd7aa2160e01b815260040160405180910390fd5b60006113953447614467565b6009805491925060006113a78361447a565b90915550506009546007549092506000906001600160a01b031663322f243233608087013587356113db60608a018a6143a8565b6040516001600160e01b031960e087901b1681526001600160a01b039094166004850152602484019290925260448301526020908101356064830152870135608482015260a40161016060405180830381865afa158015611440573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114649190614493565b60608101519091506001600160a01b031661149257604051630b24de4b60e01b815260040160405180910390fd5b600081606001516001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114fa91906143c8565b905060008061153a868261151460608b0160408c01613aec565b8661152260608d018d6143a8565b61152b90614445565b89602001518a60400151612ead565b91509150600061156085608001518660a001518560018960c001518a61010001516124d4565b905061158660405180606001604052806000815260200160008152602001606081525090565b600061159560c08b018b61454c565b90509050806000036116065760405180606001604052808481526020016000815260200160006001600160401b038111156115d2576115d2613f17565b6040519080825280601f01601f1916602001820160405280156115fc576020820181803683370190505b5090529150611695565b60005b8181101561167257600061162060c08d018d61454c565b8381811061163057611630614595565b905060200281019061164291906143a8565b61164b90614445565b90508481600001511161165f579250611672565b508061166a8161447a565b915050611609565b50815160000361169557604051637755fda760e01b815260040160405180910390fd5b60006116ae8860a0015189608001518560000151613130565b905060006116c28960800151601284613130565b90508861010001516116e3576116e3818a61012001518b6101400151613194565b6116f2888a606001518461260c565b60006040518060c001604052808d8152602001336001600160a01b031681526020018e6020013581526020018e60a00160208101906117319190613aec565b6001600160a01b0316815260200186815260200160006001600160a01b03168f60e00160208101906117639190613aec565b6001600160a01b031614611789578e60e00160208101906117849190613aec565b61178b565b335b6001600160a01b031690526040516117a691906020016145ab565b60408051601f1981840301815291905290506117cd8a8e836117c88b34614467565b6131d6565b60006117d9848a614467565b90506000811180156117f7575060e08b01516001600160a01b031615155b1561180b5761180b8a8c60e001518361260c565b611816308d33613324565b6118318d8f8561182c8f60800151601287613130565b61334c565b5050505050505050505050506118476001600355565b919050565b61185533612272565b61187257604051637c3ea23f60e01b815260040160405180910390fd5b61187a6126f6565b610e626133f4565b6001303b15806118955750611895612573565b6118b15760405162461bcd60e51b81526004016109b190614043565b604051631d70c8d360e31b81526001600160a01b03831660048201526002604360981b019063eb86469890602401610bd8565b60006118ee6126f6565b6118f661273c565b33321461196d576000600260045460ff16600281111561191857611918613b8f565b14806119495750600160045460ff16600281111561193857611938613b8f565b148015611949575061194933610b4f565b90508061196b57604051630fa0970d60e11b81523360048201526024016109b1565b505b61197d6040830160208401613aec565b6001600160a01b03166119936020840184613aec565b6001600160a01b0316036119ba57604051633b0e2de560e21b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6119dc6020840184613aec565b6001600160a01b03161480156119ff57506119fa60408301836143a8565b353414155b15611a1d57604051637dd7aa2160e01b815260040160405180910390fd5b6000611a293447614467565b600980549192506000611a3b8361447a565b90915550506009546007549092506000906001600160a01b031663f36dd64e33611a6860408801886143a8565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260200135602482015260440160a060405180830381865afa158015611ab5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad991906145be565b90506000611b22846001611af06020890189613aec565b611b0060408a0160208b01613aec565b611b0d60408b018b6143a8565b611b1690614445565b87516020890151612ead565b509050600080611b386080880160608901613aec565b6001600160a01b031614611b5b57611b566080870160608801613aec565b611b5d565b335b90506000611b7683600186604001518760800151613431565b905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee611b9d6040890160208a01613aec565b6001600160a01b031603611bba57611bb5828261257e565b611bd4565b611bd4611bcd6040890160208a01613aec565b838361260c565b6000611be08285614467565b90508015611c9a5760608501516001600160a01b03811615611c585773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee611c2160408b0160208c01613aec565b6001600160a01b031603611c3e57611c39818361257e565b611c98565b611c39611c5160408b0160208c01613aec565b828461260c565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee611c7d60408b0160208c01613aec565b6001600160a01b031603611c9857611c95828861464c565b96505b505b611ca5308733613324565b33877f64f803250cc450b9c5e2cef3ac4c82370f41b8c1e5692f4067b6b96d2430bfcb85611cd660208d018d613aec565b611ce660408e0160208f01613aec565b611cf360408f018f6143a8565b604080516001600160a01b03958616815293851660208501529190931690820152903560608201526080810186905260a081018590524260c082015260e00160405180910390a35050505050506118476001600355565b611d52612c2b565b611d6b60008051602061492183398151915283836134a2565b604051811515906001600160a01b038416907fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028690600090a35050565b611db033612272565b611dcd57604051637c3ea23f60e01b815260040160405180910390fd5b610e29816134c9565b6001303b1580611de95750611de9612573565b611e055760405162461bcd60e51b81526004016109b190614043565b604051631a33757d60e01b81526001600160a01b03841690631a33757d90611e31908590600401613bc3565b6020604051808303816000875af1158015611e50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e74919061407a565b50505050565b6000468603611e8b575060006120d6565b6007546040516318fa0c2360e21b8152600481018990526000916001600160a01b0316906363e8308c90602401602060405180830381865afa158015611ed5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef991906146ae565b80519091506001600160a01b0316611f245760405163ba8ec24160e01b815260040160405180910390fd5b6000858103611fc45781516040805160008152602081019091526001600160a01b039091169063aa4fc83d908a90611f5b9061351c565b88886040518563ffffffff1660e01b8152600401611f7c94939291906146ca565b602060405180830381865afa158015611f99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fbd919061407a565b90506120d2565b60005b868110156120d0576000612032898984818110611fe657611fe6614595565b9050602002810190611ff89190614717565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061351c92505050565b9050600084600001516001600160a01b031663aa4fc83d8c848b8b6040518563ffffffff1660e01b815260040161206c94939291906146ca565b602060405180830381865afa158015612089573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ad919061407a565b9050838111156120bb578093505b505080806120c89061447a565b915050611fc7565b505b9150505b9695505050505050565b6120e933612272565b61210657604051637c3ea23f60e01b815260040160405180910390fd5b6121206000805160206149218339815191523360006134a2565b60405133907f6cc2c67081f55c2fffb7c008fa995fbbf890f48c7c16fba93d8220f00dc84cc590600090a2565b606061097d6000805160206149218339815191526135b0565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601612194575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa1580156121d8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d87919061407a565b612204612c2b565b6001600160a01b0381166122695760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016109b1565b610e2981612c8b565b6001600160a01b03811660009081527f260b29b219d450563ddb0e5ca806bdadb1e125f7e8c506de0443797dd7122728602052604081205460ff16610d87565b600754604051631a5a276d60e31b815233600482015260009182916001600160a01b039091169063d2d13b68906024016040805180830381865afa1580156122fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612322919061475d565b9050612338848483600001518460200151613431565b949350505050565b61234933612272565b61236657604051637c3ea23f60e01b815260040160405180910390fd5b6004805482919060ff1916600183600281111561238557612385613b8f565b021790555080600281111561239c5761239c613b8f565b6040517f332a9f1d3bd9b0f7abbd95838fed6b417589632d0eb33f2d8ae6e2aa17178efd90600090a250565b6123d133612272565b6123ee57604051637c3ea23f60e01b815260040160405180910390fd5b60005b81811015611248573683838381811061240c5761240c614595565b905060400201905080602001602081019061242791906147b2565b156124415761244161243c6020830183613aec565b61361c565b61246c600560066124556020850185613aec565b61246560408601602087016147b2565b606461364f565b5061247d60408201602083016147b2565b151561248c6020830183613aec565b6001600160a01b03167f1470aed653fa8a8ce4c7b2f41287634199f7ec3c4f5fd0ace97d82cf006beec360405160405180910390a350806124cc8161447a565b9150506123f1565b60008082806124e1575083155b905060008515806124ef5750815b61251a57620186a06125018682614467565b61250b90896147cf565b61251591906147e6565b61251c565b865b9050600061252b8a8a84613130565b905086806125365750825b6125635761254786620186a0614467565b612554620186a0836147cf565b61255e91906147e6565b612565565b805b9a9950505050505050505050565b600061097d33612272565b604080516000808252602082019092526001600160a01b0384169083906040516125a89190614808565b60006040518083038185875af1925050503d80600081146125e5576040519150601f19603f3d011682016040523d82523d6000602084013e6125ea565b606091505b505090508061124857604051632e05b05360e21b815260040160405180910390fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916126689190614808565b6000604051808303816000865af19150503d80600081146126a5576040519150601f19603f3d011682016040523d82523d6000602084013e6126aa565b606091505b509150915060008280156126d65750815115806126d65750818060200190518101906126d69190614093565b905080610c0657604051632fdb1b7f60e11b815260040160405180910390fd5b60005460ff1615610e625760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016109b1565b60026003540361278e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016109b1565b6002600355565b60075460405163154d267d60e21b8152600481018490526000916001600160a01b03169063553499f490602401602060405180830381865afa1580156127df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280391906146ae565b80519091506001600160a01b031661282e57604051630b24de4b60e01b815260040160405180910390fd5b600854604051638758e33960e01b8152336004820152602481018590526000916001600160a01b031690638758e33990604401602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a2919061407a565b6008546040516227421b60e61b8152336004820152602481018790529192506001600160a01b0316906309d086c090604401600060405180830381600087803b1580156128ee57600080fd5b505af1158015612902573d6000803e3d6000fd5b505050506000811115611e74578215612996578151604051634b15b2a960e01b815260048101839052336024820152600160448201526001600160a01b0390911690634b15b2a9906064016020604051808303816000875af115801561296c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061299091906143c8565b50611e74565b600082600001516001600160a01b0316632c966a346040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129fe91906143c8565b6040516340c10f1960e01b8152336004820152602481018490529091506000906001600160a01b038316906340c10f19906044016020604051808303816000875af1158015612a51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a759190614093565b905080610c06576040516320aaed5f60e21b815260040160405180910390fd5b60005460ff16610e625760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016109b1565b612ae6612a95565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60008060005a905083811015925082612b4a576000612b54565b612b548482614467565b915050915091565b60a08101516040808301516080840151516008549251631e9f7a9b60e01b81526001600160a01b03808616600483015260248201849052604482018390529293919290911690631e9f7a9b90606401600060405180830381600087803b158015612bc557600080fd5b505af1158015612bd9573d6000803e3d6000fd5b5050855160408051868152602081018690526001600160a01b03881694509192507fb9e12bbbbed208a973bc1ec9604e1f6d7f4b91b193fc2e1150df974b7d16635b910160405180910390a350505050565b6000546001600160a01b03610100909104163314610e625760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109b1565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b6000846001600160a01b0316846001600160a01b031603612d0757508151612dfe565b86516001600160a01b0316612d2f5760405163ebb12eb360e01b815260040160405180910390fd5b6000612d3a85612166565b9050612d4f8689602001518660000151613672565b600088600001516001600160a01b03168560400151604051612d719190614808565b6000604051808303816000865af19150503d8060008114612dae576040519150601f19603f3d011682016040523d82523d6000602084013e612db3565b606091505b5050905080612dd557604051633e1f5ce560e11b815260040160405180910390fd5b612de5878a602001516000613672565b81612def87612166565b612df99190614467565b925050505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03851601612e3257612e2d828261257e565b612e3d565b612e3d84838361260c565b6020808401518451604080519283526001600160a01b0389811694840194909452878416908301526060820152608081018390529083169087907f26e7a43f3221294fff6b57719103b3bfdeb1c06dac5c3973de3e55932e7c1b3b9060a00160405180910390a350505050505050565b6000806000612ebb87612166565b905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03891601612f9a576001600160a01b038516612f095760405163ebb12eb360e01b815260040160405180910390fd5b6000856001600160a01b031687600001518860400151604051612f2c9190614808565b60006040518083038185875af1925050503d8060008114612f69576040519150601f19603f3d011682016040523d82523d6000602084013e612f6e565b606091505b5050905080612f9057604051633e1f5ce560e11b815260040160405180910390fd5b508551915061308e565b612faa883330896000015161375c565b866001600160a01b0316886001600160a01b031614613089576001600160a01b038516612fea5760405163ebb12eb360e01b815260040160405180910390fd5b612ff988858860000151613672565b6000856001600160a01b031687604001516040516130179190614808565b6000604051808303816000865af19150503d8060008114613054576040519150601f19603f3d011682016040523d82523d6000602084013e613059565b606091505b505090508061307b57604051633e1f5ce560e11b815260040160405180910390fd5b61308789866000613672565b505b600091505b8061309888612166565b6130a29190614467565b9250336001600160a01b03168915158b7f580273492d266e8e27b4253a13c46e1c74823e94794f9ad186ca8fe8b109e3ef89602001518c8c8c600001518a60405161311b9594939291909485526001600160a01b0393841660208601529190921660408401526060830191909152608082015260a00190565b60405180910390a45097509795505050505050565b600083830361314057508061318d565b8383111561316e576131528484614467565b61315d90600a6148fe565b61316790836147cf565b905061318d565b6131788385614467565b61318390600a6148fe565b61316790836147e6565b9392505050565b818310156131b557604051632220ee1360e11b815260040160405180910390fd5b808311156112485760405163341cc20160e21b815260040160405180910390fd5b83516001600160a01b03166131fe5760405163ba8ec24160e01b815260040160405180910390fd5b83516000906001600160a01b031663aa4fc83d608086013585613225610100890189614717565b6040518563ffffffff1660e01b815260040161324494939291906146ca565b602060405180830381865afa158015613261573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613285919061407a565b9050808210156132a757604051625a4bb360e21b815260040160405180910390fd5b84516001600160a01b0316636ea9cec9826080870135866132cc6101008a018a614717565b6040518663ffffffff1660e01b81526004016132eb94939291906146ca565b6000604051808303818588803b15801561330457600080fd5b505af1158015613318573d6000803e3d6000fd5b50505050505050505050565b600061333a836001600160a01b03861631614467565b90508015611e7457611e74828261257e565b336080840135857fc2ad425216cf8ac56ecd38af0315ed35266cb6771f34fc27e1f0cde1a5b3eb6a613385610100880160e08901613aec565b873561339760608a0160408b01613aec565b6133a760c08b0160a08c01613aec565b604080516001600160a01b03958616815260208101949094529184168383015290921660608201526080810188905260a081018790524260c082015290519081900360e00190a450505050565b6133fc6126f6565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612b133390565b6000818061343d575082155b15613449575083612338565b836134775761345b83620186a0614467565b613468620186a0876147cf565b61347291906147e6565b613499565b620186a06134858482614467565b61348f90876147cf565b61349991906147e6565b95945050505050565b60008381526001602090815260408083206002909252909120611e7491908484606461364f565b6134d28161361c565b600780546001600160a01b0319166001600160a01b0383169081179091556040517f278c70ced5f3e0e5eeb385b5ff9cb735748ba00a625147e66065ed48fc1562cd90600090a250565b606060006040518060c001604052806000815260200160006001600160a01b031681526020016000815260200160006001600160a01b031681526020016040518060600160405280600081526020016000815260200186815250815260200160006001600160a01b031681525060405160200161359991906145ab565b60408051601f198184030181529190529392505050565b60008181526001602090815260409182902080548351818402810184019094528084526060939283018282801561361057602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116135f2575b50505050509050919050565b6001600160a01b0381163b610e2957604051638c50d7cd60e01b81526001600160a01b03821660048201526024016109b1565b60008261366657613661868686613857565b6120d6565b6120d68686868561397f565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916136ce9190614808565b6000604051808303816000865af19150503d806000811461370b576040519150601f19603f3d011682016040523d82523d6000602084013e613710565b606091505b5091509150600082801561373c57508151158061373c57508180602001905181019061373c9190614093565b905080610c065760405163b45d44e760e01b815260040160405180910390fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916137c09190614808565b6000604051808303816000865af19150503d80600081146137fd576040519150601f19603f3d011682016040523d82523d6000602084013e613802565b606091505b5091509150600082801561382e57508151158061382e57508180602001905181019061382e9190614093565b90508061384e57604051632d9d5b4160e01b815260040160405180910390fd5b50505050505050565b6001600160a01b0381166000908152602083905260409020805460ff1690811561397757600180820154865490916000916138929190614467565b905080821461391f5760008782815481106138af576138af614595565b9060005260206000200160009054906101000a90046001600160a01b03169050808884815481106138e2576138e2614595565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815290879052604090206001018290555b8680548061392f5761392f61490a565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038716825287905260408120805460ff191681556001015550505b509392505050565b6001600160a01b03821660009081526020849052604090205460ff1615801561233857845482116139c35760405163b1655e3360e01b815260040160405180910390fd5b6040805180820182526001808252875460208084019182526001600160a01b039790971660008181529888529388209251835460ff19169015151783555191810191909155865490810187559585529290932090930180546001600160a01b0319169091179055919050565b6020808252825182820181905260009190848201906040850190845b81811015613a705783516001600160a01b031683529284019291840191600101613a4b565b50909695505050505050565b8015158114610e2957600080fd5b600080600080600060a08688031215613aa257600080fd5b853594506020860135935060408601359250606086013591506080860135613ac981613a7c565b809150509295509295909350565b6001600160a01b0381168114610e2957600080fd5b600060208284031215613afe57600080fd5b813561318d81613ad7565b60008060408385031215613b1c57600080fd5b8235613b2781613ad7565b946020939093013593505050565b600080600060608486031215613b4a57600080fd5b8335613b5581613ad7565b92506020840135613b6581613ad7565b929592945050506040919091013590565b600060208284031215613b8857600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60038110610e2957634e487b7160e01b600052602160045260246000fd5b60208101613bd083613ba5565b91905290565b60008083601f840112613be857600080fd5b5081356001600160401b03811115613bff57600080fd5b602083019150836020828501011115613c1757600080fd5b9250929050565b600080600060408486031215613c3357600080fd5b8335925060208401356001600160401b03811115613c5057600080fd5b613c5c86828701613bd6565b9497909650939450505050565b600060808284031215613c7b57600080fd5b50919050565b60008060a08385031215613c9457600080fd5b613c9e8484613c69565b915060808301356001600160401b03811115613cb957600080fd5b830160c08186031215613ccb57600080fd5b809150509250929050565b600060208284031215613ce857600080fd5b81356001600160401b03811115613cfe57600080fd5b8201610120818503121561318d57600080fd5b600060208284031215613d2357600080fd5b81356001600160401b03811115613d3957600080fd5b61233884828501613c69565b60008060408385031215613d5857600080fd5b8235613d6381613ad7565b91506020830135613ccb81613a7c565b60038110610e2957600080fd5b60008060408385031215613d9357600080fd5b8235613d9e81613ad7565b91506020830135613ccb81613d73565b60008060008060008060808789031215613dc757600080fd5b863595506020870135945060408701356001600160401b0380821115613dec57600080fd5b818901915089601f830112613e0057600080fd5b813581811115613e0f57600080fd5b8a60208260051b8501011115613e2457600080fd5b602083019650809550506060890135915080821115613e4257600080fd5b50613e4f89828a01613bd6565b979a9699509497509295939492505050565b60008060408385031215613e7457600080fd5b823591506020830135613ccb81613a7c565b600060208284031215613e9857600080fd5b813561318d81613d73565b60008060208385031215613eb657600080fd5b82356001600160401b0380821115613ecd57600080fd5b818501915085601f830112613ee157600080fd5b813581811115613ef057600080fd5b8660208260061b8501011115613f0557600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613f4f57613f4f613f17565b60405290565b604051606081016001600160401b0381118282101715613f4f57613f4f613f17565b60405160c081016001600160401b0381118282101715613f4f57613f4f613f17565b60405161016081016001600160401b0381118282101715613f4f57613f4f613f17565b604051601f8201601f191681016001600160401b0381118282101715613fe457613fe4613f17565b604052919050565b805161184781613a7c565b60006080828403121561400957600080fd5b614011613f2d565b825181526020830151602082015260408301516040820152606083015161403781613a7c565b60608201529392505050565b60208082526019908201527f426c617374436f6e6669673a20556e617574686f72697a656400000000000000604082015260600190565b60006020828403121561408c57600080fd5b5051919050565b6000602082840312156140a557600080fd5b815161318d81613a7c565b6000606082840312156140c257600080fd5b6140ca613f55565b9050813581526020808301358183015260408301356001600160401b03808211156140f457600080fd5b818501915085601f83011261410857600080fd5b81358181111561411a5761411a613f17565b61412c601f8201601f19168501613fbc565b9150808252868482850101111561414257600080fd5b808484018584013760008482840101525080604085015250505092915050565b60006020828403121561417457600080fd5b81356001600160401b038082111561418b57600080fd5b9083019060c0828603121561419f57600080fd5b6141a7613f77565b8235815260208301356141b981613ad7565b60208201526040838101359082015260608301356141d681613ad7565b60608201526080830135828111156141ed57600080fd5b6141f9878286016140b0565b60808301525060a0830135925061420f83613ad7565b60a0810192909252509392505050565b805161184781613ad7565b60006080828403121561423c57600080fd5b614244613f2d565b825161424f81613ad7565b8152602083015161425f81613ad7565b6020820152604083015161427281613ad7565b60408201526060928301519281019290925250919050565b60005b838110156142a557818101518382015260200161428d565b50506000910152565b600081518084526142c681602086016020860161428a565b601f01601f19169290920160200192915050565b805182526000602082015160018060a01b038082166020860152604084015160408601528060608501511660608601525050608082015160c06080850152805160c0850152602081015160e08501526040810151905060606101008501526143466101208501826142ae565b905060a083015161397760a08601826001600160a01b03169052565b600060018060a01b03808551168352806020860151166020840152806040860151166040840152506060840151606083015260a0608083015261233860a08301846142da565b60008235605e198336030181126143be57600080fd5b9190910192915050565b6000602082840312156143da57600080fd5b815161318d81613ad7565b6000608082840312156143f757600080fd5b6143ff613f2d565b823561440a81613ad7565b8152602083013561441a81613ad7565b6020820152604083013561442d81613ad7565b60408201526060928301359281019290925250919050565b6000610d8736836140b0565b634e487b7160e01b600052601160045260246000fd5b81810381811115610d8757610d87614451565b60006001820161448c5761448c614451565b5060010190565b600061016082840312156144a657600080fd5b6144ae613f99565b6144b78361421f565b81526144c56020840161421f565b60208201526144d66040840161421f565b60408201526144e76060840161421f565b60608201526080830151608082015260a083015160a082015260c083015160c082015261451660e0840161421f565b60e0820152610100614529818501613fec565b908201526101208381015190820152610140928301519281019290925250919050565b6000808335601e1984360301811261456357600080fd5b8301803591506001600160401b0382111561457d57600080fd5b6020019150600581901b3603821315613c1757600080fd5b634e487b7160e01b600052603260045260246000fd5b602081526000610d8460208301846142da565b600060a082840312156145d057600080fd5b60405160a081018181106001600160401b03821117156145f2576145f2613f17565b604052825161460081613ad7565b8152602083015161461081613ad7565b602082015260408381015190820152606083015161462d81613ad7565b6060820152608083015161464081613a7c565b60808201529392505050565b80820180821115610d8757610d87614451565b60006020828403121561467157600080fd5b604051602081018181106001600160401b038211171561469357614693613f17565b806040525080915082516146a681613ad7565b905292915050565b6000602082840312156146c057600080fd5b610d84838361465f565b8481526060602082015260006146e360608301866142ae565b8281036040840152838152838560208301376000602085830101526020601f19601f86011682010191505095945050505050565b6000808335601e1984360301811261472e57600080fd5b8301803591506001600160401b0382111561474857600080fd5b602001915036819003821315613c1757600080fd5b60006040828403121561476f57600080fd5b604051604081018181106001600160401b038211171561479157614791613f17565b6040528251815260208301516147a681613a7c565b60208201529392505050565b6000602082840312156147c457600080fd5b813561318d81613a7c565b8082028115828204841417610d8757610d87614451565b60008261480357634e487b7160e01b600052601260045260246000fd5b500490565b600082516143be81846020870161428a565b600181815b8085111561485557816000190482111561483b5761483b614451565b8085161561484857918102915b93841c939080029061481f565b509250929050565b60008261486c57506001610d87565b8161487957506000610d87565b816001811461488f5760028114614899576148b5565b6001915050610d87565b60ff8411156148aa576148aa614451565b50506001821b610d87565b5060208310610133831016604e8410600b84101617156148d8575081810a610d87565b6148e2838361481a565b80600019048211156148f6576148f6614451565b029392505050565b6000610d84838361485d565b634e487b7160e01b600052603160045260246000fdfe6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6fa26469706673582212207ea73b3cad3a79b1a27802e0c79ea4b52fa59fc183ca6e362478e048bce61fee64736f6c63430008130033000000000000000000000000f19ea8e63256992a823262c71568b0bb27ce146f000000000000000000000000bfc3b856b9bcc792875e79fc8ffcc09028aad40600000000000000000000000000000000000000000000000000000000000001f400000000000000000000000072e28c7f34100afefc399fcc0ae041b8fe5841ae00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106102765760003560e01c80637734095e1161014f578063ad530409116100c1578063f2fde38b1161007a578063f2fde38b146107aa578063f3ae2415146107ca578063f4162167146107ea578063f6b3fe1d1461080a578063f977350c1461082a578063fe14e8c31461084a57600080fd5b8063ad53040914610705578063ad5c464814610725578063b20f563914610740578063c2c518e114610760578063e3725b1514610775578063eedc966a1461078a57600080fd5b80638da5cb5b116101135780638da5cb5b14610654578063964236941461067757806397d75776146106975780639f487685146106b2578063a5e90eee146106c5578063a91ee0dc146106e557600080fd5b80637734095e146105cc5780637b103999146105ec5780637b25b4d41461060c578063819bc4b91461062c5780638456cb591461063f57600080fd5b806338d9e86f116101e85780634b8f9025116101ac5780634b8f90251461051b5780635c975abb14610543578063607ab5e51461055b578063655a79e0146105825780636b56a691146105a2578063715018a6146105b757600080fd5b806338d9e86f146104855780633d5439a5146104a55780633f4ba83a146104c5578063440d7248146104da57806348db6d77146104fb57600080fd5b806317daf0b41161023a57806317daf0b41461037157806327b25749146103a157806330eb1278146103c157806331a0edec146103e1578063341328c51461041457806338405ec31461046557600080fd5b806304e535e21461028257806305275651146102ad578063093f0e27146102db578063103b73971461030f5780631581c5bf1461035a57600080fd5b3661027d57005b600080fd5b34801561028e57600080fd5b5061029761086a565b6040516102a49190613a2f565b60405180910390f35b3480156102b957600080fd5b506102cd6102c8366004613a8a565b6108cc565b6040519081526020016102a4565b3480156102e757600080fd5b506102cd7f22ad9585a395edc8067b50da4778cafbb7fa2c4bbd7619fad6aeba403857fd7481565b34801561031b57600080fd5b5060008051602061492183398151915260005260016020527f3c2285c553468ca8f30447b24bb463c127f1b840e23a0cafa23caa79d906669a546102cd565b34801561036657600080fd5b5061036f610982565b005b34801561037d57600080fd5b5061039161038c366004613aec565b610b4f565b60405190151581526020016102a4565b3480156103ad57600080fd5b5061036f6103bc366004613aec565b610b6d565b3480156103cd57600080fd5b5061036f6103dc366004613b09565b610c0e565b3480156103ed57600080fd5b506103fc6003604360981b0181565b6040516001600160a01b0390911681526020016102a4565b34801561042057600080fd5b5061044e61042f366004613aec565b6006602052600090815260409020805460019091015460ff9091169082565b6040805192151583526020830191909152016102a4565b34801561047157600080fd5b5061036f610480366004613b35565b610c6e565b34801561049157600080fd5b506102cd6104a0366004613b09565b610d0e565b3480156104b157600080fd5b5061036f6104c0366004613b76565b610d8d565b3480156104d157600080fd5b5061036f610e2c565b3480156104e657600080fd5b506103916104f5366004613aec565b50600090565b34801561050757600080fd5b5061036f610516366004613b76565b610e64565b34801561052757600080fd5b506103fc732536fe9ab3f511540f2f9e2ec2a805005c3dd80081565b34801561054f57600080fd5b5060005460ff16610391565b34801561056757600080fd5b506004546105759060ff1681565b6040516102a49190613bc3565b34801561058e57600080fd5b5061036f61059d366004613c1e565b610ef6565b3480156105ae57600080fd5b506005546102cd565b3480156105c357600080fd5b5061036f6110f0565b3480156105d857600080fd5b5061036f6105e7366004613c81565b611102565b3480156105f857600080fd5b506007546103fc906001600160a01b031681565b34801561061857600080fd5b506103fc610627366004613b76565b61124d565b6102cd61063a366004613cd6565b611277565b34801561064b57600080fd5b5061036f61184c565b34801561066057600080fd5b5060005461010090046001600160a01b03166103fc565b34801561068357600080fd5b5061036f610692366004613aec565b611882565b3480156106a357600080fd5b506103fc6002604360981b0181565b6102cd6106c0366004613d11565b6118e4565b3480156106d157600080fd5b5061036f6106e0366004613d45565b611d4a565b3480156106f157600080fd5b5061036f610700366004613aec565b611da7565b34801561071157600080fd5b5061036f610720366004613d80565b611dd6565b34801561073157600080fd5b506103fc6004604360981b0181565b34801561074c57600080fd5b506102cd61075b366004613dae565b611e7a565b34801561076c57600080fd5b5061036f6120e0565b34801561078157600080fd5b5061029761214d565b34801561079657600080fd5b506102cd6107a5366004613aec565b612166565b3480156107b657600080fd5b5061036f6107c5366004613aec565b6121fc565b3480156107d657600080fd5b506103916107e5366004613aec565b612272565b3480156107f657600080fd5b506102cd610805366004613e61565b6122b2565b34801561081657600080fd5b506008546103fc906001600160a01b031681565b34801561083657600080fd5b5061036f610845366004613e86565b612340565b34801561085657600080fd5b5061036f610865366004613ea3565b6123c8565b606060058054806020026020016040519081016040528092919081815260200182805480156108c257602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116108a4575b5050505050905090565b600754604051631771177960e11b815233600482015260248101879052604481018690526064810185905260009182916001600160a01b0390911690632ee22ef290608401608060405180830381865afa15801561092e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109529190613ff7565b9050610972816000015182602001518686856040015186606001516124d4565b979650505050505050565b905090565b6001303b15806109955750610995612573565b6109ba5760405162461bcd60e51b81526004016109b190614043565b60405180910390fd5b6002604360981b016001600160a01b031663f098767a6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156109fc57600080fd5b505af1158015610a10573d6000803e3d6000fd5b505050506002604360981b016001600160a01b0316634e606c476040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610a5657600080fd5b505af1158015610a6a573d6000803e3d6000fd5b5050604051631a33757d60e01b81526003604360981b019250631a33757d9150610a9990600290600401613bc3565b6020604051808303816000875af1158015610ab8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610adc919061407a565b50604051631a33757d60e01b81526004604360981b0190631a33757d90610b0890600290600401613bc3565b6020604051808303816000875af1158015610b27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4b919061407a565b5050565b6001600160a01b031660009081526006602052604090205460ff1690565b6001303b1580610b805750610b80612573565b610b9c5760405162461bcd60e51b81526004016109b190614043565b6040516336b91f2b60e01b81526001600160a01b0383166004820152732536fe9ab3f511540f2f9e2ec2a805005c3dd800906336b91f2b906024015b600060405180830381600087803b158015610bf257600080fd5b505af1158015610c06573d6000803e3d6000fd5b505050505050565b610c1733612272565b610c3457604051637c3ea23f60e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601610c6357610b4b338261257e565b610b4b82338361260c565b6000610c78612573565b610c945760405162461bcd60e51b81526004016109b190614043565b604051635569f64b60e11b81526001600160a01b0384811660048301526024820184905285169063aad3ec96906044016020604051808303816000875af1158015610ce3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d07919061407a565b5050505050565b600854604051638758e33960e01b81526001600160a01b038481166004830152602482018490526000921690638758e33990604401602060405180830381865afa158015610d60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d84919061407a565b90505b92915050565b610d956126f6565b610d9d61273c565b333214610e14576000600260045460ff166002811115610dbf57610dbf613b8f565b1480610df05750600160045460ff166002811115610ddf57610ddf613b8f565b148015610df05750610df033610b4f565b905080610e1257604051630fa0970d60e11b81523360048201526024016109b1565b505b610e1f816001612795565b610e296001600355565b50565b610e3533612272565b610e5257604051637c3ea23f60e01b815260040160405180910390fd5b610e5a612a95565b610e62612ade565b565b610e6c6126f6565b610e7461273c565b333214610eeb576000600260045460ff166002811115610e9657610e96613b8f565b1480610ec75750600160045460ff166002811115610eb657610eb6613b8f565b148015610ec75750610ec733610b4f565b905080610ee957604051630fa0970d60e11b81523360048201526024016109b1565b505b610e1f816000612795565b610efe6126f6565b6007546040516307f9220960e41b81523360048201526001600160a01b0390911690637f92209090602401602060405180830381865afa158015610f46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f6a9190614093565b610f8757604051635d3da26d60e01b815260040160405180910390fd5b6000610f9582840184614162565b60075460408083015160808401516020015191516308f59d7960e21b81529394506000936001600160a01b03909316926323d675e492610fe19291600401918252602082015260400190565b608060405180830381865afa158015610ffe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611022919061422a565b905060008060006110368460600151612b30565b91509150811561109d57604051633b9a04af60e11b81523090637734095e9083906110679088908a90600401614362565b600060405180830381600088803b15801561108157600080fd5b5087f193505050508015611093575060015b1561109d57600192505b826110ab576110ab85612b5c565b8451604051428152841515918a917fc678724853e8a8ed1f6ed64e9efc05afa8c6826d63a2c42e33fbd4697ff458459060200160405180910390a45050505050505050565b6110f8612c2b565b610e626000612c8b565b333014611122576040516328a2ea3b60e01b815260040160405180910390fd5b60006111346060840160408501613aec565b6001600160a01b03160361115b57604051630b24de4b60e01b815260040160405180910390fd5b600061116d6060840160408501613aec565b6001600160a01b0316634b15b2a961118860808501856143a8565b60405160e083901b6001600160e01b031916815290356004820152306024820152600060448201526064016020604051808303816000875af11580156111d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f691906143c8565b905061124861120a368590038501856143e5565b83358361121d6080870160608801613aec565b61122a60808801886143a8565b61123390614445565b61124360c0890160a08a01613aec565b612ce4565b505050565b6005818154811061125d57600080fd5b6000918252602090912001546001600160a01b0316905081565b60006112816126f6565b61128961273c565b333214611300576000600260045460ff1660028111156112ab576112ab613b8f565b14806112dc5750600160045460ff1660028111156112cb576112cb613b8f565b1480156112dc57506112dc33610b4f565b9050806112fe57604051630fa0970d60e11b81523360048201526024016109b1565b505b468260800135036113245760405163785a29dd60e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6113496060840160408501613aec565b6001600160a01b031614801561136b575061136760608301836143a8565b3534105b1561138957604051637dd7aa2160e01b815260040160405180910390fd5b60006113953447614467565b6009805491925060006113a78361447a565b90915550506009546007549092506000906001600160a01b031663322f243233608087013587356113db60608a018a6143a8565b6040516001600160e01b031960e087901b1681526001600160a01b039094166004850152602484019290925260448301526020908101356064830152870135608482015260a40161016060405180830381865afa158015611440573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114649190614493565b60608101519091506001600160a01b031661149257604051630b24de4b60e01b815260040160405180910390fd5b600081606001516001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156114d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114fa91906143c8565b905060008061153a868261151460608b0160408c01613aec565b8661152260608d018d6143a8565b61152b90614445565b89602001518a60400151612ead565b91509150600061156085608001518660a001518560018960c001518a61010001516124d4565b905061158660405180606001604052806000815260200160008152602001606081525090565b600061159560c08b018b61454c565b90509050806000036116065760405180606001604052808481526020016000815260200160006001600160401b038111156115d2576115d2613f17565b6040519080825280601f01601f1916602001820160405280156115fc576020820181803683370190505b5090529150611695565b60005b8181101561167257600061162060c08d018d61454c565b8381811061163057611630614595565b905060200281019061164291906143a8565b61164b90614445565b90508481600001511161165f579250611672565b508061166a8161447a565b915050611609565b50815160000361169557604051637755fda760e01b815260040160405180910390fd5b60006116ae8860a0015189608001518560000151613130565b905060006116c28960800151601284613130565b90508861010001516116e3576116e3818a61012001518b6101400151613194565b6116f2888a606001518461260c565b60006040518060c001604052808d8152602001336001600160a01b031681526020018e6020013581526020018e60a00160208101906117319190613aec565b6001600160a01b0316815260200186815260200160006001600160a01b03168f60e00160208101906117639190613aec565b6001600160a01b031614611789578e60e00160208101906117849190613aec565b61178b565b335b6001600160a01b031690526040516117a691906020016145ab565b60408051601f1981840301815291905290506117cd8a8e836117c88b34614467565b6131d6565b60006117d9848a614467565b90506000811180156117f7575060e08b01516001600160a01b031615155b1561180b5761180b8a8c60e001518361260c565b611816308d33613324565b6118318d8f8561182c8f60800151601287613130565b61334c565b5050505050505050505050506118476001600355565b919050565b61185533612272565b61187257604051637c3ea23f60e01b815260040160405180910390fd5b61187a6126f6565b610e626133f4565b6001303b15806118955750611895612573565b6118b15760405162461bcd60e51b81526004016109b190614043565b604051631d70c8d360e31b81526001600160a01b03831660048201526002604360981b019063eb86469890602401610bd8565b60006118ee6126f6565b6118f661273c565b33321461196d576000600260045460ff16600281111561191857611918613b8f565b14806119495750600160045460ff16600281111561193857611938613b8f565b148015611949575061194933610b4f565b90508061196b57604051630fa0970d60e11b81523360048201526024016109b1565b505b61197d6040830160208401613aec565b6001600160a01b03166119936020840184613aec565b6001600160a01b0316036119ba57604051633b0e2de560e21b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6119dc6020840184613aec565b6001600160a01b03161480156119ff57506119fa60408301836143a8565b353414155b15611a1d57604051637dd7aa2160e01b815260040160405180910390fd5b6000611a293447614467565b600980549192506000611a3b8361447a565b90915550506009546007549092506000906001600160a01b031663f36dd64e33611a6860408801886143a8565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260200135602482015260440160a060405180830381865afa158015611ab5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad991906145be565b90506000611b22846001611af06020890189613aec565b611b0060408a0160208b01613aec565b611b0d60408b018b6143a8565b611b1690614445565b87516020890151612ead565b509050600080611b386080880160608901613aec565b6001600160a01b031614611b5b57611b566080870160608801613aec565b611b5d565b335b90506000611b7683600186604001518760800151613431565b905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee611b9d6040890160208a01613aec565b6001600160a01b031603611bba57611bb5828261257e565b611bd4565b611bd4611bcd6040890160208a01613aec565b838361260c565b6000611be08285614467565b90508015611c9a5760608501516001600160a01b03811615611c585773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee611c2160408b0160208c01613aec565b6001600160a01b031603611c3e57611c39818361257e565b611c98565b611c39611c5160408b0160208c01613aec565b828461260c565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee611c7d60408b0160208c01613aec565b6001600160a01b031603611c9857611c95828861464c565b96505b505b611ca5308733613324565b33877f64f803250cc450b9c5e2cef3ac4c82370f41b8c1e5692f4067b6b96d2430bfcb85611cd660208d018d613aec565b611ce660408e0160208f01613aec565b611cf360408f018f6143a8565b604080516001600160a01b03958616815293851660208501529190931690820152903560608201526080810186905260a081018590524260c082015260e00160405180910390a35050505050506118476001600355565b611d52612c2b565b611d6b60008051602061492183398151915283836134a2565b604051811515906001600160a01b038416907fbe9474bb3e78da7e315cdffa5cfa30b767fcc95bbf44a6197da60228eea1028690600090a35050565b611db033612272565b611dcd57604051637c3ea23f60e01b815260040160405180910390fd5b610e29816134c9565b6001303b1580611de95750611de9612573565b611e055760405162461bcd60e51b81526004016109b190614043565b604051631a33757d60e01b81526001600160a01b03841690631a33757d90611e31908590600401613bc3565b6020604051808303816000875af1158015611e50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e74919061407a565b50505050565b6000468603611e8b575060006120d6565b6007546040516318fa0c2360e21b8152600481018990526000916001600160a01b0316906363e8308c90602401602060405180830381865afa158015611ed5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef991906146ae565b80519091506001600160a01b0316611f245760405163ba8ec24160e01b815260040160405180910390fd5b6000858103611fc45781516040805160008152602081019091526001600160a01b039091169063aa4fc83d908a90611f5b9061351c565b88886040518563ffffffff1660e01b8152600401611f7c94939291906146ca565b602060405180830381865afa158015611f99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fbd919061407a565b90506120d2565b60005b868110156120d0576000612032898984818110611fe657611fe6614595565b9050602002810190611ff89190614717565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061351c92505050565b9050600084600001516001600160a01b031663aa4fc83d8c848b8b6040518563ffffffff1660e01b815260040161206c94939291906146ca565b602060405180830381865afa158015612089573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ad919061407a565b9050838111156120bb578093505b505080806120c89061447a565b915050611fc7565b505b9150505b9695505050505050565b6120e933612272565b61210657604051637c3ea23f60e01b815260040160405180910390fd5b6121206000805160206149218339815191523360006134a2565b60405133907f6cc2c67081f55c2fffb7c008fa995fbbf890f48c7c16fba93d8220f00dc84cc590600090a2565b606061097d6000805160206149218339815191526135b0565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601612194575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa1580156121d8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d87919061407a565b612204612c2b565b6001600160a01b0381166122695760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016109b1565b610e2981612c8b565b6001600160a01b03811660009081527f260b29b219d450563ddb0e5ca806bdadb1e125f7e8c506de0443797dd7122728602052604081205460ff16610d87565b600754604051631a5a276d60e31b815233600482015260009182916001600160a01b039091169063d2d13b68906024016040805180830381865afa1580156122fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612322919061475d565b9050612338848483600001518460200151613431565b949350505050565b61234933612272565b61236657604051637c3ea23f60e01b815260040160405180910390fd5b6004805482919060ff1916600183600281111561238557612385613b8f565b021790555080600281111561239c5761239c613b8f565b6040517f332a9f1d3bd9b0f7abbd95838fed6b417589632d0eb33f2d8ae6e2aa17178efd90600090a250565b6123d133612272565b6123ee57604051637c3ea23f60e01b815260040160405180910390fd5b60005b81811015611248573683838381811061240c5761240c614595565b905060400201905080602001602081019061242791906147b2565b156124415761244161243c6020830183613aec565b61361c565b61246c600560066124556020850185613aec565b61246560408601602087016147b2565b606461364f565b5061247d60408201602083016147b2565b151561248c6020830183613aec565b6001600160a01b03167f1470aed653fa8a8ce4c7b2f41287634199f7ec3c4f5fd0ace97d82cf006beec360405160405180910390a350806124cc8161447a565b9150506123f1565b60008082806124e1575083155b905060008515806124ef5750815b61251a57620186a06125018682614467565b61250b90896147cf565b61251591906147e6565b61251c565b865b9050600061252b8a8a84613130565b905086806125365750825b6125635761254786620186a0614467565b612554620186a0836147cf565b61255e91906147e6565b612565565b805b9a9950505050505050505050565b600061097d33612272565b604080516000808252602082019092526001600160a01b0384169083906040516125a89190614808565b60006040518083038185875af1925050503d80600081146125e5576040519150601f19603f3d011682016040523d82523d6000602084013e6125ea565b606091505b505090508061124857604051632e05b05360e21b815260040160405180910390fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916126689190614808565b6000604051808303816000865af19150503d80600081146126a5576040519150601f19603f3d011682016040523d82523d6000602084013e6126aa565b606091505b509150915060008280156126d65750815115806126d65750818060200190518101906126d69190614093565b905080610c0657604051632fdb1b7f60e11b815260040160405180910390fd5b60005460ff1615610e625760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016109b1565b60026003540361278e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016109b1565b6002600355565b60075460405163154d267d60e21b8152600481018490526000916001600160a01b03169063553499f490602401602060405180830381865afa1580156127df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280391906146ae565b80519091506001600160a01b031661282e57604051630b24de4b60e01b815260040160405180910390fd5b600854604051638758e33960e01b8152336004820152602481018590526000916001600160a01b031690638758e33990604401602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a2919061407a565b6008546040516227421b60e61b8152336004820152602481018790529192506001600160a01b0316906309d086c090604401600060405180830381600087803b1580156128ee57600080fd5b505af1158015612902573d6000803e3d6000fd5b505050506000811115611e74578215612996578151604051634b15b2a960e01b815260048101839052336024820152600160448201526001600160a01b0390911690634b15b2a9906064016020604051808303816000875af115801561296c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061299091906143c8565b50611e74565b600082600001516001600160a01b0316632c966a346040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129fe91906143c8565b6040516340c10f1960e01b8152336004820152602481018490529091506000906001600160a01b038316906340c10f19906044016020604051808303816000875af1158015612a51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a759190614093565b905080610c06576040516320aaed5f60e21b815260040160405180910390fd5b60005460ff16610e625760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016109b1565b612ae6612a95565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60008060005a905083811015925082612b4a576000612b54565b612b548482614467565b915050915091565b60a08101516040808301516080840151516008549251631e9f7a9b60e01b81526001600160a01b03808616600483015260248201849052604482018390529293919290911690631e9f7a9b90606401600060405180830381600087803b158015612bc557600080fd5b505af1158015612bd9573d6000803e3d6000fd5b5050855160408051868152602081018690526001600160a01b03881694509192507fb9e12bbbbed208a973bc1ec9604e1f6d7f4b91b193fc2e1150df974b7d16635b910160405180910390a350505050565b6000546001600160a01b03610100909104163314610e625760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109b1565b600080546001600160a01b03838116610100818102610100600160a81b0319851617855560405193049190911692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35050565b6000846001600160a01b0316846001600160a01b031603612d0757508151612dfe565b86516001600160a01b0316612d2f5760405163ebb12eb360e01b815260040160405180910390fd5b6000612d3a85612166565b9050612d4f8689602001518660000151613672565b600088600001516001600160a01b03168560400151604051612d719190614808565b6000604051808303816000865af19150503d8060008114612dae576040519150601f19603f3d011682016040523d82523d6000602084013e612db3565b606091505b5050905080612dd557604051633e1f5ce560e11b815260040160405180910390fd5b612de5878a602001516000613672565b81612def87612166565b612df99190614467565b925050505b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03851601612e3257612e2d828261257e565b612e3d565b612e3d84838361260c565b6020808401518451604080519283526001600160a01b0389811694840194909452878416908301526060820152608081018390529083169087907f26e7a43f3221294fff6b57719103b3bfdeb1c06dac5c3973de3e55932e7c1b3b9060a00160405180910390a350505050505050565b6000806000612ebb87612166565b905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03891601612f9a576001600160a01b038516612f095760405163ebb12eb360e01b815260040160405180910390fd5b6000856001600160a01b031687600001518860400151604051612f2c9190614808565b60006040518083038185875af1925050503d8060008114612f69576040519150601f19603f3d011682016040523d82523d6000602084013e612f6e565b606091505b5050905080612f9057604051633e1f5ce560e11b815260040160405180910390fd5b508551915061308e565b612faa883330896000015161375c565b866001600160a01b0316886001600160a01b031614613089576001600160a01b038516612fea5760405163ebb12eb360e01b815260040160405180910390fd5b612ff988858860000151613672565b6000856001600160a01b031687604001516040516130179190614808565b6000604051808303816000865af19150503d8060008114613054576040519150601f19603f3d011682016040523d82523d6000602084013e613059565b606091505b505090508061307b57604051633e1f5ce560e11b815260040160405180910390fd5b61308789866000613672565b505b600091505b8061309888612166565b6130a29190614467565b9250336001600160a01b03168915158b7f580273492d266e8e27b4253a13c46e1c74823e94794f9ad186ca8fe8b109e3ef89602001518c8c8c600001518a60405161311b9594939291909485526001600160a01b0393841660208601529190921660408401526060830191909152608082015260a00190565b60405180910390a45097509795505050505050565b600083830361314057508061318d565b8383111561316e576131528484614467565b61315d90600a6148fe565b61316790836147cf565b905061318d565b6131788385614467565b61318390600a6148fe565b61316790836147e6565b9392505050565b818310156131b557604051632220ee1360e11b815260040160405180910390fd5b808311156112485760405163341cc20160e21b815260040160405180910390fd5b83516001600160a01b03166131fe5760405163ba8ec24160e01b815260040160405180910390fd5b83516000906001600160a01b031663aa4fc83d608086013585613225610100890189614717565b6040518563ffffffff1660e01b815260040161324494939291906146ca565b602060405180830381865afa158015613261573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613285919061407a565b9050808210156132a757604051625a4bb360e21b815260040160405180910390fd5b84516001600160a01b0316636ea9cec9826080870135866132cc6101008a018a614717565b6040518663ffffffff1660e01b81526004016132eb94939291906146ca565b6000604051808303818588803b15801561330457600080fd5b505af1158015613318573d6000803e3d6000fd5b50505050505050505050565b600061333a836001600160a01b03861631614467565b90508015611e7457611e74828261257e565b336080840135857fc2ad425216cf8ac56ecd38af0315ed35266cb6771f34fc27e1f0cde1a5b3eb6a613385610100880160e08901613aec565b873561339760608a0160408b01613aec565b6133a760c08b0160a08c01613aec565b604080516001600160a01b03958616815260208101949094529184168383015290921660608201526080810188905260a081018790524260c082015290519081900360e00190a450505050565b6133fc6126f6565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612b133390565b6000818061343d575082155b15613449575083612338565b836134775761345b83620186a0614467565b613468620186a0876147cf565b61347291906147e6565b613499565b620186a06134858482614467565b61348f90876147cf565b61349991906147e6565b95945050505050565b60008381526001602090815260408083206002909252909120611e7491908484606461364f565b6134d28161361c565b600780546001600160a01b0319166001600160a01b0383169081179091556040517f278c70ced5f3e0e5eeb385b5ff9cb735748ba00a625147e66065ed48fc1562cd90600090a250565b606060006040518060c001604052806000815260200160006001600160a01b031681526020016000815260200160006001600160a01b031681526020016040518060600160405280600081526020016000815260200186815250815260200160006001600160a01b031681525060405160200161359991906145ab565b60408051601f198184030181529190529392505050565b60008181526001602090815260409182902080548351818402810184019094528084526060939283018282801561361057602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116135f2575b50505050509050919050565b6001600160a01b0381163b610e2957604051638c50d7cd60e01b81526001600160a01b03821660048201526024016109b1565b60008261366657613661868686613857565b6120d6565b6120d68686868561397f565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916136ce9190614808565b6000604051808303816000865af19150503d806000811461370b576040519150601f19603f3d011682016040523d82523d6000602084013e613710565b606091505b5091509150600082801561373c57508151158061373c57508180602001905181019061373c9190614093565b905080610c065760405163b45d44e760e01b815260040160405180910390fd5b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291516000928392908816916137c09190614808565b6000604051808303816000865af19150503d80600081146137fd576040519150601f19603f3d011682016040523d82523d6000602084013e613802565b606091505b5091509150600082801561382e57508151158061382e57508180602001905181019061382e9190614093565b90508061384e57604051632d9d5b4160e01b815260040160405180910390fd5b50505050505050565b6001600160a01b0381166000908152602083905260409020805460ff1690811561397757600180820154865490916000916138929190614467565b905080821461391f5760008782815481106138af576138af614595565b9060005260206000200160009054906101000a90046001600160a01b03169050808884815481106138e2576138e2614595565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815290879052604090206001018290555b8680548061392f5761392f61490a565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038716825287905260408120805460ff191681556001015550505b509392505050565b6001600160a01b03821660009081526020849052604090205460ff1615801561233857845482116139c35760405163b1655e3360e01b815260040160405180910390fd5b6040805180820182526001808252875460208084019182526001600160a01b039790971660008181529888529388209251835460ff19169015151783555191810191909155865490810187559585529290932090930180546001600160a01b0319169091179055919050565b6020808252825182820181905260009190848201906040850190845b81811015613a705783516001600160a01b031683529284019291840191600101613a4b565b50909695505050505050565b8015158114610e2957600080fd5b600080600080600060a08688031215613aa257600080fd5b853594506020860135935060408601359250606086013591506080860135613ac981613a7c565b809150509295509295909350565b6001600160a01b0381168114610e2957600080fd5b600060208284031215613afe57600080fd5b813561318d81613ad7565b60008060408385031215613b1c57600080fd5b8235613b2781613ad7565b946020939093013593505050565b600080600060608486031215613b4a57600080fd5b8335613b5581613ad7565b92506020840135613b6581613ad7565b929592945050506040919091013590565b600060208284031215613b8857600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60038110610e2957634e487b7160e01b600052602160045260246000fd5b60208101613bd083613ba5565b91905290565b60008083601f840112613be857600080fd5b5081356001600160401b03811115613bff57600080fd5b602083019150836020828501011115613c1757600080fd5b9250929050565b600080600060408486031215613c3357600080fd5b8335925060208401356001600160401b03811115613c5057600080fd5b613c5c86828701613bd6565b9497909650939450505050565b600060808284031215613c7b57600080fd5b50919050565b60008060a08385031215613c9457600080fd5b613c9e8484613c69565b915060808301356001600160401b03811115613cb957600080fd5b830160c08186031215613ccb57600080fd5b809150509250929050565b600060208284031215613ce857600080fd5b81356001600160401b03811115613cfe57600080fd5b8201610120818503121561318d57600080fd5b600060208284031215613d2357600080fd5b81356001600160401b03811115613d3957600080fd5b61233884828501613c69565b60008060408385031215613d5857600080fd5b8235613d6381613ad7565b91506020830135613ccb81613a7c565b60038110610e2957600080fd5b60008060408385031215613d9357600080fd5b8235613d9e81613ad7565b91506020830135613ccb81613d73565b60008060008060008060808789031215613dc757600080fd5b863595506020870135945060408701356001600160401b0380821115613dec57600080fd5b818901915089601f830112613e0057600080fd5b813581811115613e0f57600080fd5b8a60208260051b8501011115613e2457600080fd5b602083019650809550506060890135915080821115613e4257600080fd5b50613e4f89828a01613bd6565b979a9699509497509295939492505050565b60008060408385031215613e7457600080fd5b823591506020830135613ccb81613a7c565b600060208284031215613e9857600080fd5b813561318d81613d73565b60008060208385031215613eb657600080fd5b82356001600160401b0380821115613ecd57600080fd5b818501915085601f830112613ee157600080fd5b813581811115613ef057600080fd5b8660208260061b8501011115613f0557600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613f4f57613f4f613f17565b60405290565b604051606081016001600160401b0381118282101715613f4f57613f4f613f17565b60405160c081016001600160401b0381118282101715613f4f57613f4f613f17565b60405161016081016001600160401b0381118282101715613f4f57613f4f613f17565b604051601f8201601f191681016001600160401b0381118282101715613fe457613fe4613f17565b604052919050565b805161184781613a7c565b60006080828403121561400957600080fd5b614011613f2d565b825181526020830151602082015260408301516040820152606083015161403781613a7c565b60608201529392505050565b60208082526019908201527f426c617374436f6e6669673a20556e617574686f72697a656400000000000000604082015260600190565b60006020828403121561408c57600080fd5b5051919050565b6000602082840312156140a557600080fd5b815161318d81613a7c565b6000606082840312156140c257600080fd5b6140ca613f55565b9050813581526020808301358183015260408301356001600160401b03808211156140f457600080fd5b818501915085601f83011261410857600080fd5b81358181111561411a5761411a613f17565b61412c601f8201601f19168501613fbc565b9150808252868482850101111561414257600080fd5b808484018584013760008482840101525080604085015250505092915050565b60006020828403121561417457600080fd5b81356001600160401b038082111561418b57600080fd5b9083019060c0828603121561419f57600080fd5b6141a7613f77565b8235815260208301356141b981613ad7565b60208201526040838101359082015260608301356141d681613ad7565b60608201526080830135828111156141ed57600080fd5b6141f9878286016140b0565b60808301525060a0830135925061420f83613ad7565b60a0810192909252509392505050565b805161184781613ad7565b60006080828403121561423c57600080fd5b614244613f2d565b825161424f81613ad7565b8152602083015161425f81613ad7565b6020820152604083015161427281613ad7565b60408201526060928301519281019290925250919050565b60005b838110156142a557818101518382015260200161428d565b50506000910152565b600081518084526142c681602086016020860161428a565b601f01601f19169290920160200192915050565b805182526000602082015160018060a01b038082166020860152604084015160408601528060608501511660608601525050608082015160c06080850152805160c0850152602081015160e08501526040810151905060606101008501526143466101208501826142ae565b905060a083015161397760a08601826001600160a01b03169052565b600060018060a01b03808551168352806020860151166020840152806040860151166040840152506060840151606083015260a0608083015261233860a08301846142da565b60008235605e198336030181126143be57600080fd5b9190910192915050565b6000602082840312156143da57600080fd5b815161318d81613ad7565b6000608082840312156143f757600080fd5b6143ff613f2d565b823561440a81613ad7565b8152602083013561441a81613ad7565b6020820152604083013561442d81613ad7565b60408201526060928301359281019290925250919050565b6000610d8736836140b0565b634e487b7160e01b600052601160045260246000fd5b81810381811115610d8757610d87614451565b60006001820161448c5761448c614451565b5060010190565b600061016082840312156144a657600080fd5b6144ae613f99565b6144b78361421f565b81526144c56020840161421f565b60208201526144d66040840161421f565b60408201526144e76060840161421f565b60608201526080830151608082015260a083015160a082015260c083015160c082015261451660e0840161421f565b60e0820152610100614529818501613fec565b908201526101208381015190820152610140928301519281019290925250919050565b6000808335601e1984360301811261456357600080fd5b8301803591506001600160401b0382111561457d57600080fd5b6020019150600581901b3603821315613c1757600080fd5b634e487b7160e01b600052603260045260246000fd5b602081526000610d8460208301846142da565b600060a082840312156145d057600080fd5b60405160a081018181106001600160401b03821117156145f2576145f2613f17565b604052825161460081613ad7565b8152602083015161461081613ad7565b602082015260408381015190820152606083015161462d81613ad7565b6060820152608083015161464081613a7c565b60808201529392505050565b80820180821115610d8757610d87614451565b60006020828403121561467157600080fd5b604051602081018181106001600160401b038211171561469357614693613f17565b806040525080915082516146a681613ad7565b905292915050565b6000602082840312156146c057600080fd5b610d84838361465f565b8481526060602082015260006146e360608301866142ae565b8281036040840152838152838560208301376000602085830101526020601f19601f86011682010191505095945050505050565b6000808335601e1984360301811261472e57600080fd5b8301803591506001600160401b0382111561474857600080fd5b602001915036819003821315613c1757600080fd5b60006040828403121561476f57600080fd5b604051604081018181106001600160401b038211171561479157614791613f17565b6040528251815260208301516147a681613a7c565b60208201529392505050565b6000602082840312156147c457600080fd5b813561318d81613a7c565b8082028115828204841417610d8757610d87614451565b60008261480357634e487b7160e01b600052601260045260246000fd5b500490565b600082516143be81846020870161428a565b600181815b8085111561485557816000190482111561483b5761483b614451565b8085161561484857918102915b93841c939080029061481f565b509250929050565b60008261486c57506001610d87565b8161487957506000610d87565b816001811461488f5760028114614899576148b5565b6001915050610d87565b60ff8411156148aa576148aa614451565b50506001821b610d87565b5060208310610133831016604e8410600b84101617156148d8575081810a610d87565b6148e2838361481a565b80600019048211156148f6576148f6614451565b029392505050565b6000610d84838361485d565b634e487b7160e01b600052603160045260246000fdfe6d439300980e333f0256d64be2c9f67e86f4493ce25f82498d6db7f4be3d9e6fa26469706673582212207ea73b3cad3a79b1a27802e0c79ea4b52fa59fc183ca6e362478e048bce61fee64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000f19ea8e63256992a823262c71568b0bb27ce146f000000000000000000000000bfc3b856b9bcc792875e79fc8ffcc09028aad40600000000000000000000000000000000000000000000000000000000000001f400000000000000000000000072e28c7f34100afefc399fcc0ae041b8fe5841ae00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _registry (address): 0xF19EA8e63256992a823262C71568b0bb27cE146f
Arg [1] : _variableBalanceRecords (address): 0xbFc3b856b9BCC792875E79Fc8FFcc09028AAD406
Arg [2] : _actionIdOffset (uint256): 500
Arg [3] : _owner (address): 0x72E28c7F34100AfefC399fcc0AE041B8fe5841AE
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000f19ea8e63256992a823262c71568b0bb27ce146f
Arg [1] : 000000000000000000000000bfc3b856b9bcc792875e79fc8ffcc09028aad406
Arg [2] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [3] : 00000000000000000000000072e28c7f34100afefc399fcc0ae041b8fe5841ae
Arg [4] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.