Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 39 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Receive State Ch... | 15230953 | 885 days ago | IN | 0 ETH | 0.0025028 | ||||
Receive State Ch... | 15230953 | 885 days ago | IN | 0 ETH | 0.00250583 | ||||
Receive State Ch... | 15230953 | 885 days ago | IN | 0 ETH | 0.00249405 | ||||
Receive State Ch... | 15230952 | 885 days ago | IN | 0 ETH | 0.00249477 | ||||
Receive State Ch... | 15230952 | 885 days ago | IN | 0 ETH | 0.06101216 | ||||
Receive State Ch... | 15230952 | 885 days ago | IN | 0 ETH | 0.00249512 | ||||
Receive State Ch... | 15230952 | 885 days ago | IN | 0 ETH | 0.00250583 | ||||
Receive State Ch... | 15230952 | 885 days ago | IN | 0 ETH | 0.00249405 | ||||
Receive State Ch... | 15230951 | 885 days ago | IN | 0 ETH | 0.05692563 | ||||
Receive State Ch... | 15230951 | 885 days ago | IN | 0 ETH | 0.00249477 | ||||
Receive State Ch... | 15230951 | 885 days ago | IN | 0 ETH | 0.00249512 | ||||
Receive State Ch... | 15230951 | 885 days ago | IN | 0 ETH | 0.00232755 | ||||
Receive State Ch... | 15230951 | 885 days ago | IN | 0 ETH | 0.05691465 | ||||
Receive State Ch... | 15230951 | 885 days ago | IN | 0 ETH | 0.05090314 | ||||
Receive State Ch... | 15230951 | 885 days ago | IN | 0 ETH | 0.00232789 | ||||
Receive State Ch... | 15230951 | 885 days ago | IN | 0 ETH | 0.03337902 | ||||
Vote Proposal | 15230945 | 885 days ago | IN | 0 ETH | 0.00725745 | ||||
Vote Proposal | 15230943 | 885 days ago | IN | 0 ETH | 0.01293541 | ||||
Renounce Admin | 15217541 | 887 days ago | IN | 0 ETH | 0.00066472 | ||||
Admin Set Resour... | 15216704 | 887 days ago | IN | 0 ETH | 0.00304983 | ||||
Admin Set Resour... | 15210337 | 888 days ago | IN | 0 ETH | 0.00101896 | ||||
Renounce Admin | 15210235 | 888 days ago | IN | 0 ETH | 0.00047434 | ||||
Receive State Ch... | 15199274 | 890 days ago | IN | 0 ETH | 0.00133273 | ||||
Receive State Ch... | 15199274 | 890 days ago | IN | 0 ETH | 0.00133444 | ||||
Receive State Ch... | 15199274 | 890 days ago | IN | 0 ETH | 0.00132855 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
Bridge
Compiler Version
v0.8.11+commit.d7f03943
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity ^0.8.0; import "@openzeppelin/contracts/security/Pausable.sol"; import "@openzeppelin/contracts/utils/math/SafeCast.sol"; import "./BridgeAccessControl.sol"; import "../interfaces/IERCHandler.sol"; import "../interfaces/IDepositExecute.sol"; import "../interfaces/IExecuteRollup.sol"; import "../interfaces/ISettle.sol"; import "../handlers/RollupHandler.sol"; /// @notice This contract facilitates the following: /// - deposits /// - creation and voting of deposit proposals /// - deposit executions /// - rollup executions and state settlements contract Bridge is Pausable, BridgeAccessControl, IExecuteRollup { using SafeCast for *; /// @notice Limit relayers number because proposal can fit only so much votes uint256 public constant MAX_RELAYERS = 200; uint8 public immutable _domainID; uint8 public _relayerThreshold; uint128 public _fee; uint40 public _expiry; enum ProposalStatus { Inactive, Active, Passed, Executed, Cancelled } struct Proposal { ProposalStatus _status; uint200 _yesVotes; // bitmap, 200 maximum votes uint8 _yesVotesTotal; uint40 _proposedBlock; // 1099511627775 maximum block } // destinationDomainID => number of deposits mapping(uint8 => uint64) public _depositCounts; // resourceID => handler address mapping(bytes32 => address) public _resourceIDToHandlerAddress; // destinationDomainID + depositNonce => dataHash => Proposal mapping(uint72 => mapping(bytes32 => Proposal)) private _proposals; event RelayerThresholdChanged(uint256 newThreshold); event RelayerAdded(address relayer); event RelayerRemoved(address relayer); event Deposit( uint8 destinationDomainID, bytes32 resourceID, uint64 depositNonce, address indexed user, bytes data, bytes handlerResponse ); event ProposalEvent( uint8 originDomainID, bytes32 resourceID, uint64 depositNonce, ProposalStatus status, bytes32 dataHash ); event ProposalVote( uint8 originDomainID, uint64 depositNonce, ProposalStatus status, bytes32 dataHash ); event FailedHandlerExecution(bytes lowLevelData); event ExecuteRollup( uint8 destDomainID, bytes32 resourceID, bytes32 destResourceID, uint64 nonce, uint64 batchSize, uint256 startBlock, bytes32 stateChangeHash ); event ReceiveStateChanges( uint8 originDomainID, bytes32 resourceID, uint64 nonce, uint64 batchIndex, uint64 totalBatches ); bytes32 public constant RELAYER_ROLE = keccak256("RELAYER_ROLE"); modifier onlyAdmin() { _onlyAdmin(); _; } modifier onlyAdminOrRelayer() { _onlyAdminOrRelayer(); _; } modifier onlyRelayers() { _onlyRelayers(); _; } /// @notice Initializes Bridge, creates and grants {msg.sender} the admin role, /// creates and grants {initialRelayers} the relayer role. /// /// @param domainID ID of chain the Bridge contract exists on. /// @param initialRelayers Addresses that should be initially granted the relayer role. /// @param initialRelayerThreshold Number of votes needed for a deposit proposal to be considered passed. constructor( uint8 domainID, address[] memory initialRelayers, uint256 initialRelayerThreshold, uint256 fee, uint256 expiry ) { _domainID = domainID; _relayerThreshold = initialRelayerThreshold.toUint8(); _fee = fee.toUint128(); _expiry = expiry.toUint40(); _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); for (uint256 i = 0; i < initialRelayers.length; i++) { grantRole(RELAYER_ROLE, initialRelayers[i]); } } /// @notice Removes admin role from {msg.sender} and grants it to {newAdmin}. /// /// @notice Requirements: /// - It must be called by only admin. /// /// @param newAdmin Address that admin role will be granted to. function renounceAdmin(address newAdmin) external onlyAdmin { require(msg.sender != newAdmin, "Cannot renounce oneself"); grantRole(DEFAULT_ADMIN_ROLE, newAdmin); renounceRole(DEFAULT_ADMIN_ROLE, msg.sender); } /// @notice Pauses deposits, proposal creation and voting, and deposit executions. /// /// @notice Requirements: /// - It must be called by only admin. function adminPauseTransfers() external onlyAdmin { _pause(); } /// @notice Unpauses deposits, proposal creation and voting, and deposit executions. /// /// @notice Requirements: /// - It must be called by only admin. function adminUnpauseTransfers() external onlyAdmin { _unpause(); } /// @notice Modifies the number of votes required for a proposal to be considered passed. /// /// @notice Requirements: /// - It must be called by only admin. /// /// @param newThreshold Value {_relayerThreshold} will be changed to. /// /// @notice Emits {RelayerThresholdChanged} event. function adminChangeRelayerThreshold(uint256 newThreshold) external onlyAdmin { _relayerThreshold = newThreshold.toUint8(); emit RelayerThresholdChanged(newThreshold); } /// @notice Grants {relayerAddress} the relayer role. /// /// @notice Requirements: /// - It must be called by only admin. /// - {relayerAddress} must not already has relayer role. /// - The number of current relayer must be less than {MAX_RELAYERS} /// /// @param relayerAddress Address of relayer to be added. /// /// @notice Emits {RelayerAdded} event. /// /// @dev admin role is checked in grantRole() function adminAddRelayer(address relayerAddress) external { require( !hasRole(RELAYER_ROLE, relayerAddress), "addr already has relayer role!" ); require(_totalRelayers() < MAX_RELAYERS, "relayers limit reached"); grantRole(RELAYER_ROLE, relayerAddress); emit RelayerAdded(relayerAddress); } /// @notice Removes relayer role for {relayerAddress}. /// /// @notice Requirements: /// - It must be called by only admin. /// - {relayerAddress} must has relayer role. /// /// @param relayerAddress Address of relayer to be removed. /// /// @notice Emits {RelayerRemoved} event. /// /// @dev admin role is checked in revokeRole() function adminRemoveRelayer(address relayerAddress) external { require( hasRole(RELAYER_ROLE, relayerAddress), "addr doesn't have relayer role!" ); revokeRole(RELAYER_ROLE, relayerAddress); emit RelayerRemoved(relayerAddress); } /// @notice Sets a new resource for handler contracts that use the IERCHandler interface, /// and maps the {handlerAddress} to {resourceID} in {_resourceIDToHandlerAddress}. /// /// @notice Requirements: /// - It must be called by only admin. /// /// @param handlerAddress Address of handler resource will be set for. /// @param resourceID ResourceID to be used when making deposits. /// @param tokenAddress Address of contract to be called when a deposit is made and a deposited is executed. function adminSetResource( address handlerAddress, bytes32 resourceID, address tokenAddress ) external onlyAdmin { _resourceIDToHandlerAddress[resourceID] = handlerAddress; IERCHandler handler = IERCHandler(handlerAddress); handler.setResource(resourceID, tokenAddress); } /// @notice Sets a resource as burnable for handler contracts that use the IERCHandler interface. /// /// @notice Requirements: /// - It must be called by only admin. /// /// @param handlerAddress Address of handler resource will be set for. /// @param tokenAddress Address of contract to be called when a deposit is made and a deposited is executed. function adminSetBurnable(address handlerAddress, address tokenAddress) external onlyAdmin { IERCHandler handler = IERCHandler(handlerAddress); handler.setBurnable(tokenAddress); } /// @notice Sets the nonce for the specific domainID. /// /// @notice Requirements: /// - It must be called by only admin. /// - {nonce} must be greater than the current nonce. /// /// @param domainID Domain ID for increasing nonce. /// @param nonce The nonce value to be set. function adminSetDepositNonce(uint8 domainID, uint64 nonce) external onlyAdmin { // solhint-disable-next-line reason-string require( nonce > _depositCounts[domainID], "Does not allow decrements of the nonce" ); _depositCounts[domainID] = nonce; } /// @notice Changes deposit fee. /// /// @notice Requirements: /// - It must be called by only admin. /// - The current fee must not be equal to new fee. /// /// @param newFee Value {_fee} will be updated to. // slither-disable-next-line events-maths function adminChangeFee(uint256 newFee) external onlyAdmin { require(_fee != newFee, "Current fee is equal to new fee"); _fee = newFee.toUint128(); } /// @notice Used to manually withdraw funds from ERC safes. /// /// @notice Requirements: /// - It must be called by only admin. /// /// @param handlerAddress Address of handler to withdraw from. /// @param data ABI-encoded withdrawal params relevant to the specified handler. function adminWithdraw(address handlerAddress, bytes memory data) external onlyAdmin { IERCHandler handler = IERCHandler(handlerAddress); handler.withdraw(data); } /// @notice Initiates a transfer using a specified handler contract. /// /// @notice Requirements: /// - Bridge must be not be paused. /// - {msg.value} must be greater than or equal to {_fee}. /// - Handler must be registered with {resourceID}. /// /// @param destinationDomainID ID of chain deposit will be bridged to. /// @param resourceID ResourceID used to find address of handler to be used for deposit. /// @param data Additional data to be passed to specified handler. /// /// @notice Emits {Deposit} event with all necessary parameters and a handler response. /// - ERC20Handler: responds with an empty data. /// - ERC721Handler: responds with the deposited token metadata acquired by calling a tokenURI method in the token contract. /// - ERC1155Handler: responds with an empty data. /// - NativeHandlerSettleable: responds with an empty data. /// /// @dev RollupHandler doesn't support this function. function deposit( uint8 destinationDomainID, bytes32 resourceID, bytes calldata data ) external payable whenNotPaused { require(msg.value >= _fee, "Incorrect fee supplied"); address handler = _resourceIDToHandlerAddress[resourceID]; require(handler != address(0), "resourceID not mapped to handler"); uint64 depositNonce = ++_depositCounts[destinationDomainID]; IDepositExecute depositHandler = IDepositExecute(handler); bytes memory handlerResponse = depositHandler.deposit{ value: msg.value - _fee }(resourceID, msg.sender, data); // slither-disable-next-line reentrancy-events emit Deposit( destinationDomainID, resourceID, depositNonce, msg.sender, data, handlerResponse ); } /// @notice When called, {msg.sender} will be marked as voting in favor of proposal. /// /// @notice Requirements: /// - It must be called by only relayer. /// - Bridge must not be paused. /// - Handler must be registered with {resourceID}. /// - Proposal must not have already been passed or executed. /// - Relayer must vote only once. /// /// @param domainID ID of chain deposit originated from. /// @param depositNonce ID of deposited generated by origin Bridge contract. /// @param data Data originally provided when deposit was made. /// /// @notice Emits {ProposalEvent} event with status indicating the proposal status. /// @notice Emits {ProposalVote} event. function voteProposal( uint8 domainID, uint64 depositNonce, bytes32 resourceID, bytes calldata data ) external onlyRelayers whenNotPaused { address handler = _resourceIDToHandlerAddress[resourceID]; uint72 nonceAndID = (uint72(depositNonce) << 8) | uint72(domainID); bytes32 dataHash = keccak256(abi.encodePacked(handler, data)); Proposal memory proposal = _proposals[nonceAndID][dataHash]; require( _resourceIDToHandlerAddress[resourceID] != address(0), "no handler for resourceID" ); if (proposal._status == ProposalStatus.Passed) { executeProposal(domainID, depositNonce, data, resourceID, true); return; } // Passed case is considered already // Now we can consider Inactive, Active cases // solhint-disable-next-line reason-string require( uint256(proposal._status) <= 1, "proposal already executed/cancelled" ); require(!_hasVoted(proposal, msg.sender), "relayer already voted"); if (proposal._status == ProposalStatus.Inactive) { proposal = Proposal({ _status: ProposalStatus.Active, _yesVotes: 0, _yesVotesTotal: 0, _proposedBlock: uint40(block.number) // Overflow is desired. }); emit ProposalEvent( domainID, resourceID, depositNonce, ProposalStatus.Active, dataHash ); } else if (uint40(block.number - proposal._proposedBlock) > _expiry) { // if the number of blocks that has passed since this proposal was // submitted exceeds the expiry threshold set, cancel the proposal proposal._status = ProposalStatus.Cancelled; emit ProposalEvent( domainID, resourceID, depositNonce, ProposalStatus.Cancelled, dataHash ); } if (proposal._status != ProposalStatus.Cancelled) { proposal._yesVotes = (proposal._yesVotes | _relayerBit(msg.sender)) .toUint200(); proposal._yesVotesTotal++; // TODO: check if bit counting is cheaper. emit ProposalVote( domainID, depositNonce, proposal._status, dataHash ); // Finalize if _relayerThreshold has been reached if (proposal._yesVotesTotal >= _relayerThreshold) { proposal._status = ProposalStatus.Passed; emit ProposalEvent( domainID, resourceID, depositNonce, ProposalStatus.Passed, dataHash ); } } _proposals[nonceAndID][dataHash] = proposal; // slither-disable-next-line incorrect-equality if (proposal._status == ProposalStatus.Passed) { executeProposal(domainID, depositNonce, data, resourceID, false); } } /// @notice Cancels a deposit proposal that has not been executed yet. /// /// @notice Requirements: /// - It must be called by only relayer or admin. /// - Bridge must not be paused. /// - Proposal must be past expiry threshold. /// /// @param domainID ID of chain deposit originated from. /// @param depositNonce ID of deposited generated by origin Bridge contract. /// @param dataHash Hash of data originally provided when deposit was made. /// /// @notice Emits {ProposalEvent} event with status {Cancelled}. function cancelProposal( uint8 domainID, bytes32 resourceID, uint64 depositNonce, bytes32 dataHash ) external onlyAdminOrRelayer { uint72 nonceAndID = (uint72(depositNonce) << 8) | uint72(domainID); Proposal memory proposal = _proposals[nonceAndID][dataHash]; ProposalStatus currentStatus = proposal._status; require( currentStatus == ProposalStatus.Active || currentStatus == ProposalStatus.Passed, "Proposal cannot be cancelled" ); require( uint40(block.number - proposal._proposedBlock) > _expiry, "Proposal not at expiry threshold" ); proposal._status = ProposalStatus.Cancelled; _proposals[nonceAndID][dataHash] = proposal; emit ProposalEvent( domainID, resourceID, depositNonce, ProposalStatus.Cancelled, dataHash ); } /// @notice Transfers eth in the contract to the specified addresses. The parameters addrs and amounts are mapped 1-1. /// This means that the address at index 0 for addrs will receive the amount (in WEI) from amounts at index 0. /// /// @param addrs Array of addresses to transfer {amounts} to. /// @param amounts Array of amonuts to transfer to {addrs}. function transferFunds( address payable[] calldata addrs, uint256[] calldata amounts ) external onlyAdmin { require( addrs.length == amounts.length, "addrs[], amounts[]: diff length" ); for (uint256 i = 0; i < addrs.length; i++) { // slither-disable-next-line calls-loop,low-level-calls (bool success, ) = addrs[i].call{value: amounts[i]}(""); require(success, "ether transfer failed"); } } /// @notice Executes rollup. /// /// @notice Requirements: /// - Bridge must not be paused. /// - Handler must be registered with {resourceID}. /// - {msg.sender} must be registered in handler. /// /// @notice Emits {ExecuteRollup} event which is handled by relayer. function executeRollup( uint8 destDomainID, bytes32 resourceID, uint64 batchSize, uint256 startBlock, bytes32 stateChangeHash ) external override whenNotPaused { address handlerAddress = _resourceIDToHandlerAddress[resourceID]; require(handlerAddress != address(0), "invalid resource ID"); uint64 nonce = ++_depositCounts[destDomainID]; // Note: The source resource ID is identical to the destination resource ID. bytes32 destResourceID = RollupHandler(handlerAddress) ._tokenContractAddressToResourceID(msg.sender); require(destResourceID != bytes32(0), "invalid source resource"); emit ExecuteRollup( destDomainID, resourceID, destResourceID, nonce, batchSize, startBlock, stateChangeHash ); } /// @notice Receives state changes. /// /// @notice Requirements: /// - Handler must be registered with {resourceID}. /// /// @dev It can be called by anyone. function receiveStateChanges( uint8 originDomainID, bytes32 resourceID, uint64 nonce, bytes calldata data, bytes32[] calldata proof ) external whenNotPaused { address rollupHandlerAddress = _resourceIDToHandlerAddress[resourceID]; require( rollupHandlerAddress != address(0), "no handler for resourceID" ); ( RollupInfo memory rollupInfo, address settleableAddress ) = RollupHandler(rollupHandlerAddress).getRollupInfo( originDomainID, resourceID, nonce ); ISettle(settleableAddress).settle(rollupInfo, data, proof); uint64 batchIndex = abi.decode(data, (uint64)); // slither-disable-next-line reentrancy-events emit ReceiveStateChanges( originDomainID, resourceID, nonce, batchIndex, rollupInfo.totalBatches ); } /// @notice Returns a proposal. /// /// @param originDomainID Chain ID deposit originated from. /// @param depositNonce ID of proposal generated by proposal's origin Bridge contract. /// @param dataHash Hash of data to be provided when deposit proposal is executed. /// @return Proposal which consists of: /// - _dataHash Hash of data to be provided when deposit proposal is executed. /// - _yesVotes Number of votes in favor of proposal. /// - _noVotes Number of votes against proposal. /// - _status Current status of proposal. function getProposal( uint8 originDomainID, uint64 depositNonce, bytes32 dataHash ) external view returns (Proposal memory) { uint72 nonceAndID = (uint72(depositNonce) << 8) | uint72(originDomainID); return _proposals[nonceAndID][dataHash]; } /// @notice Returns true if {relayer} has voted on {destNonce} {dataHash} proposal. /// /// @param destNonce destinationDomainID + depositNonce of the proposal. /// @param dataHash Hash of data to be provided when deposit proposal is executed. /// @param relayer Address to check. /// /// @dev Naming left unchanged for backward compatibility. function _hasVotedOnProposal( uint72 destNonce, bytes32 dataHash, address relayer ) external view returns (bool) { return _hasVoted(_proposals[destNonce][dataHash], relayer); } /// @notice Returns true if {relayer} has the relayer role. /// /// @param relayer Address to check. function isRelayer(address relayer) external view returns (bool) { return hasRole(RELAYER_ROLE, relayer); } /// @notice Executes a deposit proposal that is considered passed using a specified handler contract. /// /// @notice Requirements: /// - It must be called by only relayer. /// - Bridge must not be paused. /// - Proposal must have Passed status. /// - Hash of {data} must equal proposal's {dataHash}. /// /// @param domainID ID of chain deposit originated from. /// @param resourceID ResourceID to be used when making deposits. /// @param depositNonce ID of deposited generated by origin Bridge contract. /// @param data Data originally provided when deposit was made. /// @param revertOnFail Decision if the transaction should be reverted in case of handler's executeProposal is reverted or not. /// /// @notice Emits {ProposalEvent} event with status {Executed}. /// @notice Emits {FailedExecution} event with the failed reason. function executeProposal( uint8 domainID, uint64 depositNonce, bytes calldata data, bytes32 resourceID, bool revertOnFail ) public onlyRelayers whenNotPaused { address handler = _resourceIDToHandlerAddress[resourceID]; uint72 nonceAndID = (uint72(depositNonce) << 8) | uint72(domainID); bytes32 dataHash = keccak256(abi.encodePacked(handler, data)); Proposal storage proposal = _proposals[nonceAndID][dataHash]; require( proposal._status == ProposalStatus.Passed, "Proposal must have Passed status" ); proposal._status = ProposalStatus.Executed; IDepositExecute depositHandler = IDepositExecute(handler); if (revertOnFail) { depositHandler.executeProposal(resourceID, data); } else { try depositHandler.executeProposal(resourceID, data) {} catch ( // slither-disable-next-line uninitialized-local,variable-scope bytes memory lowLevelData ) { // slither-disable-next-line reentrancy-no-eth proposal._status = ProposalStatus.Passed; // slither-disable-next-line reentrancy-events emit FailedHandlerExecution(lowLevelData); return; } } // slither-disable-next-line reentrancy-events emit ProposalEvent( domainID, resourceID, depositNonce, ProposalStatus.Executed, dataHash ); } /// @notice Returns total relayers number. /// /// @dev Added for backwards compatibility. function _totalRelayers() public view returns (uint256) { return BridgeAccessControl.getRoleMemberCount(RELAYER_ROLE); } function _onlyAdminOrRelayer() private view { require( hasRole(DEFAULT_ADMIN_ROLE, msg.sender) || hasRole(RELAYER_ROLE, msg.sender), "sender is not relayer or admin" ); } function _onlyAdmin() private view { require( hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "sender doesn't have admin role" ); } function _onlyRelayers() private view { require( hasRole(RELAYER_ROLE, msg.sender), "sender doesn't have relayer role" ); } function _relayerBit(address relayer) private view returns (uint256) { return uint256(1) << (BridgeAccessControl.getRoleMemberIndex(RELAYER_ROLE, relayer) - 1); } function _hasVoted(Proposal memory proposal, address relayer) private view returns (bool) { return (_relayerBit(relayer) & uint256(proposal._yesVotes)) > 0; } }
// 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.7.0) (utils/math/SafeCast.sol) pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toUint248(uint256 value) internal pure returns (uint248) { require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toUint240(uint256 value) internal pure returns (uint240) { require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toUint232(uint256 value) internal pure returns (uint232) { require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.2._ */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toUint216(uint256 value) internal pure returns (uint216) { require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toUint208(uint256 value) internal pure returns (uint208) { require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toUint200(uint256 value) internal pure returns (uint200) { require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toUint192(uint256 value) internal pure returns (uint192) { require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toUint184(uint256 value) internal pure returns (uint184) { require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toUint176(uint256 value) internal pure returns (uint176) { require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toUint168(uint256 value) internal pure returns (uint168) { require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toUint160(uint256 value) internal pure returns (uint160) { require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toUint152(uint256 value) internal pure returns (uint152) { require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toUint144(uint256 value) internal pure returns (uint144) { require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toUint136(uint256 value) internal pure returns (uint136) { require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v2.5._ */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toUint120(uint256 value) internal pure returns (uint120) { require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toUint112(uint256 value) internal pure returns (uint112) { require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toUint104(uint256 value) internal pure returns (uint104) { require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.2._ */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toUint88(uint256 value) internal pure returns (uint88) { require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toUint80(uint256 value) internal pure returns (uint80) { require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toUint72(uint256 value) internal pure returns (uint72) { require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v2.5._ */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toUint56(uint256 value) internal pure returns (uint56) { require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toUint48(uint256 value) internal pure returns (uint48) { require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toUint40(uint256 value) internal pure returns (uint40) { require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v2.5._ */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toUint24(uint256 value) internal pure returns (uint24) { require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v2.5._ */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v2.5._ */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. * * _Available since v3.0._ */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toInt248(int256 value) internal pure returns (int248) { require(value >= type(int248).min && value <= type(int248).max, "SafeCast: value doesn't fit in 248 bits"); return int248(value); } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toInt240(int256 value) internal pure returns (int240) { require(value >= type(int240).min && value <= type(int240).max, "SafeCast: value doesn't fit in 240 bits"); return int240(value); } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toInt232(int256 value) internal pure returns (int232) { require(value >= type(int232).min && value <= type(int232).max, "SafeCast: value doesn't fit in 232 bits"); return int232(value); } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.7._ */ function toInt224(int256 value) internal pure returns (int224) { require(value >= type(int224).min && value <= type(int224).max, "SafeCast: value doesn't fit in 224 bits"); return int224(value); } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toInt216(int256 value) internal pure returns (int216) { require(value >= type(int216).min && value <= type(int216).max, "SafeCast: value doesn't fit in 216 bits"); return int216(value); } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toInt208(int256 value) internal pure returns (int208) { require(value >= type(int208).min && value <= type(int208).max, "SafeCast: value doesn't fit in 208 bits"); return int208(value); } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toInt200(int256 value) internal pure returns (int200) { require(value >= type(int200).min && value <= type(int200).max, "SafeCast: value doesn't fit in 200 bits"); return int200(value); } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toInt192(int256 value) internal pure returns (int192) { require(value >= type(int192).min && value <= type(int192).max, "SafeCast: value doesn't fit in 192 bits"); return int192(value); } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toInt184(int256 value) internal pure returns (int184) { require(value >= type(int184).min && value <= type(int184).max, "SafeCast: value doesn't fit in 184 bits"); return int184(value); } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toInt176(int256 value) internal pure returns (int176) { require(value >= type(int176).min && value <= type(int176).max, "SafeCast: value doesn't fit in 176 bits"); return int176(value); } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toInt168(int256 value) internal pure returns (int168) { require(value >= type(int168).min && value <= type(int168).max, "SafeCast: value doesn't fit in 168 bits"); return int168(value); } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toInt160(int256 value) internal pure returns (int160) { require(value >= type(int160).min && value <= type(int160).max, "SafeCast: value doesn't fit in 160 bits"); return int160(value); } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toInt152(int256 value) internal pure returns (int152) { require(value >= type(int152).min && value <= type(int152).max, "SafeCast: value doesn't fit in 152 bits"); return int152(value); } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toInt144(int256 value) internal pure returns (int144) { require(value >= type(int144).min && value <= type(int144).max, "SafeCast: value doesn't fit in 144 bits"); return int144(value); } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toInt136(int256 value) internal pure returns (int136) { require(value >= type(int136).min && value <= type(int136).max, "SafeCast: value doesn't fit in 136 bits"); return int136(value); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128) { require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits"); return int128(value); } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toInt120(int256 value) internal pure returns (int120) { require(value >= type(int120).min && value <= type(int120).max, "SafeCast: value doesn't fit in 120 bits"); return int120(value); } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toInt112(int256 value) internal pure returns (int112) { require(value >= type(int112).min && value <= type(int112).max, "SafeCast: value doesn't fit in 112 bits"); return int112(value); } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toInt104(int256 value) internal pure returns (int104) { require(value >= type(int104).min && value <= type(int104).max, "SafeCast: value doesn't fit in 104 bits"); return int104(value); } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.7._ */ function toInt96(int256 value) internal pure returns (int96) { require(value >= type(int96).min && value <= type(int96).max, "SafeCast: value doesn't fit in 96 bits"); return int96(value); } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toInt88(int256 value) internal pure returns (int88) { require(value >= type(int88).min && value <= type(int88).max, "SafeCast: value doesn't fit in 88 bits"); return int88(value); } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toInt80(int256 value) internal pure returns (int80) { require(value >= type(int80).min && value <= type(int80).max, "SafeCast: value doesn't fit in 80 bits"); return int80(value); } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toInt72(int256 value) internal pure returns (int72) { require(value >= type(int72).min && value <= type(int72).max, "SafeCast: value doesn't fit in 72 bits"); return int72(value); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64) { require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits"); return int64(value); } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toInt56(int256 value) internal pure returns (int56) { require(value >= type(int56).min && value <= type(int56).max, "SafeCast: value doesn't fit in 56 bits"); return int56(value); } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toInt48(int256 value) internal pure returns (int48) { require(value >= type(int48).min && value <= type(int48).max, "SafeCast: value doesn't fit in 48 bits"); return int48(value); } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toInt40(int256 value) internal pure returns (int40) { require(value >= type(int40).min && value <= type(int40).max, "SafeCast: value doesn't fit in 40 bits"); return int40(value); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32) { require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits"); return int32(value); } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toInt24(int256 value) internal pure returns (int24) { require(value >= type(int24).min && value <= type(int24).max, "SafeCast: value doesn't fit in 24 bits"); return int24(value); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16) { require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits"); return int16(value); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8) { require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits"); return int8(value); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. * * _Available since v3.0._ */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @dev This module is supposed to be used in Bridge. /// /// This is adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.0/contracts/access/AccessControl.sol /// The only difference is added getRoleMemberIndex(bytes32 role, address account) function. import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/utils/Context.sol"; abstract contract BridgeAccessControl is Context { using EnumerableSet for EnumerableSet.AddressSet; using Address for address; struct RoleData { EnumerableSet.AddressSet members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /// @notice Emitted when `account` is granted `role`. /// /// `sender` is the account that originated the contract call, an admin role /// bearer except when using {_setupRole}. event RoleGranted( bytes32 indexed role, address indexed account, address indexed sender ); /// @notice Emitted when `account` is revoked `role`. /// /// `sender` is the account that originated the contract call: /// - if using `revokeRole`, it is the admin role bearer /// - if using `renounceRole`, it is the role bearer (i.e. `account`) event RoleRevoked( bytes32 indexed role, address indexed account, address indexed sender ); /// @notice Returns `true` if `account` has been granted `role`. function hasRole(bytes32 role, address account) public view returns (bool) { return _roles[role].members.contains(account); } /// @notice Returns the number of accounts that have `role`. Can be used /// together with {getRoleMember} to enumerate all bearers of a role. function getRoleMemberCount(bytes32 role) public view returns (uint256) { return _roles[role].members.length(); } /// @notice Returns one of the accounts that have `role`. `index` must be a /// value between 0 and {getRoleMemberCount}, non-inclusive. /// /// Role bearers are not sorted in any particular way, and their ordering may /// change at any point. /// /// WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure /// you perform all queries on the same block. See the following /// https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] /// for more information. // slither-disable-next-line external-function function getRoleMember(bytes32 role, uint256 index) public view returns (address) { return _roles[role].members.at(index); } /// @notice Returns the index of the account that have `role`. function getRoleMemberIndex(bytes32 role, address account) public view returns (uint256) { return _roles[role].members._inner._indexes[ bytes32(uint256(uint160(account))) ]; } /// @notice Returns the admin role that controls `role`. See {grantRole} and /// {revokeRole}. /// /// To change a role's admin, use {_setRoleAdmin}. // slither-disable-next-line external-function function getRoleAdmin(bytes32 role) public view returns (bytes32) { return _roles[role].adminRole; } /// @notice Grants `role` to `account`. /// /// If `account` had not been already granted `role`, emits a {RoleGranted} /// event. /// /// @notice Requirements: /// - the caller must have ``role``'s admin role. function grantRole(bytes32 role, address account) public virtual { // solhint-disable-next-line reason-string require( hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant" ); _grantRole(role, account); } /// @notice Revokes `role` from `account`. /// /// If `account` had been granted `role`, emits a {RoleRevoked} event. /// /// @notice Requirements: /// - the caller must have ``role``'s admin role. function revokeRole(bytes32 role, address account) public virtual { // solhint-disable-next-line reason-string require( hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke" ); _revokeRole(role, account); } /// @notice Revokes `role` from the calling account. /// /// Roles are often managed via {grantRole} and {revokeRole}: this function's /// purpose is to provide a mechanism for accounts to lose their privileges /// if they are compromised (such as when a trusted device is misplaced). /// /// If the calling account had been granted `role`, emits a {RoleRevoked} /// event. /// /// @notice Requirements: /// - the caller must be `account`. function renounceRole(bytes32 role, address account) public virtual { // solhint-disable-next-line reason-string require( account == _msgSender(), "AccessControl: can only renounce roles for self" ); _revokeRole(role, account); } /// @notice Grants `role` to `account`. /// /// If `account` had not been already granted `role`, emits a {RoleGranted} /// event. Note that unlike {grantRole}, this function doesn't perform any /// checks on the calling account. /// /// WARNING: This function should only be called from the constructor when setting /// up the initial roles for the system. /// /// Using this function in any other way is effectively circumventing the admin /// system imposed by {AccessControl}. function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /// @notice Sets `adminRole` as ``role``'s admin role. // slither-disable-next-line dead-code function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { _roles[role].adminRole = adminRole; } function _grantRole(bytes32 role, address account) private { if (_roles[role].members.add(account)) { emit RoleGranted(role, account, _msgSender()); } } function _revokeRole(bytes32 role, address account) private { if (_roles[role].members.remove(account)) { emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity ^0.8.0; interface IERCHandler { /// @notice Correlates {resourceID} with {contractAddress}. /// @param resourceID ResourceID to be used when making deposits. /// @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. function setResource(bytes32 resourceID, address contractAddress) external; /// @notice Marks {contractAddress} as mintable/burnable. /// @param contractAddress Address of contract to be used when making or executing deposits. function setBurnable(address contractAddress) external; /// @notice Withdraw funds from ERC safes. /// @param data ABI-encoded withdrawal params relevant to the handler. function withdraw(bytes memory data) external; }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity ^0.8.0; interface IDepositExecute { /// @notice It is intended that deposit are made using the Bridge contract. /// @param resourceID ResourceID to be used. /// @param depositer Address of account making the deposit in the Bridge contract. /// @param data Consists of additional data needed for a specific deposit. function deposit( bytes32 resourceID, address depositer, bytes calldata data ) external payable returns (bytes memory); /// @notice It is intended that proposals are executed by the Bridge contract. /// @param resourceID ResourceID to be used. /// @param data Consists of additional data needed for a specific deposit execution. function executeProposal(bytes32 resourceID, bytes calldata data) external; }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity ^0.8.0; interface IExecuteRollup { function executeRollup( uint8 destDomainID, bytes32 resourceID, uint64 batchSize, uint256 startBlock, bytes32 state ) external; }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity ^0.8.0; import "../utils/rollup/RollupTypes.sol"; interface ISettle { function settle( RollupInfo memory rollupInfo, bytes calldata data, bytes32[] calldata proof ) external; }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity ^0.8.0; import "./HandlerHelpers.sol"; import "../interfaces/IDepositExecute.sol"; import "../utils/rollup/RollupTypes.sol"; contract RollupHandler is IDepositExecute, HandlerHelpers { constructor(address bridgeAddress) HandlerHelpers(bridgeAddress) {} mapping(uint72 => Metadata) public rollupMetadata; // slither-disable-next-line locked-ether function deposit( bytes32, address, bytes calldata ) external payable override onlyBridge returns (bytes memory) { revert("not supported"); } struct Metadata { uint8 domainID; bytes32 resourceID; bytes32 destResourceID; uint64 nonce; bytes32 stateChangeHash; bytes32 rootHash; uint64 totalBatches; // bytes state; unused } /// @notice Proposal execution should be initiated when a proposal is finalized in the Bridge contract. /// /// @notice Requirements: /// - It must be called by only bridge. /// - {resourceID} must exist. /// - {contractAddress} must be allowed. /// - {resourceID} must be equal to the resource ID from metadata /// - Sender resource ID must exist. /// - Sender contract address must be allowed. /// /// @param data Consists of {resourceID}, {lenMetaData}, and {metaData}. /// /// @notice Data passed into the function should be constructed as follows: /// len(data) uint256 bytes 0 - 32 /// data bytes bytes 32 - END /// /// @notice If {_contractAddressToExecuteFunctionSignature}[{contractAddress}] is set, /// {metaData} is expected to consist of needed function arguments. function executeProposal(bytes32 resourceID, bytes calldata data) external override onlyBridge { address contractAddress = _resourceIDToTokenContractAddress[resourceID]; require(contractAddress != address(0), "invalid resource ID"); require( _contractWhitelist[contractAddress], "not an allowed contract address" ); Metadata memory md = abi.decode(data, (Metadata)); require(md.resourceID == resourceID, "different resource IDs"); address destAddress = _resourceIDToTokenContractAddress[ md.destResourceID ]; require(destAddress != address(0), "invalid dest resource ID"); require( _contractWhitelist[destAddress], "not an allowed sender address" ); uint72 nonceAndID = (uint72(md.nonce) << 8) | uint72(md.domainID); rollupMetadata[nonceAndID] = md; } /// @notice Returns rollup info by original domain ID, resource ID and nonce. /// /// @notice Requirements: /// - {resourceID} must exist. /// - {resourceID} must be equal to the resource ID from metadata /// - Sender resource ID must exist. function getRollupInfo( uint8 originDomainID, bytes32 resourceID, uint64 nonce ) external view returns (RollupInfo memory, address) { address settleableAddress = _resourceIDToTokenContractAddress[ resourceID ]; require(settleableAddress != address(0), "invalid resource ID"); uint72 nonceAndID = (uint72(nonce) << 8) | uint72(originDomainID); Metadata memory md = rollupMetadata[nonceAndID]; require(md.resourceID == resourceID, "different resource IDs"); address destAddress = _resourceIDToTokenContractAddress[ md.destResourceID ]; require(destAddress != address(0), "invalid dest resource ID"); RollupInfo memory rollupInfo = RollupInfo( originDomainID, nonce, md.stateChangeHash, md.rootHash, md.totalBatches, destAddress ); return (rollupInfo, settleableAddress); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity ^0.8.0; struct StateContext { bool _writable; bytes32 _hash; // writable uint256 _startBlock; // writable // readable uint8 _epoch; } struct KeyValuePair { bytes key; bytes value; } struct RollupInfo { uint8 originDomainID; uint64 nonce; bytes32 stateChangeHash; bytes32 rootHash; uint64 totalBatches; address destAddress; }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity ^0.8.0; import "../interfaces/IERCHandler.sol"; /// @notice This contract is intended to be used with the Bridge contract. contract HandlerHelpers is IERCHandler { address public immutable _bridgeAddress; // resourceID => token contract address mapping(bytes32 => address) public _resourceIDToTokenContractAddress; // token contract address => resourceID mapping(address => bytes32) public _tokenContractAddressToResourceID; // token contract address => is whitelisted mapping(address => bool) public _contractWhitelist; // token contract address => is burnable mapping(address => bool) public _burnList; modifier onlyBridge() { _onlyBridge(); _; } /// @param bridgeAddress Contract address of previously deployed Bridge. constructor(address bridgeAddress) { _bridgeAddress = bridgeAddress; } function _onlyBridge() private view { require(msg.sender == _bridgeAddress, "sender must be bridge contract"); } /// @notice First verifies {_resourceIDToContractAddress}[{resourceID}] and /// {_contractAddressToResourceID}[{contractAddress}] are not already set, /// then sets {_resourceIDToContractAddress} with {contractAddress}, /// {_contractAddressToResourceID} with {resourceID}, /// and {_contractWhitelist} to true for {contractAddress}. /// /// @param resourceID ResourceID to be used when making deposits. /// @param contractAddress Address of contract to be called when a deposit is made and a deposited is executed. function setResource(bytes32 resourceID, address contractAddress) external override onlyBridge { _setResource(resourceID, contractAddress); } /// @notice First verifies {contractAddress} is whitelisted, then sets {_burnList}[{contractAddress}] /// to true. /// /// @param contractAddress Address of contract to be used when making or executing deposits. function setBurnable(address contractAddress) external override onlyBridge { _setBurnable(contractAddress); } function withdraw(bytes memory data) external virtual override {} function _setResource(bytes32 resourceID, address contractAddress) internal { _resourceIDToTokenContractAddress[resourceID] = contractAddress; _tokenContractAddressToResourceID[contractAddress] = resourceID; _contractWhitelist[contractAddress] = true; } function _setBurnable(address contractAddress) internal { require( _contractWhitelist[contractAddress], "not an allowed token address" ); _burnList[contractAddress] = true; } }
{ "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
[{"inputs":[{"internalType":"uint8","name":"domainID","type":"uint8"},{"internalType":"address[]","name":"initialRelayers","type":"address[]"},{"internalType":"uint256","name":"initialRelayerThreshold","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"destinationDomainID","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"depositNonce","type":"uint64"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"handlerResponse","type":"bytes"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"destDomainID","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"destResourceID","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"nonce","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"batchSize","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"stateChangeHash","type":"bytes32"}],"name":"ExecuteRollup","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"lowLevelData","type":"bytes"}],"name":"FailedHandlerExecution","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"originDomainID","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"depositNonce","type":"uint64"},{"indexed":false,"internalType":"enum Bridge.ProposalStatus","name":"status","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"dataHash","type":"bytes32"}],"name":"ProposalEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"originDomainID","type":"uint8"},{"indexed":false,"internalType":"uint64","name":"depositNonce","type":"uint64"},{"indexed":false,"internalType":"enum Bridge.ProposalStatus","name":"status","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"dataHash","type":"bytes32"}],"name":"ProposalVote","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"originDomainID","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"nonce","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"batchIndex","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"totalBatches","type":"uint64"}],"name":"ReceiveStateChanges","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"relayer","type":"address"}],"name":"RelayerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newThreshold","type":"uint256"}],"name":"RelayerThresholdChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_RELAYERS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RELAYER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"_depositCounts","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_domainID","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_expiry","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_fee","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint72","name":"destNonce","type":"uint72"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"address","name":"relayer","type":"address"}],"name":"_hasVotedOnProposal","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_relayerThreshold","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"_resourceIDToHandlerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_totalRelayers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"relayerAddress","type":"address"}],"name":"adminAddRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"adminChangeFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newThreshold","type":"uint256"}],"name":"adminChangeRelayerThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"adminPauseTransfers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"relayerAddress","type":"address"}],"name":"adminRemoveRelayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"handlerAddress","type":"address"},{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"adminSetBurnable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"domainID","type":"uint8"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"name":"adminSetDepositNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"handlerAddress","type":"address"},{"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"adminSetResource","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"adminUnpauseTransfers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"handlerAddress","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"adminWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"domainID","type":"uint8"},{"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"internalType":"uint64","name":"depositNonce","type":"uint64"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"}],"name":"cancelProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"destinationDomainID","type":"uint8"},{"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint8","name":"domainID","type":"uint8"},{"internalType":"uint64","name":"depositNonce","type":"uint64"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"internalType":"bool","name":"revertOnFail","type":"bool"}],"name":"executeProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"destDomainID","type":"uint8"},{"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"internalType":"uint64","name":"batchSize","type":"uint64"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"bytes32","name":"stateChangeHash","type":"bytes32"}],"name":"executeRollup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"originDomainID","type":"uint8"},{"internalType":"uint64","name":"depositNonce","type":"uint64"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"}],"name":"getProposal","outputs":[{"components":[{"internalType":"enum Bridge.ProposalStatus","name":"_status","type":"uint8"},{"internalType":"uint200","name":"_yesVotes","type":"uint200"},{"internalType":"uint8","name":"_yesVotesTotal","type":"uint8"},{"internalType":"uint40","name":"_proposedBlock","type":"uint40"}],"internalType":"struct Bridge.Proposal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"getRoleMemberIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"relayer","type":"address"}],"name":"isRelayer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"originDomainID","type":"uint8"},{"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"receiveStateChanges","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"renounceAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable[]","name":"addrs","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"transferFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"domainID","type":"uint8"},{"internalType":"uint64","name":"depositNonce","type":"uint64"},{"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"voteProposal","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b5060405162003add38038062003add8339810160408190526200003491620004a1565b6000805460ff1916905560ff85166080526200005c8362000178602090811b6200220a17901c565b600260006101000a81548160ff021916908360ff1602179055506200008c82620001e360201b6200226f1760201c565b600260016101000a8154816001600160801b0302191690836001600160801b03160217905550620000c8816200024e60201b620022d81760201c565b6002805464ffffffffff92909216600160881b0264ffffffffff60881b19909216919091179055620000fc600033620002b6565b60005b84518110156200016c57620001577fe2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4868381518110620001435762000143620005aa565b6020026020010151620002c660201b60201c565b806200016381620005c0565b915050620000ff565b505050505050620005ea565b600060ff821115620001df5760405162461bcd60e51b815260206004820152602560248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2038604482015264206269747360d81b60648201526084015b60405180910390fd5b5090565b60006001600160801b03821115620001df5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b6064820152608401620001d6565b600064ffffffffff821115620001df5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526530206269747360d01b6064820152608401620001d6565b620002c282826200034a565b5050565b600082815260016020526040902060020154620002e49033620003b3565b620002b65760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e60448201526e0818591b5a5b881d1bc819dc985b9d608a1b6064820152608401620001d6565b6000828152600160209081526040909120620003719183906200233e620003e2821b17901c565b15620002c25760405133906001600160a01b0383169084907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d90600090a45050565b60008281526001602090815260408220620003d991849062002353620003f9821b17901c565b90505b92915050565b6000620003d9836001600160a01b0384166200041c565b6001600160a01b03811660009081526001830160205260408120541515620003d9565b60008181526001830160205260408120546200046557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003dc565b506000620003dc565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b03811681146200049c57600080fd5b919050565b600080600080600060a08688031215620004ba57600080fd5b855160ff81168114620004cc57600080fd5b602087810151919650906001600160401b0380821115620004ec57600080fd5b818901915089601f8301126200050157600080fd5b8151818111156200051657620005166200046e565b8060051b604051601f19603f830116810181811085821117156200053e576200053e6200046e565b60405291825284820192508381018501918c8311156200055d57600080fd5b938501935b828510156200058657620005768562000484565b8452938501939285019262000562565b60408c015160608d01516080909d01519b9e919d509b9a9950975050505050505050565b634e487b7160e01b600052603260045260246000fd5b6000600019821415620005e357634e487b7160e01b600052601160045260246000fd5b5060010190565b6080516134d76200060660003960006105da01526134d76000f3fe60806040526004361061023b5760003560e01c80639010d07c1161012e578063c0331b3e116100ab578063cdb0f73a1161006f578063cdb0f73a1461075d578063d547741f1461077d578063d7a9cd791461079d578063edc20c3c146107b7578063ffaac0eb146107d757600080fd5b8063c0331b3e14610685578063c5b37c22146106a5578063c5ec8970146106e2578063ca15c8731461071d578063cb10f2151461073d57600080fd5b80639dd694f4116100f25780639dd694f4146105c85780639debb3bd1461060e578063a217fddf14610623578063a9cf69fa14610638578063bd2a18201461066557600080fd5b80639010d07c1461052657806391c404ac1461054657806391d1485414610566578063926d7d7f146105865780639d82dd63146105a857600080fd5b80634e056005116101bc5780637febe63f116101805780637febe63f1461046e578063802aabe81461048e57806380ae1c28146104a357806384db809f146104b85780638c0c26311461050657600080fd5b80634e056005146103c65780634e0df3f6146103e6578063541d5548146104065780635c975abb146104365780635e1fab0f1461044e57600080fd5b80632593f1d2116102035780632593f1d2146102f85780632f2ff15d1461031857806336568abe146103385780634603ae38146103585780634b0b919d1461037857600080fd5b806305e2ca17146102405780630e334977146102555780631d267c9e14610275578063206a98fd14610295578063248a9ca3146102b5575b600080fd5b61025361024e366004612923565b6107ec565b005b34801561026157600080fd5b50610253610270366004612993565b6109ef565b34801561028157600080fd5b506102536102903660046129db565b610c84565b3480156102a157600080fd5b506102536102b0366004612a2d565b610e61565b3480156102c157600080fd5b506102e56102d0366004612ab6565b60009081526001602052604090206002015490565b6040519081526020015b60405180910390f35b34801561030457600080fd5b50610253610313366004612b13565b6110eb565b34801561032457600080fd5b50610253610333366004612bc6565b6112c0565b34801561034457600080fd5b50610253610353366004612bc6565b61134e565b34801561036457600080fd5b50610253610373366004612bf6565b6113c8565b34801561038457600080fd5b506103ae610393366004612c55565b6003602052600090815260409020546001600160401b031681565b6040516001600160401b0390911681526020016102ef565b3480156103d257600080fd5b506102536103e1366004612ab6565b61151d565b3480156103f257600080fd5b506102e5610401366004612bc6565b611579565b34801561041257600080fd5b50610426610421366004612c72565b6115a5565b60405190151581526020016102ef565b34801561044257600080fd5b5060005460ff16610426565b34801561045a57600080fd5b50610253610469366004612c72565b6115bf565b34801561047a57600080fd5b50610426610489366004612c8f565b611639565b34801561049a57600080fd5b506102e56116df565b3480156104af57600080fd5b506102536116fd565b3480156104c457600080fd5b506104ee6104d3366004612ab6565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016102ef565b34801561051257600080fd5b50610253610521366004612cdf565b61170f565b34801561053257600080fd5b506104ee610541366004612d0d565b61177b565b34801561055257600080fd5b50610253610561366004612ab6565b61179a565b34801561057257600080fd5b50610426610581366004612bc6565b611834565b34801561059257600080fd5b506102e560008051602061346283398151915281565b3480156105b457600080fd5b506102536105c3366004612c72565b61184c565b3480156105d457600080fd5b506105fc7f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff90911681526020016102ef565b34801561061a57600080fd5b506102e560c881565b34801561062f57600080fd5b506102e5600081565b34801561064457600080fd5b50610658610653366004612d2f565b611901565b6040516102ef9190612da8565b34801561067157600080fd5b50610253610680366004612e5e565b6119cf565b34801561069157600080fd5b506102536106a0366004612ef0565b611a05565b3480156106b157600080fd5b506002546106ca9061010090046001600160801b031681565b6040516001600160801b0390911681526020016102ef565b3480156106ee57600080fd5b5060025461070790600160881b900464ffffffffff1681565b60405164ffffffffff90911681526020016102ef565b34801561072957600080fd5b506102e5610738366004612ab6565b611f0f565b34801561074957600080fd5b50610253610758366004612f62565b611f26565b34801561076957600080fd5b50610253610778366004612c72565b611fba565b34801561078957600080fd5b50610253610798366004612bc6565b6120c0565b3480156107a957600080fd5b506002546105fc9060ff1681565b3480156107c357600080fd5b506102536107d2366004612f82565b612141565b3480156107e357600080fd5b506102536121fa565b6107f4612375565b60025461010090046001600160801b03163410156108525760405162461bcd60e51b8152602060048201526016602482015275125b98dbdc9c9958dd08199959481cdd5c1c1b1a595960521b60448201526064015b60405180910390fd5b6000838152600460205260409020546001600160a01b0316806108b75760405162461bcd60e51b815260206004820181905260248201527f7265736f757263654944206e6f74206d617070656420746f2068616e646c65726044820152606401610849565b60ff85166000908152600360205260408120805482906108df906001600160401b0316612fc6565b825461010092830a6001600160401b0381810219909216918316021790925560025491925083916000916001600160a01b0384169163b07e54bb9161092e91046001600160801b031634612fed565b89338a8a6040518663ffffffff1660e01b8152600401610951949392919061302d565b60006040518083038185885af115801561096f573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526109989190810190613092565b9050336001600160a01b03167f17bc3181e17a9620a479c24e6c606e474ba84fc036877b768926872e8cd0e11f8989868a8a876040516109dd96959493929190613134565b60405180910390a25050505050505050565b6109f76123bb565b60ff848116600884901b68ffffffffffffffff0016176000818152600560209081526040808320868452909152808220815160808101909252805493949293919290918391166004811115610a4e57610a4e612d70565b6004811115610a5f57610a5f612d70565b8152905461010081046001600160c81b03166020830152600160d01b810460ff166040830152600160d81b900464ffffffffff1660609091015280519091506001816004811115610ab257610ab2612d70565b1480610acf57506002816004811115610acd57610acd612d70565b145b610b1b5760405162461bcd60e51b815260206004820152601c60248201527f50726f706f73616c2063616e6e6f742062652063616e63656c6c6564000000006044820152606401610849565b600254606083015164ffffffffff600160881b909204821691610b3f911643612fed565b64ffffffffff1611610b935760405162461bcd60e51b815260206004820181905260248201527f50726f706f73616c206e6f7420617420657870697279207468726573686f6c646044820152606401610849565b600480835268ffffffffffffffffff841660009081526005602090815260408083208884529091529020835181548593839160ff1916906001908490811115610bde57610bde612d70565b02179055506020820151815460408085015160609095015164ffffffffff16600160d81b026001600160d81b0360ff909616600160d01b0260ff60d01b196001600160c81b039095166101000294909416610100600160d81b03199093169290921792909217939093169290921790555160008051602061348283398151915290610c73908990899089906004908a90613185565b60405180910390a150505050505050565b610c8c612375565b6000848152600460205260409020546001600160a01b031680610ce75760405162461bcd60e51b81526020600482015260136024820152721a5b9d985b1a59081c995cdbdd5c98d9481251606a1b6044820152606401610849565b60ff8616600090815260036020526040812080548290610d0f906001600160401b0316612fc6565b82546001600160401b038083166101009490940a938402930219169190911790915560405163c8ba6c8760e01b81523360048201529091506000906001600160a01b0384169063c8ba6c8790602401602060405180830381865afa158015610d7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9f91906131c2565b905080610dee5760405162461bcd60e51b815260206004820152601760248201527f696e76616c696420736f75726365207265736f757263650000000000000000006044820152606401610849565b6040805160ff8a168152602081018990529081018290526001600160401b0380841660608301528716608082015260a0810186905260c081018590527fe661e74edc20ee64cac60fe9827478a663e2b89663a19ca9dd53aee32233ab319060e00160405180910390a15050505050505050565b610e69612430565b610e71612375565b60008281526004602090815260408083205490516001600160a01b039091169268ffffffffffffffff0060088a901b1660ff8b1617929091610eb99185918a918a91016131db565b60408051601f19818403018152918152815160209283012068ffffffffffffffffff851660009081526005845282812082825290935291209091506002815460ff166004811115610f0c57610f0c612d70565b14610f595760405162461bcd60e51b815260206004820181905260248201527f50726f706f73616c206d757374206861766520506173736564207374617475736044820152606401610849565b805460ff19166003178155838515610fd25760405163712467f960e11b81526001600160a01b0382169063e248cff290610f9b908a908d908d90600401613207565b600060405180830381600087803b158015610fb557600080fd5b505af1158015610fc9573d6000803e3d6000fd5b505050506110af565b60405163712467f960e11b81526001600160a01b0382169063e248cff290611002908a908d908d90600401613207565b600060405180830381600087803b15801561101c57600080fd5b505af192505050801561102d575060015b6110af573d80801561105b576040519150601f19603f3d011682016040523d82523d6000602084013e611060565b606091505b50825460ff191660021783556040517fbd37c1f0d53bb2f33fe4c2104de272fcdeb4d2fef3acdbf1e4ddc3d6833ca3769061109c908390613221565b60405180910390a15050505050506110e3565b6000805160206134828339815191528b888c6003876040516110d5959493929190613185565b60405180910390a150505050505b505050505050565b6110f3612375565b6000868152600460205260409020546001600160a01b0316806111545760405162461bcd60e51b81526020600482015260196024820152781b9bc81a185b991b195c88199bdc881c995cdbdd5c98d95251603a1b6044820152606401610849565b6040516330985a5360e21b815260ff89166004820152602481018890526001600160401b038716604482015260009081906001600160a01b0384169063c261694c9060640160e060405180830381865afa1580156111b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111da9190613244565b60405163d475d3cb60e01b815291935091506001600160a01b0382169063d475d3cb906112139085908b908b908b908b906004016132ff565b600060405180830381600087803b15801561122d57600080fd5b505af1158015611241573d6000803e3d6000fd5b5060009250611255915050878901896133a8565b90507fa12cfd91dc25577484866615ca883a35b8e09f169cc20ed5839a3c4bb3d7754c8b8b8b8487608001516040516110d595949392919060ff95909516855260208501939093526001600160401b0391821660408501528116606084015216608082015260a00190565b6000828152600160205260409020600201546112dc9033611834565b6113405760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e60448201526e0818591b5a5b881d1bc819dc985b9d608a1b6064820152608401610849565b61134a8282612494565b5050565b6001600160a01b03811633146113be5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610849565b61134a82826124ed565b6113d0612546565b82811461141f5760405162461bcd60e51b815260206004820152601f60248201527f61646472735b5d2c20616d6f756e74735b5d3a2064696666206c656e677468006044820152606401610849565b60005b8381101561151657600085858381811061143e5761143e6133c5565b90506020020160208101906114539190612c72565b6001600160a01b031684848481811061146e5761146e6133c5565b9050602002013560405160006040518083038185875af1925050503d80600081146114b5576040519150601f19603f3d011682016040523d82523d6000602084013e6114ba565b606091505b50509050806115035760405162461bcd60e51b8152602060048201526015602482015274195d1a195c881d1c985b9cd9995c8819985a5b1959605a1b6044820152606401610849565b508061150e816133db565b915050611422565b5050505050565b611525612546565b61152e8161220a565b6002805460ff191660ff929092169190911790556040518181527fa20d6b84cd798a24038be305eff8a45ca82ef54a2aa2082005d8e14c0a4746c8906020015b60405180910390a150565b60008281526001602081815260408084206001600160a01b038616855290920190529020545b92915050565b600061159f60008051602061346283398151915283611834565b6115c7612546565b336001600160a01b03821614156116205760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f742072656e6f756e6365206f6e6573656c660000000000000000006044820152606401610849565b61162b6000826112c0565b61163660003361134e565b50565b68ffffffffffffffffff8316600090815260056020908152604080832085845290915280822081516080810190925280546116d7929190829060ff16600481111561168657611686612d70565b600481111561169757611697612d70565b8152905461010081046001600160c81b03166020830152600160d01b810460ff166040830152600160d81b900464ffffffffff166060909101528361259d565b949350505050565b60006116f8600080516020613462833981519152611f0f565b905090565b611705612546565b61170d6125c0565b565b611717612546565b6040516307b7ed9960e01b81526001600160a01b0382811660048301528391908216906307b7ed99906024015b600060405180830381600087803b15801561175e57600080fd5b505af1158015611772573d6000803e3d6000fd5b50505050505050565b6000828152600160205260408120611793908361261a565b9392505050565b6117a2612546565b60025461010090046001600160801b03168114156118025760405162461bcd60e51b815260206004820152601f60248201527f43757272656e742066656520697320657175616c20746f206e657720666565006044820152606401610849565b61180b8161226f565b600260016101000a8154816001600160801b0302191690836001600160801b0316021790555050565b60008281526001602052604081206117939083612353565b61186460008051602061346283398151915282611834565b6118b05760405162461bcd60e51b815260206004820152601f60248201527f6164647220646f65736e277420686176652072656c6179657220726f6c6521006044820152606401610849565b6118c8600080516020613462833981519152826120c0565b6040516001600160a01b03821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b9060200161156e565b60408051608081018252600080825260208201819052918101829052606081019190915260ff848116600885901b68ffffffffffffffff0016176000818152600560209081526040808320878452909152908190208151608081019092528054929391929091839116600481111561197b5761197b612d70565b600481111561198c5761198c612d70565b8152905461010081046001600160c81b03166020830152600160d01b810460ff166040830152600160d81b900464ffffffffff1660609091015295945050505050565b6119d7612546565b60405163025a3c9960e21b815282906001600160a01b03821690630968f26490611744908590600401613221565b611a0d612430565b611a15612375565b60008381526004602090815260408083205490516001600160a01b039091169268ffffffffffffffff00600889901b1660ff8a1617929091611a5d91859188918891016131db565b60408051601f19818403018152828252805160209182012068ffffffffffffffffff861660009081526005835283812082825290925282822060808501909352825490945090929190829060ff166004811115611abc57611abc612d70565b6004811115611acd57611acd612d70565b8152905461010081046001600160c81b0316602080840191909152600160d01b820460ff16604080850191909152600160d81b90920464ffffffffff1660609093019290925260008a815260049092529020549091506001600160a01b0316611b745760405162461bcd60e51b81526020600482015260196024820152781b9bc81a185b991b195c88199bdc881c995cdbdd5c98d95251603a1b6044820152606401610849565b600281516004811115611b8957611b89612d70565b1415611ba757611b9e898988888b6001610e61565b50505050611516565b80516001906004811115611bbd57611bbd612d70565b1115611c175760405162461bcd60e51b815260206004820152602360248201527f70726f706f73616c20616c72656164792065786563757465642f63616e63656c6044820152621b195960ea1b6064820152608401610849565b611c21813361259d565b15611c665760405162461bcd60e51b81526020600482015260156024820152741c995b185e595c88185b1c9958591e481d9bdd1959605a1b6044820152606401610849565b600081516004811115611c7b57611c7b612d70565b1415611cdd57506040805160808101825260018082526000602083018190528284015264ffffffffff431660608301529151909160008051602061348283398151915291611cd0918c918b918d918890613185565b60405180910390a1611d41565b600254606082015164ffffffffff600160881b909204821691611d01911643612fed565b64ffffffffff161115611d4157600480825260405160008051602061348283398151915291611d38918c918b918d91908890613185565b60405180910390a15b600481516004811115611d5657611d56612d70565b14611e2457611d7b611d6733612626565b82602001516001600160c81b031617612656565b6001600160c81b0316602082015260408101805190611d99826133f6565b60ff1690525080516040517f25f8daaa4635a7729927ba3f5b3d59cc3320aca7c32c9db4e7ca7b957434364091611dd5918c918c918790613416565b60405180910390a1600254604082015160ff918216911610611e2457600280825260405160008051602061348283398151915291611e1b918c918b918d91908890613185565b60405180910390a15b68ffffffffffffffffff8316600090815260056020908152604080832085845290915290208151815483929190829060ff19166001836004811115611e6b57611e6b612d70565b021790555060208201518154604084015160609094015164ffffffffff16600160d81b026001600160d81b0360ff909516600160d01b0260ff60d01b196001600160c81b039094166101000293909316610100600160d81b0319909216919091179190911792909216919091179055600281516004811115611eef57611eef612d70565b1415611f0457611f04898988888b6000610e61565b505050505050505050565b600081815260016020526040812061159f906126bf565b611f2e612546565b60008281526004602081905260409182902080546001600160a01b0319166001600160a01b038781169182179092559251635c7d1b9b60e11b81529182018590528316602482015284919063b8fa373690604401600060405180830381600087803b158015611f9c57600080fd5b505af1158015611fb0573d6000803e3d6000fd5b5050505050505050565b611fd260008051602061346283398151915282611834565b1561201f5760405162461bcd60e51b815260206004820152601e60248201527f6164647220616c7265616479206861732072656c6179657220726f6c652100006044820152606401610849565b60c86120296116df565b1061206f5760405162461bcd60e51b81526020600482015260166024820152751c995b185e595c9cc81b1a5b5a5d081c995858da195960521b6044820152606401610849565b612087600080516020613462833981519152826112c0565b6040516001600160a01b03821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c59060200161156e565b6000828152600160205260409020600201546120dc9033611834565b6113be5760405162461bcd60e51b815260206004820152603060248201527f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e60448201526f2061646d696e20746f207265766f6b6560801b6064820152608401610849565b612149612546565b60ff82166000908152600360205260409020546001600160401b03908116908216116121c65760405162461bcd60e51b815260206004820152602660248201527f446f6573206e6f7420616c6c6f772064656372656d656e7473206f6620746865604482015265206e6f6e636560d01b6064820152608401610849565b60ff919091166000908152600360205260409020805467ffffffffffffffff19166001600160401b03909216919091179055565b612202612546565b61170d6126c9565b600060ff82111561226b5760405162461bcd60e51b815260206004820152602560248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2038604482015264206269747360d81b6064820152608401610849565b5090565b60006001600160801b0382111561226b5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b6064820152608401610849565b600064ffffffffff82111561226b5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526530206269747360d01b6064820152608401610849565b6000611793836001600160a01b038416612702565b6001600160a01b03811660009081526001830160205260408120541515611793565b60005460ff161561170d5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610849565b6123c6600033611834565b806123e457506123e460008051602061346283398151915233611834565b61170d5760405162461bcd60e51b815260206004820152601e60248201527f73656e646572206973206e6f742072656c61796572206f722061646d696e00006044820152606401610849565b61244860008051602061346283398151915233611834565b61170d5760405162461bcd60e51b815260206004820181905260248201527f73656e64657220646f65736e277420686176652072656c6179657220726f6c656044820152606401610849565b60008281526001602052604090206124ac908261233e565b1561134a5760405133906001600160a01b0383169084907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d90600090a45050565b60008281526001602052604090206125059082612751565b1561134a5760405133906001600160a01b0383169084907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b90600090a45050565b612551600033611834565b61170d5760405162461bcd60e51b815260206004820152601e60248201527f73656e64657220646f65736e277420686176652061646d696e20726f6c6500006044820152606401610849565b60008083602001516001600160c81b03166125b784612626565b16119392505050565b6125c8612375565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586125fd3390565b6040516001600160a01b03909116815260200160405180910390a1565b60006117938383612766565b6000600161264260008051602061346283398151915284611579565b61264c9190612fed565b6001901b92915050565b60006001600160c81b0382111561226b5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663030206269747360c81b6064820152608401610849565b600061159f825490565b6126d1612790565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa336125fd565b60008181526001830160205260408120546127495750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561159f565b50600061159f565b6000611793836001600160a01b0384166127d9565b600082600001828154811061277d5761277d6133c5565b9060005260206000200154905092915050565b60005460ff1661170d5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610849565b600081815260018301602052604081205480156128c25760006127fd600183612fed565b855490915060009061281190600190612fed565b9050818114612876576000866000018281548110612831576128316133c5565b9060005260206000200154905080876000018481548110612854576128546133c5565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806128875761288761344b565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061159f565b600091505061159f565b60ff8116811461163657600080fd5b60008083601f8401126128ed57600080fd5b5081356001600160401b0381111561290457600080fd5b60208301915083602082850101111561291c57600080fd5b9250929050565b6000806000806060858703121561293957600080fd5b8435612944816128cc565b93506020850135925060408501356001600160401b0381111561296657600080fd5b612972878288016128db565b95989497509550505050565b6001600160401b038116811461163657600080fd5b600080600080608085870312156129a957600080fd5b84356129b4816128cc565b93506020850135925060408501356129cb8161297e565b9396929550929360600135925050565b600080600080600060a086880312156129f357600080fd5b85356129fe816128cc565b9450602086013593506040860135612a158161297e565b94979396509394606081013594506080013592915050565b60008060008060008060a08789031215612a4657600080fd5b8635612a51816128cc565b95506020870135612a618161297e565b945060408701356001600160401b03811115612a7c57600080fd5b612a8889828a016128db565b9095509350506060870135915060808701358015158114612aa857600080fd5b809150509295509295509295565b600060208284031215612ac857600080fd5b5035919050565b60008083601f840112612ae157600080fd5b5081356001600160401b03811115612af857600080fd5b6020830191508360208260051b850101111561291c57600080fd5b600080600080600080600060a0888a031215612b2e57600080fd5b8735612b39816128cc565b9650602088013595506040880135612b508161297e565b945060608801356001600160401b0380821115612b6c57600080fd5b612b788b838c016128db565b909650945060808a0135915080821115612b9157600080fd5b50612b9e8a828b01612acf565b989b979a50959850939692959293505050565b6001600160a01b038116811461163657600080fd5b60008060408385031215612bd957600080fd5b823591506020830135612beb81612bb1565b809150509250929050565b60008060008060408587031215612c0c57600080fd5b84356001600160401b0380821115612c2357600080fd5b612c2f88838901612acf565b90965094506020870135915080821115612c4857600080fd5b5061297287828801612acf565b600060208284031215612c6757600080fd5b8135611793816128cc565b600060208284031215612c8457600080fd5b813561179381612bb1565b600080600060608486031215612ca457600080fd5b833568ffffffffffffffffff81168114612cbd57600080fd5b9250602084013591506040840135612cd481612bb1565b809150509250925092565b60008060408385031215612cf257600080fd5b8235612cfd81612bb1565b91506020830135612beb81612bb1565b60008060408385031215612d2057600080fd5b50508035926020909101359150565b600080600060608486031215612d4457600080fd5b8335612d4f816128cc565b92506020840135612d5f8161297e565b929592945050506040919091013590565b634e487b7160e01b600052602160045260246000fd5b60058110612da457634e487b7160e01b600052602160045260246000fd5b9052565b6000608082019050612dbb828451612d86565b60018060c81b03602084015116602083015260ff604084015116604083015264ffffffffff606084015116606083015292915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715612e2f57612e2f612df1565b604052919050565b60006001600160401b03821115612e5057612e50612df1565b50601f01601f191660200190565b60008060408385031215612e7157600080fd5b8235612e7c81612bb1565b915060208301356001600160401b03811115612e9757600080fd5b8301601f81018513612ea857600080fd5b8035612ebb612eb682612e37565b612e07565b818152866020838501011115612ed057600080fd5b816020840160208301376000602083830101528093505050509250929050565b600080600080600060808688031215612f0857600080fd5b8535612f13816128cc565b94506020860135612f238161297e565b93506040860135925060608601356001600160401b03811115612f4557600080fd5b612f51888289016128db565b969995985093965092949392505050565b600080600060608486031215612f7757600080fd5b8335612cbd81612bb1565b60008060408385031215612f9557600080fd5b8235612fa0816128cc565b91506020830135612beb8161297e565b634e487b7160e01b600052601160045260246000fd5b60006001600160401b0380831681811415612fe357612fe3612fb0565b6001019392505050565b600082821015612fff57612fff612fb0565b500390565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8481526001600160a01b03841660208201526060604082018190526000906130589083018486613004565b9695505050505050565b60005b8381101561307d578181015183820152602001613065565b8381111561308c576000848401525b50505050565b6000602082840312156130a457600080fd5b81516001600160401b038111156130ba57600080fd5b8201601f810184136130cb57600080fd5b80516130d9612eb682612e37565b8181528560208385010111156130ee57600080fd5b6130ff826020830160208601613062565b95945050505050565b60008151808452613120816020860160208601613062565b601f01601f19169290920160200192915050565b60ff871681528560208201526001600160401b038516604082015260a06060820152600061316660a083018587613004565b82810360808401526131788185613108565b9998505050505050505050565b60ff86168152602081018590526001600160401b038416604082015260a081016131b26060830185612d86565b8260808301529695505050505050565b6000602082840312156131d457600080fd5b5051919050565b6bffffffffffffffffffffffff198460601b168152818360148301376000910160140190815292915050565b8381526040602082015260006130ff604083018486613004565b6020815260006117936020830184613108565b805161323f81612bb1565b919050565b60008082840360e081121561325857600080fd5b60c081121561326657600080fd5b5060405160c081018181106001600160401b038211171561328957613289612df1565b6040528351613297816128cc565b815260208401516132a78161297e565b80602083015250604084015160408201526060840151606082015260808401516132d08161297e565b608082015260a08401516132e381612bb1565b60a082015291506132f660c08401613234565b90509250929050565b600061010060ff885116835260208801516001600160401b03808216602086015260408a0151604086015260608a015160608601528060808b0151166080860152505060018060a01b0360a08901511660a08401528060c08401526133678184018789613004565b83810360e085015284815290506001600160fb1b0384111561338857600080fd5b8360051b8086602084013760009101602001908152979650505050505050565b6000602082840312156133ba57600080fd5b81356117938161297e565b634e487b7160e01b600052603260045260246000fd5b60006000198214156133ef576133ef612fb0565b5060010190565b600060ff821660ff81141561340d5761340d612fb0565b60010192915050565b60ff851681526001600160401b03841660208201526080810161343c6040830185612d86565b82606083015295945050505050565b634e487b7160e01b600052603160045260246000fdfee2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4efff49f4c5619a2ddc010f7bd6cf656ebb90da54c8469c26ac330ce7619e5c1ea26469706673582212206d2acc8ac4bfbe2ba169e3771da55a7310f266b89cbaf57a7f0964083bbcb09d64736f6c634300080b0033000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009896800000000000000000000000000000000000000000000000000000000000000002000000000000000000000000980754a1bdb3ddde98ba0e63bb985630096aac480000000000000000000000001f06ec074d88403c5837078aab4e696716b6544d
Deployed Bytecode
0x60806040526004361061023b5760003560e01c80639010d07c1161012e578063c0331b3e116100ab578063cdb0f73a1161006f578063cdb0f73a1461075d578063d547741f1461077d578063d7a9cd791461079d578063edc20c3c146107b7578063ffaac0eb146107d757600080fd5b8063c0331b3e14610685578063c5b37c22146106a5578063c5ec8970146106e2578063ca15c8731461071d578063cb10f2151461073d57600080fd5b80639dd694f4116100f25780639dd694f4146105c85780639debb3bd1461060e578063a217fddf14610623578063a9cf69fa14610638578063bd2a18201461066557600080fd5b80639010d07c1461052657806391c404ac1461054657806391d1485414610566578063926d7d7f146105865780639d82dd63146105a857600080fd5b80634e056005116101bc5780637febe63f116101805780637febe63f1461046e578063802aabe81461048e57806380ae1c28146104a357806384db809f146104b85780638c0c26311461050657600080fd5b80634e056005146103c65780634e0df3f6146103e6578063541d5548146104065780635c975abb146104365780635e1fab0f1461044e57600080fd5b80632593f1d2116102035780632593f1d2146102f85780632f2ff15d1461031857806336568abe146103385780634603ae38146103585780634b0b919d1461037857600080fd5b806305e2ca17146102405780630e334977146102555780631d267c9e14610275578063206a98fd14610295578063248a9ca3146102b5575b600080fd5b61025361024e366004612923565b6107ec565b005b34801561026157600080fd5b50610253610270366004612993565b6109ef565b34801561028157600080fd5b506102536102903660046129db565b610c84565b3480156102a157600080fd5b506102536102b0366004612a2d565b610e61565b3480156102c157600080fd5b506102e56102d0366004612ab6565b60009081526001602052604090206002015490565b6040519081526020015b60405180910390f35b34801561030457600080fd5b50610253610313366004612b13565b6110eb565b34801561032457600080fd5b50610253610333366004612bc6565b6112c0565b34801561034457600080fd5b50610253610353366004612bc6565b61134e565b34801561036457600080fd5b50610253610373366004612bf6565b6113c8565b34801561038457600080fd5b506103ae610393366004612c55565b6003602052600090815260409020546001600160401b031681565b6040516001600160401b0390911681526020016102ef565b3480156103d257600080fd5b506102536103e1366004612ab6565b61151d565b3480156103f257600080fd5b506102e5610401366004612bc6565b611579565b34801561041257600080fd5b50610426610421366004612c72565b6115a5565b60405190151581526020016102ef565b34801561044257600080fd5b5060005460ff16610426565b34801561045a57600080fd5b50610253610469366004612c72565b6115bf565b34801561047a57600080fd5b50610426610489366004612c8f565b611639565b34801561049a57600080fd5b506102e56116df565b3480156104af57600080fd5b506102536116fd565b3480156104c457600080fd5b506104ee6104d3366004612ab6565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016102ef565b34801561051257600080fd5b50610253610521366004612cdf565b61170f565b34801561053257600080fd5b506104ee610541366004612d0d565b61177b565b34801561055257600080fd5b50610253610561366004612ab6565b61179a565b34801561057257600080fd5b50610426610581366004612bc6565b611834565b34801561059257600080fd5b506102e560008051602061346283398151915281565b3480156105b457600080fd5b506102536105c3366004612c72565b61184c565b3480156105d457600080fd5b506105fc7f000000000000000000000000000000000000000000000000000000000000000181565b60405160ff90911681526020016102ef565b34801561061a57600080fd5b506102e560c881565b34801561062f57600080fd5b506102e5600081565b34801561064457600080fd5b50610658610653366004612d2f565b611901565b6040516102ef9190612da8565b34801561067157600080fd5b50610253610680366004612e5e565b6119cf565b34801561069157600080fd5b506102536106a0366004612ef0565b611a05565b3480156106b157600080fd5b506002546106ca9061010090046001600160801b031681565b6040516001600160801b0390911681526020016102ef565b3480156106ee57600080fd5b5060025461070790600160881b900464ffffffffff1681565b60405164ffffffffff90911681526020016102ef565b34801561072957600080fd5b506102e5610738366004612ab6565b611f0f565b34801561074957600080fd5b50610253610758366004612f62565b611f26565b34801561076957600080fd5b50610253610778366004612c72565b611fba565b34801561078957600080fd5b50610253610798366004612bc6565b6120c0565b3480156107a957600080fd5b506002546105fc9060ff1681565b3480156107c357600080fd5b506102536107d2366004612f82565b612141565b3480156107e357600080fd5b506102536121fa565b6107f4612375565b60025461010090046001600160801b03163410156108525760405162461bcd60e51b8152602060048201526016602482015275125b98dbdc9c9958dd08199959481cdd5c1c1b1a595960521b60448201526064015b60405180910390fd5b6000838152600460205260409020546001600160a01b0316806108b75760405162461bcd60e51b815260206004820181905260248201527f7265736f757263654944206e6f74206d617070656420746f2068616e646c65726044820152606401610849565b60ff85166000908152600360205260408120805482906108df906001600160401b0316612fc6565b825461010092830a6001600160401b0381810219909216918316021790925560025491925083916000916001600160a01b0384169163b07e54bb9161092e91046001600160801b031634612fed565b89338a8a6040518663ffffffff1660e01b8152600401610951949392919061302d565b60006040518083038185885af115801561096f573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526109989190810190613092565b9050336001600160a01b03167f17bc3181e17a9620a479c24e6c606e474ba84fc036877b768926872e8cd0e11f8989868a8a876040516109dd96959493929190613134565b60405180910390a25050505050505050565b6109f76123bb565b60ff848116600884901b68ffffffffffffffff0016176000818152600560209081526040808320868452909152808220815160808101909252805493949293919290918391166004811115610a4e57610a4e612d70565b6004811115610a5f57610a5f612d70565b8152905461010081046001600160c81b03166020830152600160d01b810460ff166040830152600160d81b900464ffffffffff1660609091015280519091506001816004811115610ab257610ab2612d70565b1480610acf57506002816004811115610acd57610acd612d70565b145b610b1b5760405162461bcd60e51b815260206004820152601c60248201527f50726f706f73616c2063616e6e6f742062652063616e63656c6c6564000000006044820152606401610849565b600254606083015164ffffffffff600160881b909204821691610b3f911643612fed565b64ffffffffff1611610b935760405162461bcd60e51b815260206004820181905260248201527f50726f706f73616c206e6f7420617420657870697279207468726573686f6c646044820152606401610849565b600480835268ffffffffffffffffff841660009081526005602090815260408083208884529091529020835181548593839160ff1916906001908490811115610bde57610bde612d70565b02179055506020820151815460408085015160609095015164ffffffffff16600160d81b026001600160d81b0360ff909616600160d01b0260ff60d01b196001600160c81b039095166101000294909416610100600160d81b03199093169290921792909217939093169290921790555160008051602061348283398151915290610c73908990899089906004908a90613185565b60405180910390a150505050505050565b610c8c612375565b6000848152600460205260409020546001600160a01b031680610ce75760405162461bcd60e51b81526020600482015260136024820152721a5b9d985b1a59081c995cdbdd5c98d9481251606a1b6044820152606401610849565b60ff8616600090815260036020526040812080548290610d0f906001600160401b0316612fc6565b82546001600160401b038083166101009490940a938402930219169190911790915560405163c8ba6c8760e01b81523360048201529091506000906001600160a01b0384169063c8ba6c8790602401602060405180830381865afa158015610d7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9f91906131c2565b905080610dee5760405162461bcd60e51b815260206004820152601760248201527f696e76616c696420736f75726365207265736f757263650000000000000000006044820152606401610849565b6040805160ff8a168152602081018990529081018290526001600160401b0380841660608301528716608082015260a0810186905260c081018590527fe661e74edc20ee64cac60fe9827478a663e2b89663a19ca9dd53aee32233ab319060e00160405180910390a15050505050505050565b610e69612430565b610e71612375565b60008281526004602090815260408083205490516001600160a01b039091169268ffffffffffffffff0060088a901b1660ff8b1617929091610eb99185918a918a91016131db565b60408051601f19818403018152918152815160209283012068ffffffffffffffffff851660009081526005845282812082825290935291209091506002815460ff166004811115610f0c57610f0c612d70565b14610f595760405162461bcd60e51b815260206004820181905260248201527f50726f706f73616c206d757374206861766520506173736564207374617475736044820152606401610849565b805460ff19166003178155838515610fd25760405163712467f960e11b81526001600160a01b0382169063e248cff290610f9b908a908d908d90600401613207565b600060405180830381600087803b158015610fb557600080fd5b505af1158015610fc9573d6000803e3d6000fd5b505050506110af565b60405163712467f960e11b81526001600160a01b0382169063e248cff290611002908a908d908d90600401613207565b600060405180830381600087803b15801561101c57600080fd5b505af192505050801561102d575060015b6110af573d80801561105b576040519150601f19603f3d011682016040523d82523d6000602084013e611060565b606091505b50825460ff191660021783556040517fbd37c1f0d53bb2f33fe4c2104de272fcdeb4d2fef3acdbf1e4ddc3d6833ca3769061109c908390613221565b60405180910390a15050505050506110e3565b6000805160206134828339815191528b888c6003876040516110d5959493929190613185565b60405180910390a150505050505b505050505050565b6110f3612375565b6000868152600460205260409020546001600160a01b0316806111545760405162461bcd60e51b81526020600482015260196024820152781b9bc81a185b991b195c88199bdc881c995cdbdd5c98d95251603a1b6044820152606401610849565b6040516330985a5360e21b815260ff89166004820152602481018890526001600160401b038716604482015260009081906001600160a01b0384169063c261694c9060640160e060405180830381865afa1580156111b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111da9190613244565b60405163d475d3cb60e01b815291935091506001600160a01b0382169063d475d3cb906112139085908b908b908b908b906004016132ff565b600060405180830381600087803b15801561122d57600080fd5b505af1158015611241573d6000803e3d6000fd5b5060009250611255915050878901896133a8565b90507fa12cfd91dc25577484866615ca883a35b8e09f169cc20ed5839a3c4bb3d7754c8b8b8b8487608001516040516110d595949392919060ff95909516855260208501939093526001600160401b0391821660408501528116606084015216608082015260a00190565b6000828152600160205260409020600201546112dc9033611834565b6113405760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e60448201526e0818591b5a5b881d1bc819dc985b9d608a1b6064820152608401610849565b61134a8282612494565b5050565b6001600160a01b03811633146113be5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610849565b61134a82826124ed565b6113d0612546565b82811461141f5760405162461bcd60e51b815260206004820152601f60248201527f61646472735b5d2c20616d6f756e74735b5d3a2064696666206c656e677468006044820152606401610849565b60005b8381101561151657600085858381811061143e5761143e6133c5565b90506020020160208101906114539190612c72565b6001600160a01b031684848481811061146e5761146e6133c5565b9050602002013560405160006040518083038185875af1925050503d80600081146114b5576040519150601f19603f3d011682016040523d82523d6000602084013e6114ba565b606091505b50509050806115035760405162461bcd60e51b8152602060048201526015602482015274195d1a195c881d1c985b9cd9995c8819985a5b1959605a1b6044820152606401610849565b508061150e816133db565b915050611422565b5050505050565b611525612546565b61152e8161220a565b6002805460ff191660ff929092169190911790556040518181527fa20d6b84cd798a24038be305eff8a45ca82ef54a2aa2082005d8e14c0a4746c8906020015b60405180910390a150565b60008281526001602081815260408084206001600160a01b038616855290920190529020545b92915050565b600061159f60008051602061346283398151915283611834565b6115c7612546565b336001600160a01b03821614156116205760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f742072656e6f756e6365206f6e6573656c660000000000000000006044820152606401610849565b61162b6000826112c0565b61163660003361134e565b50565b68ffffffffffffffffff8316600090815260056020908152604080832085845290915280822081516080810190925280546116d7929190829060ff16600481111561168657611686612d70565b600481111561169757611697612d70565b8152905461010081046001600160c81b03166020830152600160d01b810460ff166040830152600160d81b900464ffffffffff166060909101528361259d565b949350505050565b60006116f8600080516020613462833981519152611f0f565b905090565b611705612546565b61170d6125c0565b565b611717612546565b6040516307b7ed9960e01b81526001600160a01b0382811660048301528391908216906307b7ed99906024015b600060405180830381600087803b15801561175e57600080fd5b505af1158015611772573d6000803e3d6000fd5b50505050505050565b6000828152600160205260408120611793908361261a565b9392505050565b6117a2612546565b60025461010090046001600160801b03168114156118025760405162461bcd60e51b815260206004820152601f60248201527f43757272656e742066656520697320657175616c20746f206e657720666565006044820152606401610849565b61180b8161226f565b600260016101000a8154816001600160801b0302191690836001600160801b0316021790555050565b60008281526001602052604081206117939083612353565b61186460008051602061346283398151915282611834565b6118b05760405162461bcd60e51b815260206004820152601f60248201527f6164647220646f65736e277420686176652072656c6179657220726f6c6521006044820152606401610849565b6118c8600080516020613462833981519152826120c0565b6040516001600160a01b03821681527f10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b9060200161156e565b60408051608081018252600080825260208201819052918101829052606081019190915260ff848116600885901b68ffffffffffffffff0016176000818152600560209081526040808320878452909152908190208151608081019092528054929391929091839116600481111561197b5761197b612d70565b600481111561198c5761198c612d70565b8152905461010081046001600160c81b03166020830152600160d01b810460ff166040830152600160d81b900464ffffffffff1660609091015295945050505050565b6119d7612546565b60405163025a3c9960e21b815282906001600160a01b03821690630968f26490611744908590600401613221565b611a0d612430565b611a15612375565b60008381526004602090815260408083205490516001600160a01b039091169268ffffffffffffffff00600889901b1660ff8a1617929091611a5d91859188918891016131db565b60408051601f19818403018152828252805160209182012068ffffffffffffffffff861660009081526005835283812082825290925282822060808501909352825490945090929190829060ff166004811115611abc57611abc612d70565b6004811115611acd57611acd612d70565b8152905461010081046001600160c81b0316602080840191909152600160d01b820460ff16604080850191909152600160d81b90920464ffffffffff1660609093019290925260008a815260049092529020549091506001600160a01b0316611b745760405162461bcd60e51b81526020600482015260196024820152781b9bc81a185b991b195c88199bdc881c995cdbdd5c98d95251603a1b6044820152606401610849565b600281516004811115611b8957611b89612d70565b1415611ba757611b9e898988888b6001610e61565b50505050611516565b80516001906004811115611bbd57611bbd612d70565b1115611c175760405162461bcd60e51b815260206004820152602360248201527f70726f706f73616c20616c72656164792065786563757465642f63616e63656c6044820152621b195960ea1b6064820152608401610849565b611c21813361259d565b15611c665760405162461bcd60e51b81526020600482015260156024820152741c995b185e595c88185b1c9958591e481d9bdd1959605a1b6044820152606401610849565b600081516004811115611c7b57611c7b612d70565b1415611cdd57506040805160808101825260018082526000602083018190528284015264ffffffffff431660608301529151909160008051602061348283398151915291611cd0918c918b918d918890613185565b60405180910390a1611d41565b600254606082015164ffffffffff600160881b909204821691611d01911643612fed565b64ffffffffff161115611d4157600480825260405160008051602061348283398151915291611d38918c918b918d91908890613185565b60405180910390a15b600481516004811115611d5657611d56612d70565b14611e2457611d7b611d6733612626565b82602001516001600160c81b031617612656565b6001600160c81b0316602082015260408101805190611d99826133f6565b60ff1690525080516040517f25f8daaa4635a7729927ba3f5b3d59cc3320aca7c32c9db4e7ca7b957434364091611dd5918c918c918790613416565b60405180910390a1600254604082015160ff918216911610611e2457600280825260405160008051602061348283398151915291611e1b918c918b918d91908890613185565b60405180910390a15b68ffffffffffffffffff8316600090815260056020908152604080832085845290915290208151815483929190829060ff19166001836004811115611e6b57611e6b612d70565b021790555060208201518154604084015160609094015164ffffffffff16600160d81b026001600160d81b0360ff909516600160d01b0260ff60d01b196001600160c81b039094166101000293909316610100600160d81b0319909216919091179190911792909216919091179055600281516004811115611eef57611eef612d70565b1415611f0457611f04898988888b6000610e61565b505050505050505050565b600081815260016020526040812061159f906126bf565b611f2e612546565b60008281526004602081905260409182902080546001600160a01b0319166001600160a01b038781169182179092559251635c7d1b9b60e11b81529182018590528316602482015284919063b8fa373690604401600060405180830381600087803b158015611f9c57600080fd5b505af1158015611fb0573d6000803e3d6000fd5b5050505050505050565b611fd260008051602061346283398151915282611834565b1561201f5760405162461bcd60e51b815260206004820152601e60248201527f6164647220616c7265616479206861732072656c6179657220726f6c652100006044820152606401610849565b60c86120296116df565b1061206f5760405162461bcd60e51b81526020600482015260166024820152751c995b185e595c9cc81b1a5b5a5d081c995858da195960521b6044820152606401610849565b612087600080516020613462833981519152826112c0565b6040516001600160a01b03821681527f03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c59060200161156e565b6000828152600160205260409020600201546120dc9033611834565b6113be5760405162461bcd60e51b815260206004820152603060248201527f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e60448201526f2061646d696e20746f207265766f6b6560801b6064820152608401610849565b612149612546565b60ff82166000908152600360205260409020546001600160401b03908116908216116121c65760405162461bcd60e51b815260206004820152602660248201527f446f6573206e6f7420616c6c6f772064656372656d656e7473206f6620746865604482015265206e6f6e636560d01b6064820152608401610849565b60ff919091166000908152600360205260409020805467ffffffffffffffff19166001600160401b03909216919091179055565b612202612546565b61170d6126c9565b600060ff82111561226b5760405162461bcd60e51b815260206004820152602560248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2038604482015264206269747360d81b6064820152608401610849565b5090565b60006001600160801b0382111561226b5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b6064820152608401610849565b600064ffffffffff82111561226b5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526530206269747360d01b6064820152608401610849565b6000611793836001600160a01b038416612702565b6001600160a01b03811660009081526001830160205260408120541515611793565b60005460ff161561170d5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610849565b6123c6600033611834565b806123e457506123e460008051602061346283398151915233611834565b61170d5760405162461bcd60e51b815260206004820152601e60248201527f73656e646572206973206e6f742072656c61796572206f722061646d696e00006044820152606401610849565b61244860008051602061346283398151915233611834565b61170d5760405162461bcd60e51b815260206004820181905260248201527f73656e64657220646f65736e277420686176652072656c6179657220726f6c656044820152606401610849565b60008281526001602052604090206124ac908261233e565b1561134a5760405133906001600160a01b0383169084907f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d90600090a45050565b60008281526001602052604090206125059082612751565b1561134a5760405133906001600160a01b0383169084907ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b90600090a45050565b612551600033611834565b61170d5760405162461bcd60e51b815260206004820152601e60248201527f73656e64657220646f65736e277420686176652061646d696e20726f6c6500006044820152606401610849565b60008083602001516001600160c81b03166125b784612626565b16119392505050565b6125c8612375565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586125fd3390565b6040516001600160a01b03909116815260200160405180910390a1565b60006117938383612766565b6000600161264260008051602061346283398151915284611579565b61264c9190612fed565b6001901b92915050565b60006001600160c81b0382111561226b5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663030206269747360c81b6064820152608401610849565b600061159f825490565b6126d1612790565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa336125fd565b60008181526001830160205260408120546127495750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561159f565b50600061159f565b6000611793836001600160a01b0384166127d9565b600082600001828154811061277d5761277d6133c5565b9060005260206000200154905092915050565b60005460ff1661170d5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610849565b600081815260018301602052604081205480156128c25760006127fd600183612fed565b855490915060009061281190600190612fed565b9050818114612876576000866000018281548110612831576128316133c5565b9060005260206000200154905080876000018481548110612854576128546133c5565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806128875761288761344b565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061159f565b600091505061159f565b60ff8116811461163657600080fd5b60008083601f8401126128ed57600080fd5b5081356001600160401b0381111561290457600080fd5b60208301915083602082850101111561291c57600080fd5b9250929050565b6000806000806060858703121561293957600080fd5b8435612944816128cc565b93506020850135925060408501356001600160401b0381111561296657600080fd5b612972878288016128db565b95989497509550505050565b6001600160401b038116811461163657600080fd5b600080600080608085870312156129a957600080fd5b84356129b4816128cc565b93506020850135925060408501356129cb8161297e565b9396929550929360600135925050565b600080600080600060a086880312156129f357600080fd5b85356129fe816128cc565b9450602086013593506040860135612a158161297e565b94979396509394606081013594506080013592915050565b60008060008060008060a08789031215612a4657600080fd5b8635612a51816128cc565b95506020870135612a618161297e565b945060408701356001600160401b03811115612a7c57600080fd5b612a8889828a016128db565b9095509350506060870135915060808701358015158114612aa857600080fd5b809150509295509295509295565b600060208284031215612ac857600080fd5b5035919050565b60008083601f840112612ae157600080fd5b5081356001600160401b03811115612af857600080fd5b6020830191508360208260051b850101111561291c57600080fd5b600080600080600080600060a0888a031215612b2e57600080fd5b8735612b39816128cc565b9650602088013595506040880135612b508161297e565b945060608801356001600160401b0380821115612b6c57600080fd5b612b788b838c016128db565b909650945060808a0135915080821115612b9157600080fd5b50612b9e8a828b01612acf565b989b979a50959850939692959293505050565b6001600160a01b038116811461163657600080fd5b60008060408385031215612bd957600080fd5b823591506020830135612beb81612bb1565b809150509250929050565b60008060008060408587031215612c0c57600080fd5b84356001600160401b0380821115612c2357600080fd5b612c2f88838901612acf565b90965094506020870135915080821115612c4857600080fd5b5061297287828801612acf565b600060208284031215612c6757600080fd5b8135611793816128cc565b600060208284031215612c8457600080fd5b813561179381612bb1565b600080600060608486031215612ca457600080fd5b833568ffffffffffffffffff81168114612cbd57600080fd5b9250602084013591506040840135612cd481612bb1565b809150509250925092565b60008060408385031215612cf257600080fd5b8235612cfd81612bb1565b91506020830135612beb81612bb1565b60008060408385031215612d2057600080fd5b50508035926020909101359150565b600080600060608486031215612d4457600080fd5b8335612d4f816128cc565b92506020840135612d5f8161297e565b929592945050506040919091013590565b634e487b7160e01b600052602160045260246000fd5b60058110612da457634e487b7160e01b600052602160045260246000fd5b9052565b6000608082019050612dbb828451612d86565b60018060c81b03602084015116602083015260ff604084015116604083015264ffffffffff606084015116606083015292915050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715612e2f57612e2f612df1565b604052919050565b60006001600160401b03821115612e5057612e50612df1565b50601f01601f191660200190565b60008060408385031215612e7157600080fd5b8235612e7c81612bb1565b915060208301356001600160401b03811115612e9757600080fd5b8301601f81018513612ea857600080fd5b8035612ebb612eb682612e37565b612e07565b818152866020838501011115612ed057600080fd5b816020840160208301376000602083830101528093505050509250929050565b600080600080600060808688031215612f0857600080fd5b8535612f13816128cc565b94506020860135612f238161297e565b93506040860135925060608601356001600160401b03811115612f4557600080fd5b612f51888289016128db565b969995985093965092949392505050565b600080600060608486031215612f7757600080fd5b8335612cbd81612bb1565b60008060408385031215612f9557600080fd5b8235612fa0816128cc565b91506020830135612beb8161297e565b634e487b7160e01b600052601160045260246000fd5b60006001600160401b0380831681811415612fe357612fe3612fb0565b6001019392505050565b600082821015612fff57612fff612fb0565b500390565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8481526001600160a01b03841660208201526060604082018190526000906130589083018486613004565b9695505050505050565b60005b8381101561307d578181015183820152602001613065565b8381111561308c576000848401525b50505050565b6000602082840312156130a457600080fd5b81516001600160401b038111156130ba57600080fd5b8201601f810184136130cb57600080fd5b80516130d9612eb682612e37565b8181528560208385010111156130ee57600080fd5b6130ff826020830160208601613062565b95945050505050565b60008151808452613120816020860160208601613062565b601f01601f19169290920160200192915050565b60ff871681528560208201526001600160401b038516604082015260a06060820152600061316660a083018587613004565b82810360808401526131788185613108565b9998505050505050505050565b60ff86168152602081018590526001600160401b038416604082015260a081016131b26060830185612d86565b8260808301529695505050505050565b6000602082840312156131d457600080fd5b5051919050565b6bffffffffffffffffffffffff198460601b168152818360148301376000910160140190815292915050565b8381526040602082015260006130ff604083018486613004565b6020815260006117936020830184613108565b805161323f81612bb1565b919050565b60008082840360e081121561325857600080fd5b60c081121561326657600080fd5b5060405160c081018181106001600160401b038211171561328957613289612df1565b6040528351613297816128cc565b815260208401516132a78161297e565b80602083015250604084015160408201526060840151606082015260808401516132d08161297e565b608082015260a08401516132e381612bb1565b60a082015291506132f660c08401613234565b90509250929050565b600061010060ff885116835260208801516001600160401b03808216602086015260408a0151604086015260608a015160608601528060808b0151166080860152505060018060a01b0360a08901511660a08401528060c08401526133678184018789613004565b83810360e085015284815290506001600160fb1b0384111561338857600080fd5b8360051b8086602084013760009101602001908152979650505050505050565b6000602082840312156133ba57600080fd5b81356117938161297e565b634e487b7160e01b600052603260045260246000fd5b60006000198214156133ef576133ef612fb0565b5060010190565b600060ff821660ff81141561340d5761340d612fb0565b60010192915050565b60ff851681526001600160401b03841660208201526080810161343c6040830185612d86565b82606083015295945050505050565b634e487b7160e01b600052603160045260246000fdfee2b7fb3b832174769106daebcfd6d1970523240dda11281102db9363b83b0dc4efff49f4c5619a2ddc010f7bd6cf656ebb90da54c8469c26ac330ce7619e5c1ea26469706673582212206d2acc8ac4bfbe2ba169e3771da55a7310f266b89cbaf57a7f0964083bbcb09d64736f6c634300080b0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009896800000000000000000000000000000000000000000000000000000000000000002000000000000000000000000980754a1bdb3ddde98ba0e63bb985630096aac480000000000000000000000001f06ec074d88403c5837078aab4e696716b6544d
-----Decoded View---------------
Arg [0] : domainID (uint8): 1
Arg [1] : initialRelayers (address[]): 0x980754A1bdb3DDdE98ba0E63BB985630096AAC48,0x1F06ec074D88403C5837078Aab4E696716B6544D
Arg [2] : initialRelayerThreshold (uint256): 1
Arg [3] : fee (uint256): 0
Arg [4] : expiry (uint256): 10000000
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000989680
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [6] : 000000000000000000000000980754a1bdb3ddde98ba0e63bb985630096aac48
Arg [7] : 0000000000000000000000001f06ec074d88403c5837078aab4e696716b6544d
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ 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.