Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
21371952 | 34 hrs ago | 0.0001116 ETH | ||||
21371952 | 34 hrs ago | 0.0001116 ETH | ||||
21328033 | 7 days ago | 0.0001485 ETH | ||||
21328033 | 7 days ago | 0.0001485 ETH | ||||
21318696 | 8 days ago | 0.000051 ETH | ||||
21318696 | 8 days ago | 0.000051 ETH | ||||
21309256 | 10 days ago | 0.00012212 ETH | ||||
21309256 | 10 days ago | 0.00012212 ETH | ||||
21305949 | 10 days ago | 0.00014792 ETH | ||||
21305949 | 10 days ago | 0.00014792 ETH | ||||
21303319 | 11 days ago | 0.00012225 ETH | ||||
21303319 | 11 days ago | 0.00012225 ETH | ||||
21301396 | 11 days ago | 0.00005073 ETH | ||||
21301396 | 11 days ago | 0.00005073 ETH | ||||
21296089 | 12 days ago | 0.00012238 ETH | ||||
21296089 | 12 days ago | 0.00012238 ETH | ||||
21287368 | 13 days ago | 0.0001386 ETH | ||||
21287368 | 13 days ago | 0.0001386 ETH | ||||
21286626 | 13 days ago | 0.00005125 ETH | ||||
21286626 | 13 days ago | 0.00005125 ETH | ||||
21278253 | 14 days ago | 0.00005285 ETH | ||||
21278253 | 14 days ago | 0.00005285 ETH | ||||
21278024 | 14 days ago | 0.00011501 ETH | ||||
21278024 | 14 days ago | 0.00011501 ETH | ||||
21277517 | 14 days ago | 0.00005263 ETH |
Loading...
Loading
Contract Name:
Bridge
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.17; import "./libraries/Utils.sol"; import "./roles/Attestable.sol"; import "./interfaces/IBridge.sol"; import "./interfaces/IReceiver.sol"; import "./interfaces/ICallProxy.sol"; import "./interfaces/ITokenMessenger.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; contract Bridge is IBridge, Attestable, Pausable, ReentrancyGuard { using SafeERC20 for IERC20; address public feeCollector; address public tokenMessenger; address public callProxy; // destination domain => destination bridge mapping(uint32 => bytes32) public bridgeHashMap; // token => disabled mapping(address => bool) public disabledBridgeTokens; // token, destination domain => disabled mapping(address => mapping(uint32 => bool)) public disabledRoutes; event SetTokenMessenger(address tokenMessenger); event SetFeeCollector(address feeCollector); event SetCallProxy(address callProxy); event EnableBridgeToken(address token); event DisableBridgeToken(address token); event EnableRoute(address token, uint32 destinationDomain); event DisableRoute(address token, uint32 destinationDomain); event BindBridge(uint32 destinationDomain, bytes32 targetBridge); event BindBridgeBatch(uint32[] destinationDomains, bytes32[] targetBridges); event BridgeOut( address sender, address token, uint32 destinationDomain, uint256 amount, uint64 nonce, bytes32 recipient, bytes callData, uint256 fee ); event BridgeIn( address sender, address recipient, address token, uint256 amount ); struct TxArgs { address token; bytes message; bytes mintAttestation; bytes32 recipient; bytes callData; } receive() external payable { } constructor( address _tokenMessenger, address _attester, address _feeCollector ) Attestable(_attester) { require(_tokenMessenger != address(0), "tokenMessenger address cannot be zero"); require(_feeCollector != address(0), "feeCollector address cannot be zero"); tokenMessenger = _tokenMessenger; feeCollector = _feeCollector; } function bridgeOut( address token, uint256 amount, uint32 destinationDomain, bytes32 recipient, bytes calldata callData ) external payable nonReentrant whenNotPaused { bytes32 targetBridge = bridgeHashMap[destinationDomain]; require(targetBridge != bytes32(0), "target bridge not enabled"); require(msg.sender != callProxy, "forbidden"); require(recipient != bytes32(0), "recipient address cannot be zero"); require(!disabledBridgeTokens[token], "token not enabled"); require(!disabledRoutes[token][destinationDomain], "route disabled"); IERC20(token).safeTransferFrom(msg.sender, address(this), amount); IERC20(token).safeApprove(tokenMessenger, amount); uint64 nonce = ITokenMessenger(tokenMessenger).depositForBurnWithCaller( amount, destinationDomain, targetBridge, token, targetBridge ); sendNative(feeCollector, msg.value); emit BridgeOut(msg.sender, token, destinationDomain, amount, nonce, recipient, callData, msg.value); } function bridgeIn( bytes calldata args, bytes calldata attestation ) external nonReentrant whenNotPaused { require(args.length > 0, "invalid bridgeIn args"); _verifyAttestationSignatures(args, attestation); TxArgs memory txArgs = deserializeTxArgs(args); address token = txArgs.token; uint256 balanceBefore = IERC20(token).balanceOf(address(this)); bool success = _getMessageTransmitter().receiveMessage(txArgs.message, txArgs.mintAttestation); require(success, "receive message failed"); uint256 amount = IERC20(token).balanceOf(address(this)) - balanceBefore; require(amount > 0, "amount cannot be zero"); address recipient = bytes32ToAddress(txArgs.recipient); require(recipient != address(0), "recipient address cannot be zero"); if (txArgs.callData.length == 0 || callProxy == address(0)) { IERC20(token).safeTransfer(recipient, amount); } else { IERC20(token).safeTransfer(callProxy, amount); require(ICallProxy(callProxy).proxyCall(token, amount, recipient, txArgs.callData), "proxy call failed"); } emit BridgeIn(msg.sender, recipient, token, amount); } function getMessageTransmitter() external view returns (IReceiver) { return _getMessageTransmitter(); } function _getMessageTransmitter() internal view returns (IReceiver) { return IReceiver(ITokenMessenger(tokenMessenger).localMessageTransmitter()); } function setTokenMessenger(address newTokenMessenger) onlyOwner external { require(newTokenMessenger != address(0), "tokenMessenger address cannot be zero"); tokenMessenger = newTokenMessenger; emit SetTokenMessenger(newTokenMessenger); } function enableBridgeToken(address token) external onlyOwner { require(token != address(0), "token address cannot be zero"); delete disabledBridgeTokens[token]; emit EnableBridgeToken(token); } function disableBridgeToken(address token) external onlyOwner { require(token != address(0), "token address cannot be zero"); disabledBridgeTokens[token] = true; emit DisableBridgeToken(token); } function enableRouter(address token, uint32 destinationDomain) external onlyOwner { require(token != address(0), "token address cannot be zero"); delete disabledRoutes[token][destinationDomain]; emit EnableRoute(token, destinationDomain); } function disableRoute(address token, uint32 destinationDomain) external onlyOwner { require(token != address(0), "token address cannot be zero"); disabledRoutes[token][destinationDomain] = true; emit DisableRoute(token, destinationDomain); } function setCallProxy(address newCallProxy) onlyOwner external { callProxy = newCallProxy; emit SetCallProxy(newCallProxy); } function setFeeCollector(address newFeeCollector) external onlyOwner { require(newFeeCollector != address(0), "feeCollector address cannot be zero"); feeCollector = newFeeCollector; emit SetFeeCollector(newFeeCollector); } function bindBridge(uint32 destinationDomain, bytes32 targetBridge) onlyOwner external returns (bool) { bridgeHashMap[destinationDomain] = targetBridge; emit BindBridge(destinationDomain, targetBridge); return true; } function bindBridgeBatch(uint32[] calldata destinationDomains, bytes32[] calldata targetBridgeHashes) onlyOwner external returns (bool) { require(destinationDomains.length == targetBridgeHashes.length, "Inconsistent parameter lengths"); for (uint i = 0; i < destinationDomains.length; i++) { bridgeHashMap[destinationDomains[i]] = targetBridgeHashes[i]; } emit BindBridgeBatch(destinationDomains, targetBridgeHashes); return true; } function externalCall(address callee, bytes calldata data) external onlyOwner { (bool success, ) = callee.call(data); require(success, "external call failed"); } function rescueFund(address tokenAddress) external onlyOwner { IERC20 token = IERC20(tokenAddress); token.safeTransfer(_msgSender(), token.balanceOf(address(this))); } function rescueNative(address receiver) external onlyOwner { sendNative(receiver, address(this).balance); } function pause() external onlyOwner { _pause(); } function unpause() external onlyOwner { _unpause(); } function sendNative(address receiver, uint256 amount) internal { (bool success, ) = receiver.call{ value: amount }(""); require(success, "unable to send value, recipient may have reverted"); } function deserializeTxArgs(bytes calldata rawArgs) internal pure returns (TxArgs memory) { TxArgs memory txArgs; uint256 offset = 0; bytes memory tokenBytes; (tokenBytes, offset) = Utils.NextVarBytes(rawArgs, offset); txArgs.token = Utils.bytesToAddress(tokenBytes); (txArgs.message, offset) = Utils.NextVarBytes(rawArgs, offset); (txArgs.mintAttestation, offset) = Utils.NextVarBytes(rawArgs, offset); bytes memory recipientBytes; (recipientBytes, offset) = Utils.NextVarBytes(rawArgs, offset); txArgs.recipient = addressToBytes32(Utils.bytesToAddress(recipientBytes)); (txArgs.callData, offset) = Utils.NextVarBytes(rawArgs, offset); return txArgs; } // May revert if current chain does not implement the `BASEFEE` opcode function getBasefee() external view returns (uint256 basefee) { basefee = block.basefee; } function addressToBytes32(address addr) internal pure returns (bytes32) { return bytes32(uint256(uint160(addr))); } function bytes32ToAddress(bytes32 _buf) internal pure returns (address) { return address(uint160(uint256(_buf))); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or 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 { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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: 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.8.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. 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) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // 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 in 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: AGPL-3.0 pragma solidity 0.8.17; import "@openzeppelin/contracts/utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
/* * Copyright (c) 2022, Circle Internet Financial Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.17; import "./Ownable.sol"; /** * @dev forked from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/7c5f6bc2c8743d83443fa46395d75f2f3f99054a/contracts/access/Ownable2Step.sol * Modifications: * 1. Update Solidity version from 0.8.0 to 0.7.6. Version 0.8.0 was used * as base because this contract was added to OZ repo after version 0.8.0. * * Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted( address indexed previousOwner, address indexed newOwner ); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { require(newOwner != address(0), "new owner address cannot be zero"); _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() external { address sender = _msgSender(); require( pendingOwner() == sender, "Ownable2Step: caller is not the new owner" ); _transferOwnership(sender); } }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.0; interface IBridge { function callProxy() external returns (address); function bridgeOut( address token, uint256 amount, uint32 destinationDomain, bytes32 recipient, bytes calldata callData ) external payable; function bridgeIn( bytes calldata args, bytes calldata attestation ) external; }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.17; interface ICallProxy { function proxyCall( address token, uint256 amount, address receiver, bytes memory callData ) external returns (bool); }
/* * Copyright (c) 2022, Circle Internet Financial Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.17; import "./IReceiver.sol"; /** * @title IMessageTransmitter * @notice Interface for message transmitters, which both relay and receive messages. */ interface IMessageTransmitter is IReceiver { function localDomain() external view returns (uint32); }
/* * Copyright (c) 2022, Circle Internet Financial Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.17; /** * @title IReceiver * @notice Receives messages on destination chain and forwards them to IMessageDestinationHandler */ interface IReceiver { /** * @notice Receives an incoming message, validating the header and passing * the body to application-specific handler. * @param message The message raw bytes * @param signature The message signature * @return success bool, true if successful */ function receiveMessage(bytes calldata message, bytes calldata signature) external returns (bool success); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.17; import "./IMessageTransmitter.sol"; interface ITokenMessenger { function depositForBurn( uint256 amount, uint32 destinationDomain, bytes32 mintRecipient, address burnToken ) external returns (uint64 _nonce); function depositForBurnWithCaller( uint256 amount, uint32 destinationDomain, bytes32 mintRecipient, address burnToken, bytes32 destinationCaller ) external returns (uint64 nonce); function localMessageTransmitter() external view returns (IMessageTransmitter); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.0; library Utils { function WriteByte(bytes1 b) internal pure returns (bytes memory) { return WriteUint8(uint8(b)); } function WriteUint8(uint8 v) internal pure returns (bytes memory) { bytes memory buff; assembly{ buff := mload(0x40) mstore(buff, 1) mstore(add(buff, 0x20), shl(248, v)) // mstore(add(buff, 0x20), byte(0x1f, v)) mstore(0x40, add(buff, 0x21)) } return buff; } function WriteUint16(uint16 v) internal pure returns (bytes memory) { bytes memory buff; assembly{ buff := mload(0x40) let byteLen := 0x02 mstore(buff, byteLen) for { let mindex := 0x00 let vindex := 0x1f } lt(mindex, byteLen) { mindex := add(mindex, 0x01) vindex := sub(vindex, 0x01) }{ mstore8(add(add(buff, 0x20), mindex), byte(vindex, v)) } mstore(0x40, add(buff, 0x22)) } return buff; } function WriteUint32(uint32 v) internal pure returns(bytes memory) { bytes memory buff; assembly{ buff := mload(0x40) let byteLen := 0x04 mstore(buff, byteLen) for { let mindex := 0x00 let vindex := 0x1f } lt(mindex, byteLen) { mindex := add(mindex, 0x01) vindex := sub(vindex, 0x01) }{ mstore8(add(add(buff, 0x20), mindex), byte(vindex, v)) } mstore(0x40, add(buff, 0x24)) } return buff; } function WriteUint64(uint64 v) internal pure returns(bytes memory) { bytes memory buff; assembly{ buff := mload(0x40) let byteLen := 0x08 mstore(buff, byteLen) for { let mindex := 0x00 let vindex := 0x1f } lt(mindex, byteLen) { mindex := add(mindex, 0x01) vindex := sub(vindex, 0x01) }{ mstore8(add(add(buff, 0x20), mindex), byte(vindex, v)) } mstore(0x40, add(buff, 0x28)) } return buff; } function WriteUint255(uint256 v) internal pure returns (bytes memory) { require(v <= 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, "Value exceeds uint255 range"); bytes memory buff; assembly{ buff := mload(0x40) let byteLen := 0x20 mstore(buff, byteLen) for { let mindex := 0x00 let vindex := 0x1f } lt(mindex, byteLen) { mindex := add(mindex, 0x01) vindex := sub(vindex, 0x01) }{ mstore8(add(add(buff, 0x20), mindex), byte(vindex, v)) } mstore(0x40, add(buff, 0x40)) } return buff; } function WriteVarBytes(bytes memory data) internal pure returns (bytes memory) { uint64 l = uint64(data.length); return abi.encodePacked(WriteVarUint(l), data); } function WriteVarUint(uint64 v) internal pure returns (bytes memory) { if (v < 0xFD){ return WriteUint8(uint8(v)); } else if (v <= 0xFFFF) { return abi.encodePacked(WriteByte(0xFD), WriteUint16(uint16(v))); } else if (v <= 0xFFFFFFFF) { return abi.encodePacked(WriteByte(0xFE), WriteUint32(uint32(v))); } else { return abi.encodePacked(WriteByte(0xFF), WriteUint64(uint64(v))); } } function NextByte(bytes memory buff, uint256 offset) internal pure returns (bytes1, uint256) { require(offset + 1 <= buff.length && offset < offset + 1, "NextByte, Offset exceeds maximum"); bytes1 v; assembly{ v := mload(add(add(buff, 0x20), offset)) } return (v, offset + 1); } function NextUint8(bytes memory buff, uint256 offset) internal pure returns (uint8, uint256) { require(offset + 1 <= buff.length && offset < offset + 1, "NextUint8, Offset exceeds maximum"); uint8 v; assembly{ let tmpbytes := mload(0x40) let bvalue := mload(add(add(buff, 0x20), offset)) mstore8(tmpbytes, byte(0, bvalue)) mstore(0x40, add(tmpbytes, 0x01)) v := mload(sub(tmpbytes, 0x1f)) } return (v, offset + 1); } function NextUint16(bytes memory buff, uint256 offset) internal pure returns (uint16, uint256) { require(offset + 2 <= buff.length && offset < offset + 2, "NextUint16, offset exceeds maximum"); uint16 v; assembly { let tmpbytes := mload(0x40) let bvalue := mload(add(add(buff, 0x20), offset)) mstore8(tmpbytes, byte(0x01, bvalue)) mstore8(add(tmpbytes, 0x01), byte(0, bvalue)) mstore(0x40, add(tmpbytes, 0x02)) v := mload(sub(tmpbytes, 0x1e)) } return (v, offset + 2); } function NextUint32(bytes memory buff, uint256 offset) internal pure returns (uint32, uint256) { require(offset + 4 <= buff.length && offset < offset + 4, "NextUint32, offset exceeds maximum"); uint32 v; assembly { let tmpbytes := mload(0x40) let byteLen := 0x04 for { let tindex := 0x00 let bindex := sub(byteLen, 0x01) let bvalue := mload(add(add(buff, 0x20), offset)) } lt(tindex, byteLen) { tindex := add(tindex, 0x01) bindex := sub(bindex, 0x01) }{ mstore8(add(tmpbytes, tindex), byte(bindex, bvalue)) } mstore(0x40, add(tmpbytes, byteLen)) v := mload(sub(tmpbytes, sub(0x20, byteLen))) } return (v, offset + 4); } function NextUint64(bytes memory buff, uint256 offset) internal pure returns (uint64, uint256) { require(offset + 8 <= buff.length && offset < offset + 8, "NextUint64, offset exceeds maximum"); uint64 v; assembly { let tmpbytes := mload(0x40) let byteLen := 0x08 for { let tindex := 0x00 let bindex := sub(byteLen, 0x01) let bvalue := mload(add(add(buff, 0x20), offset)) } lt(tindex, byteLen) { tindex := add(tindex, 0x01) bindex := sub(bindex, 0x01) }{ mstore8(add(tmpbytes, tindex), byte(bindex, bvalue)) } mstore(0x40, add(tmpbytes, byteLen)) v := mload(sub(tmpbytes, sub(0x20, byteLen))) } return (v, offset + 8); } function NextUint255(bytes memory buff, uint256 offset) internal pure returns (uint256, uint256) { require(offset + 32 <= buff.length && offset < offset + 32, "NextUint255, offset exceeds maximum"); uint256 v; assembly { let tmpbytes := mload(0x40) let byteLen := 0x20 for { let tindex := 0x00 let bindex := sub(byteLen, 0x01) let bvalue := mload(add(add(buff, 0x20), offset)) } lt(tindex, byteLen) { tindex := add(tindex, 0x01) bindex := sub(bindex, 0x01) }{ mstore8(add(tmpbytes, tindex), byte(bindex, bvalue)) } mstore(0x40, add(tmpbytes, byteLen)) v := mload(tmpbytes) } require(v <= 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, "Value exceeds the range"); return (v, offset + 32); } function NextVarBytes(bytes memory buff, uint256 offset) internal pure returns(bytes memory, uint256) { uint len; (len, offset) = NextVarUint(buff, offset); require(offset + len <= buff.length && offset <= offset + len, "NextVarBytes, offset exceeds maximum"); bytes memory tempBytes; assembly{ switch iszero(len) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(len, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, len) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(buff, lengthmod), mul(0x20, iszero(lengthmod))), offset) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, len) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) mstore(0x40, add(tempBytes, 0x20)) } } return (tempBytes, offset + len); } function NextVarUint(bytes memory buff, uint256 offset) internal pure returns(uint, uint256) { bytes1 v; (v, offset) = NextByte(buff, offset); uint value; if (v == 0xFD) { // return NextUint16(buff, offset); (value, offset) = NextUint16(buff, offset); require(value >= 0xFD && value <= 0xFFFF, "NextUint16, value outside range"); return (value, offset); } else if (v == 0xFE) { // return NextUint32(buff, offset); (value, offset) = NextUint32(buff, offset); require(value > 0xFFFF && value <= 0xFFFFFFFF, "NextVarUint, value outside range"); return (value, offset); } else if (v == 0xFF) { // return NextUint64(buff, offset); (value, offset) = NextUint64(buff, offset); require(value > 0xFFFFFFFF, "NextVarUint, value outside range"); return (value, offset); } else{ // return (uint8(v), offset); value = uint8(v); require(value < 0xFD, "NextVarUint, value outside range"); return (value, offset); } } function bytesToAddress(bytes memory _bs) internal pure returns (address addr) { require(_bs.length == 20, "bytes length does not match address"); assembly { // for _bs, first word store _bs.length, second word store _bs.value // load 32 bytes from mem[_bs+20], convert it into Uint160, meaning we take last 20 bytes as addr (address). addr := mload(add(_bs, 0x14)) } } function equalStorage(bytes storage _preBytes, bytes memory _postBytes) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // fslot can contain both the length and contents of the array // if slength < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage // slength != 0 if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint(mc < end) + cb == 2) for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } }
/* * Copyright (c) 2022, Circle Internet Financial Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.17; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "../access/Ownable2Step.sol"; contract Attestable is Ownable2Step { // ============ Events ============ /** * @notice Emitted when an attester is enabled * @param attester newly enabled attester */ event AttesterEnabled(address indexed attester); /** * @notice Emitted when an attester is disabled * @param attester newly disabled attester */ event AttesterDisabled(address indexed attester); /** * @notice Emitted when threshold number of attestations (m in m/n multisig) is updated * @param oldSignatureThreshold old signature threshold * @param newSignatureThreshold new signature threshold */ event SignatureThresholdUpdated( uint256 oldSignatureThreshold, uint256 newSignatureThreshold ); /** * @dev Emitted when attester manager address is updated * @param previousAttesterManager representing the address of the previous attester manager * @param newAttesterManager representing the address of the new attester manager */ event AttesterManagerUpdated( address indexed previousAttesterManager, address indexed newAttesterManager ); // ============ Libraries ============ using EnumerableSet for EnumerableSet.AddressSet; // ============ State Variables ============ // number of signatures from distinct attesters required for a message to be received (m in m/n multisig) uint256 public signatureThreshold; // 65-byte ECDSA signature: v (32) + r (32) + s (1) uint256 internal constant signatureLength = 65; // enabled attesters (message signers) // (length of enabledAttesters is n in m/n multisig of message signers) EnumerableSet.AddressSet private enabledAttesters; // Attester Manager of the contract address private _attesterManager; // ============ Modifiers ============ /** * @dev Throws if called by any account other than the attester manager. */ modifier onlyAttesterManager() { require(msg.sender == _attesterManager, "Caller not attester manager"); _; } // ============ Constructor ============ /** * @dev The constructor sets the original attester manager of the contract to the sender account. * @param attester attester to initialize */ constructor(address attester) { _setAttesterManager(msg.sender); // Initially 1 signature is required. Threshold can be increased by attesterManager. signatureThreshold = 1; enableAttester(attester); } // ============ Public/External Functions ============ /** * @notice Enables an attester * @dev Only callable by attesterManager. New attester must be nonzero, and currently disabled. * @param newAttester attester to enable */ function enableAttester(address newAttester) public onlyAttesterManager { require(newAttester != address(0), "New attester must be nonzero"); require(enabledAttesters.add(newAttester), "Attester already enabled"); emit AttesterEnabled(newAttester); } /** * @notice returns true if given `attester` is enabled, else false * @param attester attester to check enabled status of * @return true if given `attester` is enabled, else false */ function isEnabledAttester(address attester) public view returns (bool) { return enabledAttesters.contains(attester); } /** * @notice returns the number of enabled attesters * @return number of enabled attesters */ function getNumEnabledAttesters() public view returns (uint256) { return enabledAttesters.length(); } /** * @dev Allows the current attester manager to transfer control of the contract to a newAttesterManager. * @param newAttesterManager The address to update attester manager to. */ function updateAttesterManager(address newAttesterManager) external onlyOwner { require( newAttesterManager != address(0), "Invalid attester manager address" ); address _oldAttesterManager = _attesterManager; _setAttesterManager(newAttesterManager); emit AttesterManagerUpdated(_oldAttesterManager, newAttesterManager); } /** * @notice Disables an attester * @dev Only callable by attesterManager. Disabling the attester is not allowed if there is only one attester * enabled, or if it would cause the number of enabled attesters to become less than signatureThreshold. * (Attester must be currently enabled.) * @param attester attester to disable */ function disableAttester(address attester) external onlyAttesterManager { // Disallow disabling attester if there is only 1 active attester uint256 _numEnabledAttesters = getNumEnabledAttesters(); require(_numEnabledAttesters > 1, "Too few enabled attesters"); // Disallow disabling an attester if it would cause the n in m/n multisig to fall below m (threshold # of signers). require( _numEnabledAttesters > signatureThreshold, "Signature threshold is too low" ); require(enabledAttesters.remove(attester), "Attester already disabled"); emit AttesterDisabled(attester); } /** * @notice Sets the threshold of signatures required to attest to a message. * (This is the m in m/n multisig.) * @dev new signature threshold must be nonzero, and must not exceed number * of enabled attesters. * @param newSignatureThreshold new signature threshold */ function setSignatureThreshold(uint256 newSignatureThreshold) external onlyAttesterManager { require(newSignatureThreshold != 0, "Invalid signature threshold"); // New signature threshold cannot exceed the number of enabled attesters require( newSignatureThreshold <= enabledAttesters.length(), "New signature threshold too high" ); require( newSignatureThreshold != signatureThreshold, "Signature threshold already set" ); uint256 _oldSignatureThreshold = signatureThreshold; signatureThreshold = newSignatureThreshold; emit SignatureThresholdUpdated( _oldSignatureThreshold, signatureThreshold ); } /** * @dev Returns the address of the attester manager * @return address of the attester manager */ function attesterManager() external view returns (address) { return _attesterManager; } /** * @notice gets enabled attester at given `index` * @param index index of attester to check * @return enabled attester at given `index` */ function getEnabledAttester(uint256 index) external view returns (address) { return enabledAttesters.at(index); } // ============ Internal Utils ============ /** * @dev Sets a new attester manager address * @param _newAttesterManager attester manager address to set */ function _setAttesterManager(address _newAttesterManager) internal { _attesterManager = _newAttesterManager; } /** * @notice reverts if the attestation, which is comprised of one or more concatenated 65-byte signatures, is invalid. * @dev Rules for valid attestation: * 1. length of `_attestation` == 65 (signature length) * signatureThreshold * 2. addresses recovered from attestation must be in increasing order. * For example, if signature A is signed by address 0x1..., and signature B * is signed by address 0x2..., attestation must be passed as AB. * 3. no duplicate signers * 4. all signers must be enabled attesters * * Based on Christian Lundkvist's Simple Multisig * (https://github.com/christianlundkvist/simple-multisig/tree/560c463c8651e0a4da331bd8f245ccd2a48ab63d) * @param _message message to verify attestation of * @param _attestation attestation of `_message` */ function _verifyAttestationSignatures( bytes calldata _message, bytes calldata _attestation ) internal view { require( _attestation.length == signatureLength * signatureThreshold, "Invalid attestation length" ); // (Attesters cannot be address(0)) address _latestAttesterAddress = address(0); // Address recovered from signatures must be in increasing order, to prevent duplicates bytes32 _digest = keccak256(_message); for (uint256 i; i < signatureThreshold; ++i) { bytes memory _signature = _attestation[i * signatureLength:i * signatureLength + signatureLength]; address _recoveredAttester = _recoverAttesterSignature( _digest, _signature ); // Signatures must be in increasing order of address, and may not duplicate signatures from same address require( _recoveredAttester > _latestAttesterAddress, "Invalid signature order or dupe" ); require( isEnabledAttester(_recoveredAttester), "Invalid signature: not attester" ); _latestAttesterAddress = _recoveredAttester; } } /** * @notice Checks that signature was signed by attester * @param _digest message hash * @param _signature message signature * @return address of recovered signer **/ function _recoverAttesterSignature(bytes32 _digest, bytes memory _signature) internal pure returns (address) { return (ECDSA.recover(_digest, _signature)); } }
{ "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":"address","name":"_tokenMessenger","type":"address"},{"internalType":"address","name":"_attester","type":"address"},{"internalType":"address","name":"_feeCollector","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"attester","type":"address"}],"name":"AttesterDisabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"attester","type":"address"}],"name":"AttesterEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousAttesterManager","type":"address"},{"indexed":true,"internalType":"address","name":"newAttesterManager","type":"address"}],"name":"AttesterManagerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"destinationDomain","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"targetBridge","type":"bytes32"}],"name":"BindBridge","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32[]","name":"destinationDomains","type":"uint32[]"},{"indexed":false,"internalType":"bytes32[]","name":"targetBridges","type":"bytes32[]"}],"name":"BindBridgeBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BridgeIn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint32","name":"destinationDomain","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"nonce","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"recipient","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"callData","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"BridgeOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"DisableBridgeToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint32","name":"destinationDomain","type":"uint32"}],"name":"DisableRoute","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"EnableBridgeToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint32","name":"destinationDomain","type":"uint32"}],"name":"EnableRoute","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"callProxy","type":"address"}],"name":"SetCallProxy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeCollector","type":"address"}],"name":"SetFeeCollector","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"tokenMessenger","type":"address"}],"name":"SetTokenMessenger","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldSignatureThreshold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSignatureThreshold","type":"uint256"}],"name":"SignatureThresholdUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"attesterManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"destinationDomain","type":"uint32"},{"internalType":"bytes32","name":"targetBridge","type":"bytes32"}],"name":"bindBridge","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"destinationDomains","type":"uint32[]"},{"internalType":"bytes32[]","name":"targetBridgeHashes","type":"bytes32[]"}],"name":"bindBridgeBatch","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"bridgeHashMap","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"args","type":"bytes"},{"internalType":"bytes","name":"attestation","type":"bytes"}],"name":"bridgeIn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint32","name":"destinationDomain","type":"uint32"},{"internalType":"bytes32","name":"recipient","type":"bytes32"},{"internalType":"bytes","name":"callData","type":"bytes"}],"name":"bridgeOut","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"callProxy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"attester","type":"address"}],"name":"disableAttester","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"disableBridgeToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint32","name":"destinationDomain","type":"uint32"}],"name":"disableRoute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"disabledBridgeTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"disabledRoutes","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAttester","type":"address"}],"name":"enableAttester","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"enableBridgeToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint32","name":"destinationDomain","type":"uint32"}],"name":"enableRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"callee","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"externalCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBasefee","outputs":[{"internalType":"uint256","name":"basefee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getEnabledAttester","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMessageTransmitter","outputs":[{"internalType":"contract IReceiver","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumEnabledAttesters","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"attester","type":"address"}],"name":"isEnabledAttester","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"rescueFund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"rescueNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newCallProxy","type":"address"}],"name":"setCallProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFeeCollector","type":"address"}],"name":"setFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newSignatureThreshold","type":"uint256"}],"name":"setSignatureThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTokenMessenger","type":"address"}],"name":"setTokenMessenger","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signatureThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenMessenger","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAttesterManager","type":"address"}],"name":"updateAttesterManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060405162003e2038038062003e208339810160408190526200003491620003d4565b81620000403362000177565b600580546001600160a01b0319163317905560016002556200006281620001a1565b506005805460ff60a01b1916905560016006556001600160a01b038316620000df5760405162461bcd60e51b815260206004820152602560248201527f746f6b656e4d657373656e67657220616464726573732063616e6e6f74206265604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6001600160a01b038116620001435760405162461bcd60e51b815260206004820152602360248201527f666565436f6c6c6563746f7220616464726573732063616e6e6f74206265207a60448201526265726f60e81b6064820152608401620000d6565b600880546001600160a01b039485166001600160a01b0319918216179091556007805492909416911617909155506200041e565b600180546001600160a01b03191690556200019e81620002f5602090811b62001d6417901c565b50565b6005546001600160a01b03163314620001fd5760405162461bcd60e51b815260206004820152601b60248201527f43616c6c6572206e6f74206174746573746572206d616e6167657200000000006044820152606401620000d6565b6001600160a01b038116620002555760405162461bcd60e51b815260206004820152601c60248201527f4e6577206174746573746572206d757374206265206e6f6e7a65726f000000006044820152606401620000d6565b620002708160036200034560201b62001db41790919060201c565b620002be5760405162461bcd60e51b815260206004820152601860248201527f417474657374657220616c726561647920656e61626c656400000000000000006044820152606401620000d6565b6040516001600160a01b038216907f5b99bab45c72ce67e89466dbc47480b9c1fde1400e7268bbf463b8354ee4653f90600090a250565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006200035c836001600160a01b03841662000365565b90505b92915050565b6000818152600183016020526040812054620003ae575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200035f565b5060006200035f565b80516001600160a01b0381168114620003cf57600080fd5b919050565b600080600060608486031215620003ea57600080fd5b620003f584620003b7565b92506200040560208501620003b7565b91506200041560408501620003b7565b90509250925092565b6139f2806200042e6000396000f3fe6080604052600436106102295760003560e01c80638da5cb5b11610123578063c415b95c116100ab578063ea6f1f8a1161006f578063ea6f1f8a1461066b578063f2fde38b14610680578063f586384f146106a0578063f5d18139146106c0578063fae36879146106e057600080fd5b8063c415b95c146105b2578063c8df4230146105d2578063ccfdfb53146105f2578063de7769d41461062d578063e30c39781461064d57600080fd5b8063a42dce80116100f2578063a42dce801461051c578063a82f2e261461053c578063b8c6fd8414610552578063bbde537414610572578063beb673d81461059257600080fd5b80638da5cb5b1461049357806390b589f7146104b1578063974b3e92146104de5780639b0d94b7146104fe57600080fd5b806351079a53116101b15780637af82f60116101755780637af82f60146103fe5780637b6371961461041e5780638056508f1461043e5780638456cb591461045e5780638b82a7001461047357600080fd5b806351079a53146103595780635c975abb1461036e578063654c9bdb1461039957806371fbc36c146103b957806379ba5097146103e957600080fd5b806335b53a37116101f857806335b53a37146102d45780633e64a696146102e75780633f4ba83a146103045780634611783014610319578063504c97f51461033957600080fd5b80632b0d0a8b146102355780632d025080146102575780632da688ac146102775780632f898852146102b457600080fd5b3661023057005b600080fd5b34801561024157600080fd5b506102556102503660046132ab565b610700565b005b34801561026357600080fd5b506102556102723660046132ab565b610788565b34801561028357600080fd5b50600954610297906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102c057600080fd5b506102556102cf3660046132ab565b6108ee565b6102556102e2366004613323565b610992565b3480156102f357600080fd5b50485b6040519081526020016102ab565b34801561031057600080fd5b50610255610c95565b34801561032557600080fd5b50600854610297906001600160a01b031681565b34801561034557600080fd5b5061025561035436600461339d565b610cc9565b34801561036557600080fd5b506102f6610d89565b34801561037a57600080fd5b50600554600160a01b900460ff165b60405190151581526020016102ab565b3480156103a557600080fd5b506102556103b43660046133d2565b610d9a565b3480156103c557600080fd5b506103896103d43660046132ab565b600b6020526000908152604090205460ff1681565b3480156103f557600080fd5b50610255610e70565b34801561040a57600080fd5b506103896104193660046132ab565b610eea565b34801561042a57600080fd5b50610255610439366004613427565b610efd565b34801561044a57600080fd5b50610389610459366004613493565b61133d565b34801561046a57600080fd5b506102556113c2565b34801561047f57600080fd5b5061025561048e36600461339d565b6113f4565b34801561049f57600080fd5b506000546001600160a01b0316610297565b3480156104bd57600080fd5b506102f66104cc3660046134bd565b600a6020526000908152604090205481565b3480156104ea57600080fd5b506103896104f936600461351d565b6114af565b34801561050a57600080fd5b506005546001600160a01b0316610297565b34801561052857600080fd5b506102556105373660046132ab565b6115eb565b34801561054857600080fd5b506102f660025481565b34801561055e57600080fd5b5061025561056d3660046132ab565b6116c5565b34801561057e57600080fd5b5061025561058d36600461357d565b611771565b34801561059e57600080fd5b506102976105ad36600461357d565b6118d3565b3480156105be57600080fd5b50600754610297906001600160a01b031681565b3480156105de57600080fd5b506102556105ed3660046132ab565b6118e0565b3480156105fe57600080fd5b5061038961060d36600461339d565b600c60209081526000928352604080842090915290825290205460ff1681565b34801561063957600080fd5b506102556106483660046132ab565b611914565b34801561065957600080fd5b506001546001600160a01b0316610297565b34801561067757600080fd5b506102976119e6565b34801561068c57600080fd5b5061025561069b3660046132ab565b6119f0565b3480156106ac57600080fd5b506102556106bb3660046132ab565b611ad9565b3480156106cc57600080fd5b506102556106db3660046132ab565b611bb5565b3480156106ec57600080fd5b506102556106fb3660046132ab565b611c56565b6000546001600160a01b031633146107335760405162461bcd60e51b815260040161072a90613596565b60405180910390fd5b600980546001600160a01b0319166001600160a01b0383169081179091556040519081527ffc57056a17359d1eb9fbfc67fb83f4d68e63ce44051e9190ad4ab8e4fc8d2c45906020015b60405180910390a150565b6005546001600160a01b031633146107b25760405162461bcd60e51b815260040161072a906135cb565b60006107bc610d89565b90506001811161080e5760405162461bcd60e51b815260206004820152601960248201527f546f6f2066657720656e61626c65642061747465737465727300000000000000604482015260640161072a565b600254811161085f5760405162461bcd60e51b815260206004820152601e60248201527f5369676e6174757265207468726573686f6c6420697320746f6f206c6f770000604482015260640161072a565b61086a600383611dd0565b6108b65760405162461bcd60e51b815260206004820152601960248201527f417474657374657220616c72656164792064697361626c656400000000000000604482015260640161072a565b6040516001600160a01b038316907f78e573a18c75957b7cadaab01511aa1c19a659f06ecf53e01de37ed92d3261fc90600090a25050565b6000546001600160a01b031633146109185760405162461bcd60e51b815260040161072a90613596565b6001600160a01b03811661093e5760405162461bcd60e51b815260040161072a90613602565b6001600160a01b0381166000818152600b6020908152604091829020805460ff1916600117905590519182527f480364d6684f39277516e3764b4dc11bda0afb4d8e2a10b3b64aa599e1ad88ef910161077d565b61099a611de5565b6109a2611e3e565b63ffffffff84166000908152600a602052604090205480610a055760405162461bcd60e51b815260206004820152601960248201527f74617267657420627269646765206e6f7420656e61626c656400000000000000604482015260640161072a565b6009546001600160a01b03163303610a4b5760405162461bcd60e51b81526020600482015260096024820152683337b93134b23232b760b91b604482015260640161072a565b83610a985760405162461bcd60e51b815260206004820181905260248201527f726563697069656e7420616464726573732063616e6e6f74206265207a65726f604482015260640161072a565b6001600160a01b0387166000908152600b602052604090205460ff1615610af55760405162461bcd60e51b81526020600482015260116024820152701d1bdad95b881b9bdd08195b98589b1959607a1b604482015260640161072a565b6001600160a01b0387166000908152600c6020908152604080832063ffffffff8916845290915290205460ff1615610b605760405162461bcd60e51b815260206004820152600e60248201526d1c9bdd5d1948191a5cd8589b195960921b604482015260640161072a565b610b756001600160a01b038816333089611e8b565b600854610b8f906001600160a01b03898116911688611ef6565b600854604051637c2b6edb60e11b81526004810188905263ffffffff87166024820152604481018390526001600160a01b03898116606483015260848201849052600092169063f856ddb69060a4016020604051808303816000875af1158015610bfd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c219190613639565b600754909150610c3a906001600160a01b031634612010565b7fb7a75eb0e8d07789358b14c88b1d05913f210ad19e699c2a89865896393fa0b33389888a858a8a8a34604051610c7999989796959493929190613663565b60405180910390a15050610c8d6001600655565b505050505050565b6000546001600160a01b03163314610cbf5760405162461bcd60e51b815260040161072a90613596565b610cc76120cd565b565b6000546001600160a01b03163314610cf35760405162461bcd60e51b815260040161072a90613596565b6001600160a01b038216610d195760405162461bcd60e51b815260040161072a90613602565b6001600160a01b0382166000818152600c6020908152604080832063ffffffff861680855290835292819020805460ff191690558051938452908301919091527f9f330e8599d43d6b44d47465808950f2c7b2d641213d0a255f9a34ffffd88f2e91015b60405180910390a15050565b6000610d956003612122565b905090565b6000546001600160a01b03163314610dc45760405162461bcd60e51b815260040161072a90613596565b6000836001600160a01b03168383604051610de09291906136e4565b6000604051808303816000865af19150503d8060008114610e1d576040519150601f19603f3d011682016040523d82523d6000602084013e610e22565b606091505b5050905080610e6a5760405162461bcd60e51b8152602060048201526014602482015273195e1d195c9b985b0818d85b1b0819985a5b195960621b604482015260640161072a565b50505050565b60015433906001600160a01b03168114610ede5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161072a565b610ee78161212c565b50565b6000610ef7600383612145565b92915050565b610f05611de5565b610f0d611e3e565b82610f525760405162461bcd60e51b8152602060048201526015602482015274696e76616c696420627269646765496e206172677360581b604482015260640161072a565b610f5e84848484612167565b6000610f6a8585612338565b80516040516370a0823160e01b8152306004820152919250906000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdb91906136f4565b90506000610fe7612535565b6001600160a01b03166357ecfd28856020015186604001516040518363ffffffff1660e01b815260040161101c92919061375d565b6020604051808303816000875af115801561103b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105f919061378b565b9050806110a75760405162461bcd60e51b81526020600482015260166024820152751c9958d95a5d99481b595cdcd859d94819985a5b195960521b604482015260640161072a565b6040516370a0823160e01b815230600482015260009083906001600160a01b038616906370a0823190602401602060405180830381865afa1580156110f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111491906136f4565b61111e91906137c3565b9050600081116111685760405162461bcd60e51b8152602060048201526015602482015274616d6f756e742063616e6e6f74206265207a65726f60581b604482015260640161072a565b6000611175866060015190565b90506001600160a01b0381166111cd5760405162461bcd60e51b815260206004820181905260248201527f726563697069656e7420616464726573732063616e6e6f74206265207a65726f604482015260640161072a565b60808601515115806111e857506009546001600160a01b0316155b15611206576112016001600160a01b03861682846125a3565b6112dd565b600954611220906001600160a01b038781169116846125a3565b6009546080870151604051633973ef1360e11b81526001600160a01b03909216916372e7de269161125a91899187918791906004016137d6565b6020604051808303816000875af1158015611279573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129d919061378b565b6112dd5760405162461bcd60e51b81526020600482015260116024820152701c1c9bde1e4818d85b1b0819985a5b1959607a1b604482015260640161072a565b604080513381526001600160a01b0383811660208301528716818301526060810184905290517f9e092e01469c86728c7d519fc4fcb43156d472a63854770c4650fa938958c5db9181900360800190a1505050505050610e6a6001600655565b600080546001600160a01b031633146113685760405162461bcd60e51b815260040161072a90613596565b63ffffffff83166000818152600a6020908152604091829020859055815192835282018490527fdcdf86433da1e54eed0603b8a39d5e85a0d3b5dbbbdee7e9d72552a2b8c3dde5910160405180910390a150600192915050565b6000546001600160a01b031633146113ec5760405162461bcd60e51b815260040161072a90613596565b610cc76125d3565b6000546001600160a01b0316331461141e5760405162461bcd60e51b815260040161072a90613596565b6001600160a01b0382166114445760405162461bcd60e51b815260040161072a90613602565b6001600160a01b0382166000818152600c6020908152604080832063ffffffff861680855290835292819020805460ff191660011790558051938452908301919091527fd1c8e282c39ea4ab5b7e53108411033a3d2f97fdcae9b79e4081c2e695683f9f9101610d7d565b600080546001600160a01b031633146114da5760405162461bcd60e51b815260040161072a90613596565b8382146115295760405162461bcd60e51b815260206004820152601e60248201527f496e636f6e73697374656e7420706172616d65746572206c656e677468730000604482015260640161072a565b60005b848110156115a15783838281811061154657611546613813565b90506020020135600a600088888581811061156357611563613813565b905060200201602081019061157891906134bd565b63ffffffff1681526020810191909152604001600020558061159981613829565b91505061152c565b507fd69c8cbfd41b3cc8c0c978579a2ef51200632abe69d96291ae3ace885ed0d123858585856040516115d79493929190613842565b60405180910390a15060015b949350505050565b6000546001600160a01b031633146116155760405162461bcd60e51b815260040161072a90613596565b6001600160a01b0381166116775760405162461bcd60e51b815260206004820152602360248201527f666565436f6c6c6563746f7220616464726573732063616e6e6f74206265207a60448201526265726f60e81b606482015260840161072a565b600780546001600160a01b0319166001600160a01b0383169081179091556040519081527fd649da8f6092116f86ea4e5139de0b75ad371d823918d16368ba3ff09a5cbc9f9060200161077d565b6000546001600160a01b031633146116ef5760405162461bcd60e51b815260040161072a90613596565b8061176d336040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa158015611738573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061175c91906136f4565b6001600160a01b03841691906125a3565b5050565b6005546001600160a01b0316331461179b5760405162461bcd60e51b815260040161072a906135cb565b806000036117eb5760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964207369676e6174757265207468726573686f6c640000000000604482015260640161072a565b6117f56003612122565b8111156118445760405162461bcd60e51b815260206004820181905260248201527f4e6577207369676e6174757265207468726573686f6c6420746f6f2068696768604482015260640161072a565b60025481036118955760405162461bcd60e51b815260206004820152601f60248201527f5369676e6174757265207468726573686f6c6420616c72656164792073657400604482015260640161072a565b600280549082905560408051828152602081018490527f149153f58b4da003a8cfd4523709a202402182cb5aa335046911277a1be6eede9101610d7d565b6000610ef7600383612616565b6000546001600160a01b0316331461190a5760405162461bcd60e51b815260040161072a90613596565b610ee78147612010565b6000546001600160a01b0316331461193e5760405162461bcd60e51b815260040161072a90613596565b6001600160a01b0381166119945760405162461bcd60e51b815260206004820181905260248201527f496e76616c6964206174746573746572206d616e616765722061646472657373604482015260640161072a565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0cee1b7ae04f3c788dd3a46c6fa677eb95b913611ef7ab59524fdc09d346021990600090a35050565b6000610d95612535565b6000546001600160a01b03163314611a1a5760405162461bcd60e51b815260040161072a90613596565b6001600160a01b038116611a705760405162461bcd60e51b815260206004820181905260248201527f6e6577206f776e657220616464726573732063616e6e6f74206265207a65726f604482015260640161072a565b600180546001600160a01b0383166001600160a01b03199091168117909155611aa16000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000546001600160a01b03163314611b035760405162461bcd60e51b815260040161072a90613596565b6001600160a01b038116611b675760405162461bcd60e51b815260206004820152602560248201527f746f6b656e4d657373656e67657220616464726573732063616e6e6f74206265604482015264207a65726f60d81b606482015260840161072a565b600880546001600160a01b0319166001600160a01b0383169081179091556040519081527f488f5bf1a70a38a9375047ad150b98b716eb1ac057183acd79e1667bb601b7979060200161077d565b6000546001600160a01b03163314611bdf5760405162461bcd60e51b815260040161072a90613596565b6001600160a01b038116611c055760405162461bcd60e51b815260040161072a90613602565b6001600160a01b0381166000818152600b6020908152604091829020805460ff1916905590519182527fd4acc9512766117a8032c0db6285dff079dc98eb07f284ea1379a622cbb90344910161077d565b6005546001600160a01b03163314611c805760405162461bcd60e51b815260040161072a906135cb565b6001600160a01b038116611cd65760405162461bcd60e51b815260206004820152601c60248201527f4e6577206174746573746572206d757374206265206e6f6e7a65726f00000000604482015260640161072a565b611ce1600382611db4565b611d2d5760405162461bcd60e51b815260206004820152601860248201527f417474657374657220616c726561647920656e61626c65640000000000000000604482015260640161072a565b6040516001600160a01b038216907f5b99bab45c72ce67e89466dbc47480b9c1fde1400e7268bbf463b8354ee4653f90600090a250565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000611dc9836001600160a01b038416612622565b9392505050565b6000611dc9836001600160a01b038416612671565b600260065403611e375760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161072a565b6002600655565b600554600160a01b900460ff1615610cc75760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161072a565b6040516001600160a01b0380851660248301528316604482015260648101829052610e6a9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612764565b801580611f705750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611f4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f6e91906136f4565b155b611fdb5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606482015260840161072a565b6040516001600160a01b03831660248201526044810182905261200b90849063095ea7b360e01b90606401611ebf565b505050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461205d576040519150601f19603f3d011682016040523d82523d6000602084013e612062565b606091505b505090508061200b5760405162461bcd60e51b815260206004820152603160248201527f756e61626c6520746f2073656e642076616c75652c20726563697069656e74206044820152701b585e481a185d99481c995d995c9d1959607a1b606482015260840161072a565b6120d5612836565b6005805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6000610ef7825490565b600180546001600160a01b0319169055610ee781611d64565b6001600160a01b03811660009081526001830160205260408120541515611dc9565b6002546121759060416138bb565b81146121c35760405162461bcd60e51b815260206004820152601a60248201527f496e76616c6964206174746573746174696f6e206c656e677468000000000000604482015260640161072a565b60008085856040516121d69291906136e4565b6040518091039020905060005b60025481101561232f57600085856121fc6041856138bb565b90604161220981876138bb565b61221391906138d2565b92612220939291906138e5565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509394506122639250869150849050612886565b9050846001600160a01b0316816001600160a01b0316116122c65760405162461bcd60e51b815260206004820152601f60248201527f496e76616c6964207369676e6174757265206f72646572206f72206475706500604482015260640161072a565b6122cf81610eea565b61231b5760405162461bcd60e51b815260206004820152601f60248201527f496e76616c6964207369676e61747572653a206e6f7420617474657374657200604482015260640161072a565b9350612328905081613829565b90506121e3565b50505050505050565b6040805160a08101825260008082526060602083018190529282018390528282015260808101919091526040805160a0810182526000808252606060208301819052928201839052828201526080810191909152600060606123d186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250869250612892915050565b925090506123de816129a1565b6001600160a01b03168352604080516020601f8801819004810282018101909252868152612428918890889081908401838280828437600092019190915250869250612892915050565b84602001819450829052505061247586868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250869250612892915050565b84604001819450829052505060606124c487878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250879250612892915050565b935090506124e06124d4826129a1565b6001600160a01b031690565b6060850152604080516020601f8901819004810282018101909252878152612524918990899081908401838280828437600092019190915250879250612892915050565b506080850152509195945050505050565b60085460408051632c12192160e01b815290516000926001600160a01b031691632c1219219160048083019260209291908290030181865afa15801561257f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d95919061390f565b6040516001600160a01b03831660248201526044810182905261200b90849063a9059cbb60e01b90606401611ebf565b6125db611e3e565b6005805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586121053390565b6000611dc98383612a08565b600081815260018301602052604081205461266957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610ef7565b506000610ef7565b6000818152600183016020526040812054801561275a5760006126956001836137c3565b85549091506000906126a9906001906137c3565b905081811461270e5760008660000182815481106126c9576126c9613813565b90600052602060002001549050808760000184815481106126ec576126ec613813565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061271f5761271f61392c565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610ef7565b6000915050610ef7565b60006127b9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612a329092919063ffffffff16565b80519091501561200b57808060200190518101906127d7919061378b565b61200b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161072a565b600554600160a01b900460ff16610cc75760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161072a565b6000611dc98383612a41565b60606000806128a18585612a65565b86519095509091506128b382866138d2565b111580156128ca57506128c681856138d2565b8411155b6129225760405162461bcd60e51b8152602060048201526024808201527f4e65787456617242797465732c206f66667365742065786365656473206d6178604482015263696d756d60e01b606482015260840161072a565b60608115801561293d57604051915060208201604052612987565b6040519150601f8316801560200281840101848101888315602002848c0101015b8183101561297657805183526020928301920161295e565b5050848452601f01601f1916604052505b508061299383876138d2565b9350935050505b9250929050565b60008151601414612a005760405162461bcd60e51b815260206004820152602360248201527f6279746573206c656e67746820646f6573206e6f74206d61746368206164647260448201526265737360e81b606482015260840161072a565b506014015190565b6000826000018281548110612a1f57612a1f613813565b9060005260206000200154905092915050565b60606115e38484600085612bd9565b6000806000612a508585612cb4565b91509150612a5d81612cf6565b509392505050565b6000806000612a748585612e40565b9450905060006001600160f81b0319821660fd60f81b03612b0c57612a998686612ed4565b955061ffff16905060fd8110801590612ab4575061ffff8111155b612b005760405162461bcd60e51b815260206004820152601f60248201527f4e65787455696e7431362c2076616c7565206f7574736964652072616e676500604482015260640161072a565b925083915061299a9050565b6001600160f81b03198216607f60f91b03612b6657612b2b8686612f8d565b955063ffffffff16905061ffff81118015612b4a575063ffffffff8111155b612b005760405162461bcd60e51b815260040161072a90613942565b6001600160f81b03198083169003612bb357612b82868661305e565b955067ffffffffffffffff16905063ffffffff8111612b005760405162461bcd60e51b815260040161072a90613942565b5060f881901c60fd8110612b005760405162461bcd60e51b815260040161072a90613942565b606082471015612c3a5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161072a565b600080866001600160a01b03168587604051612c569190613977565b60006040518083038185875af1925050503d8060008114612c93576040519150601f19603f3d011682016040523d82523d6000602084013e612c98565b606091505b5091509150612ca98783838761312f565b979650505050505050565b6000808251604103612cea5760208301516040840151606085015160001a612cde878285856131a8565b9450945050505061299a565b5060009050600261299a565b6000816004811115612d0a57612d0a613993565b03612d125750565b6001816004811115612d2657612d26613993565b03612d735760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161072a565b6002816004811115612d8757612d87613993565b03612dd45760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161072a565b6003816004811115612de857612de8613993565b03610ee75760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161072a565b6000808351836001612e5291906138d2565b11158015612e695750612e668360016138d2565b83105b612eb55760405162461bcd60e51b815260206004820181905260248201527f4e657874427974652c204f66667365742065786365656473206d6178696d756d604482015260640161072a565b8383016020015180612ec88560016138d2565b92509250509250929050565b6000808351836002612ee691906138d2565b11158015612efd5750612efa8360026138d2565b83105b612f545760405162461bcd60e51b815260206004820152602260248201527f4e65787455696e7431362c206f66667365742065786365656473206d6178696d604482015261756d60f01b606482015260840161072a565b6000604051846020870101518060011a82538060001a60018301535060028101604052601e81035191505080846002612ec891906138d2565b6000808351836004612f9f91906138d2565b11158015612fb65750612fb38360046138d2565b83105b61300d5760405162461bcd60e51b815260206004820152602260248201527f4e65787455696e7433322c206f66667365742065786365656473206d6178696d604482015261756d60f01b606482015260840161072a565b600060405160046000600182038760208a0101515b838310156130425780821a83860153600183019250600182039150613022565b505050016040819052601f190151905080612ec88560046138d2565b600080835183600861307091906138d2565b1115801561308757506130848360086138d2565b83105b6130de5760405162461bcd60e51b815260206004820152602260248201527f4e65787455696e7436342c206f66667365742065786365656473206d6178696d604482015261756d60f01b606482015260840161072a565b600060405160086000600182038760208a0101515b838310156131135780821a838601536001830192506001820391506130f3565b505050016040819052601f190151905080612ec88560086138d2565b6060831561319e578251600003613197576001600160a01b0385163b6131975760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161072a565b50816115e3565b6115e3838361326c565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156131df5750600090506003613263565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015613233573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661325c57600060019250925050613263565b9150600090505b94509492505050565b81511561327c5781518083602001fd5b8060405162461bcd60e51b815260040161072a91906139a9565b6001600160a01b0381168114610ee757600080fd5b6000602082840312156132bd57600080fd5b8135611dc981613296565b803563ffffffff811681146132dc57600080fd5b919050565b60008083601f8401126132f357600080fd5b50813567ffffffffffffffff81111561330b57600080fd5b60208301915083602082850101111561299a57600080fd5b60008060008060008060a0878903121561333c57600080fd5b863561334781613296565b95506020870135945061335c604088016132c8565b935060608701359250608087013567ffffffffffffffff81111561337f57600080fd5b61338b89828a016132e1565b979a9699509497509295939492505050565b600080604083850312156133b057600080fd5b82356133bb81613296565b91506133c9602084016132c8565b90509250929050565b6000806000604084860312156133e757600080fd5b83356133f281613296565b9250602084013567ffffffffffffffff81111561340e57600080fd5b61341a868287016132e1565b9497909650939450505050565b6000806000806040858703121561343d57600080fd5b843567ffffffffffffffff8082111561345557600080fd5b613461888389016132e1565b9096509450602087013591508082111561347a57600080fd5b50613487878288016132e1565b95989497509550505050565b600080604083850312156134a657600080fd5b6134af836132c8565b946020939093013593505050565b6000602082840312156134cf57600080fd5b611dc9826132c8565b60008083601f8401126134ea57600080fd5b50813567ffffffffffffffff81111561350257600080fd5b6020830191508360208260051b850101111561299a57600080fd5b6000806000806040858703121561353357600080fd5b843567ffffffffffffffff8082111561354b57600080fd5b613557888389016134d8565b9096509450602087013591508082111561357057600080fd5b50613487878288016134d8565b60006020828403121561358f57600080fd5b5035919050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601b908201527f43616c6c6572206e6f74206174746573746572206d616e616765720000000000604082015260600190565b6020808252601c908201527f746f6b656e20616464726573732063616e6e6f74206265207a65726f00000000604082015260600190565b60006020828403121561364b57600080fd5b815167ffffffffffffffff81168114611dc957600080fd5b6001600160a01b038a811682528916602082015263ffffffff881660408201526060810187905267ffffffffffffffff8616608082015260a0810185905261010060c0820181905281018390526000610120848682850137600083860182015260e083019390935250601f909201601f191690910101979650505050505050565b8183823760009101908152919050565b60006020828403121561370657600080fd5b5051919050565b60005b83811015613728578181015183820152602001613710565b50506000910152565b6000815180845261374981602086016020860161370d565b601f01601f19169290920160200192915050565b6040815260006137706040830185613731565b82810360208401526137828185613731565b95945050505050565b60006020828403121561379d57600080fd5b81518015158114611dc957600080fd5b634e487b7160e01b600052601160045260246000fd5b81810381811115610ef757610ef76137ad565b6001600160a01b038581168252602082018590528316604082015260806060820181905260009061380990830184613731565b9695505050505050565b634e487b7160e01b600052603260045260246000fd5b60006001820161383b5761383b6137ad565b5060010190565b6040808252810184905260008560608301825b878110156138805763ffffffff61386b846132c8565b16825260209283019290910190600101613855565b5083810360208501528481526001600160fb1b038511156138a057600080fd5b8460051b915081866020830137016020019695505050505050565b8082028115828204841417610ef757610ef76137ad565b80820180821115610ef757610ef76137ad565b600080858511156138f557600080fd5b8386111561390257600080fd5b5050820193919092039150565b60006020828403121561392157600080fd5b8151611dc981613296565b634e487b7160e01b600052603160045260246000fd5b6020808252818101527f4e65787456617255696e742c2076616c7565206f7574736964652072616e6765604082015260600190565b6000825161398981846020870161370d565b9190910192915050565b634e487b7160e01b600052602160045260246000fd5b602081526000611dc9602083018461373156fea2646970667358221220592f65a6057e732a10e0c910599ad06f8808589723472c56f994ee99e1c023f464736f6c63430008110033000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af315500000000000000000000000001e2fffebe57c9f8b82c22cf15dec28de2e56ee4000000000000000000000000a81dc97fc2f5df4c1dc39cd9dc20ec778ee31700
Deployed Bytecode
0x6080604052600436106102295760003560e01c80638da5cb5b11610123578063c415b95c116100ab578063ea6f1f8a1161006f578063ea6f1f8a1461066b578063f2fde38b14610680578063f586384f146106a0578063f5d18139146106c0578063fae36879146106e057600080fd5b8063c415b95c146105b2578063c8df4230146105d2578063ccfdfb53146105f2578063de7769d41461062d578063e30c39781461064d57600080fd5b8063a42dce80116100f2578063a42dce801461051c578063a82f2e261461053c578063b8c6fd8414610552578063bbde537414610572578063beb673d81461059257600080fd5b80638da5cb5b1461049357806390b589f7146104b1578063974b3e92146104de5780639b0d94b7146104fe57600080fd5b806351079a53116101b15780637af82f60116101755780637af82f60146103fe5780637b6371961461041e5780638056508f1461043e5780638456cb591461045e5780638b82a7001461047357600080fd5b806351079a53146103595780635c975abb1461036e578063654c9bdb1461039957806371fbc36c146103b957806379ba5097146103e957600080fd5b806335b53a37116101f857806335b53a37146102d45780633e64a696146102e75780633f4ba83a146103045780634611783014610319578063504c97f51461033957600080fd5b80632b0d0a8b146102355780632d025080146102575780632da688ac146102775780632f898852146102b457600080fd5b3661023057005b600080fd5b34801561024157600080fd5b506102556102503660046132ab565b610700565b005b34801561026357600080fd5b506102556102723660046132ab565b610788565b34801561028357600080fd5b50600954610297906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102c057600080fd5b506102556102cf3660046132ab565b6108ee565b6102556102e2366004613323565b610992565b3480156102f357600080fd5b50485b6040519081526020016102ab565b34801561031057600080fd5b50610255610c95565b34801561032557600080fd5b50600854610297906001600160a01b031681565b34801561034557600080fd5b5061025561035436600461339d565b610cc9565b34801561036557600080fd5b506102f6610d89565b34801561037a57600080fd5b50600554600160a01b900460ff165b60405190151581526020016102ab565b3480156103a557600080fd5b506102556103b43660046133d2565b610d9a565b3480156103c557600080fd5b506103896103d43660046132ab565b600b6020526000908152604090205460ff1681565b3480156103f557600080fd5b50610255610e70565b34801561040a57600080fd5b506103896104193660046132ab565b610eea565b34801561042a57600080fd5b50610255610439366004613427565b610efd565b34801561044a57600080fd5b50610389610459366004613493565b61133d565b34801561046a57600080fd5b506102556113c2565b34801561047f57600080fd5b5061025561048e36600461339d565b6113f4565b34801561049f57600080fd5b506000546001600160a01b0316610297565b3480156104bd57600080fd5b506102f66104cc3660046134bd565b600a6020526000908152604090205481565b3480156104ea57600080fd5b506103896104f936600461351d565b6114af565b34801561050a57600080fd5b506005546001600160a01b0316610297565b34801561052857600080fd5b506102556105373660046132ab565b6115eb565b34801561054857600080fd5b506102f660025481565b34801561055e57600080fd5b5061025561056d3660046132ab565b6116c5565b34801561057e57600080fd5b5061025561058d36600461357d565b611771565b34801561059e57600080fd5b506102976105ad36600461357d565b6118d3565b3480156105be57600080fd5b50600754610297906001600160a01b031681565b3480156105de57600080fd5b506102556105ed3660046132ab565b6118e0565b3480156105fe57600080fd5b5061038961060d36600461339d565b600c60209081526000928352604080842090915290825290205460ff1681565b34801561063957600080fd5b506102556106483660046132ab565b611914565b34801561065957600080fd5b506001546001600160a01b0316610297565b34801561067757600080fd5b506102976119e6565b34801561068c57600080fd5b5061025561069b3660046132ab565b6119f0565b3480156106ac57600080fd5b506102556106bb3660046132ab565b611ad9565b3480156106cc57600080fd5b506102556106db3660046132ab565b611bb5565b3480156106ec57600080fd5b506102556106fb3660046132ab565b611c56565b6000546001600160a01b031633146107335760405162461bcd60e51b815260040161072a90613596565b60405180910390fd5b600980546001600160a01b0319166001600160a01b0383169081179091556040519081527ffc57056a17359d1eb9fbfc67fb83f4d68e63ce44051e9190ad4ab8e4fc8d2c45906020015b60405180910390a150565b6005546001600160a01b031633146107b25760405162461bcd60e51b815260040161072a906135cb565b60006107bc610d89565b90506001811161080e5760405162461bcd60e51b815260206004820152601960248201527f546f6f2066657720656e61626c65642061747465737465727300000000000000604482015260640161072a565b600254811161085f5760405162461bcd60e51b815260206004820152601e60248201527f5369676e6174757265207468726573686f6c6420697320746f6f206c6f770000604482015260640161072a565b61086a600383611dd0565b6108b65760405162461bcd60e51b815260206004820152601960248201527f417474657374657220616c72656164792064697361626c656400000000000000604482015260640161072a565b6040516001600160a01b038316907f78e573a18c75957b7cadaab01511aa1c19a659f06ecf53e01de37ed92d3261fc90600090a25050565b6000546001600160a01b031633146109185760405162461bcd60e51b815260040161072a90613596565b6001600160a01b03811661093e5760405162461bcd60e51b815260040161072a90613602565b6001600160a01b0381166000818152600b6020908152604091829020805460ff1916600117905590519182527f480364d6684f39277516e3764b4dc11bda0afb4d8e2a10b3b64aa599e1ad88ef910161077d565b61099a611de5565b6109a2611e3e565b63ffffffff84166000908152600a602052604090205480610a055760405162461bcd60e51b815260206004820152601960248201527f74617267657420627269646765206e6f7420656e61626c656400000000000000604482015260640161072a565b6009546001600160a01b03163303610a4b5760405162461bcd60e51b81526020600482015260096024820152683337b93134b23232b760b91b604482015260640161072a565b83610a985760405162461bcd60e51b815260206004820181905260248201527f726563697069656e7420616464726573732063616e6e6f74206265207a65726f604482015260640161072a565b6001600160a01b0387166000908152600b602052604090205460ff1615610af55760405162461bcd60e51b81526020600482015260116024820152701d1bdad95b881b9bdd08195b98589b1959607a1b604482015260640161072a565b6001600160a01b0387166000908152600c6020908152604080832063ffffffff8916845290915290205460ff1615610b605760405162461bcd60e51b815260206004820152600e60248201526d1c9bdd5d1948191a5cd8589b195960921b604482015260640161072a565b610b756001600160a01b038816333089611e8b565b600854610b8f906001600160a01b03898116911688611ef6565b600854604051637c2b6edb60e11b81526004810188905263ffffffff87166024820152604481018390526001600160a01b03898116606483015260848201849052600092169063f856ddb69060a4016020604051808303816000875af1158015610bfd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c219190613639565b600754909150610c3a906001600160a01b031634612010565b7fb7a75eb0e8d07789358b14c88b1d05913f210ad19e699c2a89865896393fa0b33389888a858a8a8a34604051610c7999989796959493929190613663565b60405180910390a15050610c8d6001600655565b505050505050565b6000546001600160a01b03163314610cbf5760405162461bcd60e51b815260040161072a90613596565b610cc76120cd565b565b6000546001600160a01b03163314610cf35760405162461bcd60e51b815260040161072a90613596565b6001600160a01b038216610d195760405162461bcd60e51b815260040161072a90613602565b6001600160a01b0382166000818152600c6020908152604080832063ffffffff861680855290835292819020805460ff191690558051938452908301919091527f9f330e8599d43d6b44d47465808950f2c7b2d641213d0a255f9a34ffffd88f2e91015b60405180910390a15050565b6000610d956003612122565b905090565b6000546001600160a01b03163314610dc45760405162461bcd60e51b815260040161072a90613596565b6000836001600160a01b03168383604051610de09291906136e4565b6000604051808303816000865af19150503d8060008114610e1d576040519150601f19603f3d011682016040523d82523d6000602084013e610e22565b606091505b5050905080610e6a5760405162461bcd60e51b8152602060048201526014602482015273195e1d195c9b985b0818d85b1b0819985a5b195960621b604482015260640161072a565b50505050565b60015433906001600160a01b03168114610ede5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161072a565b610ee78161212c565b50565b6000610ef7600383612145565b92915050565b610f05611de5565b610f0d611e3e565b82610f525760405162461bcd60e51b8152602060048201526015602482015274696e76616c696420627269646765496e206172677360581b604482015260640161072a565b610f5e84848484612167565b6000610f6a8585612338565b80516040516370a0823160e01b8152306004820152919250906000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdb91906136f4565b90506000610fe7612535565b6001600160a01b03166357ecfd28856020015186604001516040518363ffffffff1660e01b815260040161101c92919061375d565b6020604051808303816000875af115801561103b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105f919061378b565b9050806110a75760405162461bcd60e51b81526020600482015260166024820152751c9958d95a5d99481b595cdcd859d94819985a5b195960521b604482015260640161072a565b6040516370a0823160e01b815230600482015260009083906001600160a01b038616906370a0823190602401602060405180830381865afa1580156110f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111491906136f4565b61111e91906137c3565b9050600081116111685760405162461bcd60e51b8152602060048201526015602482015274616d6f756e742063616e6e6f74206265207a65726f60581b604482015260640161072a565b6000611175866060015190565b90506001600160a01b0381166111cd5760405162461bcd60e51b815260206004820181905260248201527f726563697069656e7420616464726573732063616e6e6f74206265207a65726f604482015260640161072a565b60808601515115806111e857506009546001600160a01b0316155b15611206576112016001600160a01b03861682846125a3565b6112dd565b600954611220906001600160a01b038781169116846125a3565b6009546080870151604051633973ef1360e11b81526001600160a01b03909216916372e7de269161125a91899187918791906004016137d6565b6020604051808303816000875af1158015611279573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129d919061378b565b6112dd5760405162461bcd60e51b81526020600482015260116024820152701c1c9bde1e4818d85b1b0819985a5b1959607a1b604482015260640161072a565b604080513381526001600160a01b0383811660208301528716818301526060810184905290517f9e092e01469c86728c7d519fc4fcb43156d472a63854770c4650fa938958c5db9181900360800190a1505050505050610e6a6001600655565b600080546001600160a01b031633146113685760405162461bcd60e51b815260040161072a90613596565b63ffffffff83166000818152600a6020908152604091829020859055815192835282018490527fdcdf86433da1e54eed0603b8a39d5e85a0d3b5dbbbdee7e9d72552a2b8c3dde5910160405180910390a150600192915050565b6000546001600160a01b031633146113ec5760405162461bcd60e51b815260040161072a90613596565b610cc76125d3565b6000546001600160a01b0316331461141e5760405162461bcd60e51b815260040161072a90613596565b6001600160a01b0382166114445760405162461bcd60e51b815260040161072a90613602565b6001600160a01b0382166000818152600c6020908152604080832063ffffffff861680855290835292819020805460ff191660011790558051938452908301919091527fd1c8e282c39ea4ab5b7e53108411033a3d2f97fdcae9b79e4081c2e695683f9f9101610d7d565b600080546001600160a01b031633146114da5760405162461bcd60e51b815260040161072a90613596565b8382146115295760405162461bcd60e51b815260206004820152601e60248201527f496e636f6e73697374656e7420706172616d65746572206c656e677468730000604482015260640161072a565b60005b848110156115a15783838281811061154657611546613813565b90506020020135600a600088888581811061156357611563613813565b905060200201602081019061157891906134bd565b63ffffffff1681526020810191909152604001600020558061159981613829565b91505061152c565b507fd69c8cbfd41b3cc8c0c978579a2ef51200632abe69d96291ae3ace885ed0d123858585856040516115d79493929190613842565b60405180910390a15060015b949350505050565b6000546001600160a01b031633146116155760405162461bcd60e51b815260040161072a90613596565b6001600160a01b0381166116775760405162461bcd60e51b815260206004820152602360248201527f666565436f6c6c6563746f7220616464726573732063616e6e6f74206265207a60448201526265726f60e81b606482015260840161072a565b600780546001600160a01b0319166001600160a01b0383169081179091556040519081527fd649da8f6092116f86ea4e5139de0b75ad371d823918d16368ba3ff09a5cbc9f9060200161077d565b6000546001600160a01b031633146116ef5760405162461bcd60e51b815260040161072a90613596565b8061176d336040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa158015611738573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061175c91906136f4565b6001600160a01b03841691906125a3565b5050565b6005546001600160a01b0316331461179b5760405162461bcd60e51b815260040161072a906135cb565b806000036117eb5760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964207369676e6174757265207468726573686f6c640000000000604482015260640161072a565b6117f56003612122565b8111156118445760405162461bcd60e51b815260206004820181905260248201527f4e6577207369676e6174757265207468726573686f6c6420746f6f2068696768604482015260640161072a565b60025481036118955760405162461bcd60e51b815260206004820152601f60248201527f5369676e6174757265207468726573686f6c6420616c72656164792073657400604482015260640161072a565b600280549082905560408051828152602081018490527f149153f58b4da003a8cfd4523709a202402182cb5aa335046911277a1be6eede9101610d7d565b6000610ef7600383612616565b6000546001600160a01b0316331461190a5760405162461bcd60e51b815260040161072a90613596565b610ee78147612010565b6000546001600160a01b0316331461193e5760405162461bcd60e51b815260040161072a90613596565b6001600160a01b0381166119945760405162461bcd60e51b815260206004820181905260248201527f496e76616c6964206174746573746572206d616e616765722061646472657373604482015260640161072a565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f0cee1b7ae04f3c788dd3a46c6fa677eb95b913611ef7ab59524fdc09d346021990600090a35050565b6000610d95612535565b6000546001600160a01b03163314611a1a5760405162461bcd60e51b815260040161072a90613596565b6001600160a01b038116611a705760405162461bcd60e51b815260206004820181905260248201527f6e6577206f776e657220616464726573732063616e6e6f74206265207a65726f604482015260640161072a565b600180546001600160a01b0383166001600160a01b03199091168117909155611aa16000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000546001600160a01b03163314611b035760405162461bcd60e51b815260040161072a90613596565b6001600160a01b038116611b675760405162461bcd60e51b815260206004820152602560248201527f746f6b656e4d657373656e67657220616464726573732063616e6e6f74206265604482015264207a65726f60d81b606482015260840161072a565b600880546001600160a01b0319166001600160a01b0383169081179091556040519081527f488f5bf1a70a38a9375047ad150b98b716eb1ac057183acd79e1667bb601b7979060200161077d565b6000546001600160a01b03163314611bdf5760405162461bcd60e51b815260040161072a90613596565b6001600160a01b038116611c055760405162461bcd60e51b815260040161072a90613602565b6001600160a01b0381166000818152600b6020908152604091829020805460ff1916905590519182527fd4acc9512766117a8032c0db6285dff079dc98eb07f284ea1379a622cbb90344910161077d565b6005546001600160a01b03163314611c805760405162461bcd60e51b815260040161072a906135cb565b6001600160a01b038116611cd65760405162461bcd60e51b815260206004820152601c60248201527f4e6577206174746573746572206d757374206265206e6f6e7a65726f00000000604482015260640161072a565b611ce1600382611db4565b611d2d5760405162461bcd60e51b815260206004820152601860248201527f417474657374657220616c726561647920656e61626c65640000000000000000604482015260640161072a565b6040516001600160a01b038216907f5b99bab45c72ce67e89466dbc47480b9c1fde1400e7268bbf463b8354ee4653f90600090a250565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000611dc9836001600160a01b038416612622565b9392505050565b6000611dc9836001600160a01b038416612671565b600260065403611e375760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161072a565b6002600655565b600554600160a01b900460ff1615610cc75760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161072a565b6040516001600160a01b0380851660248301528316604482015260648101829052610e6a9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612764565b801580611f705750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611f4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f6e91906136f4565b155b611fdb5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606482015260840161072a565b6040516001600160a01b03831660248201526044810182905261200b90849063095ea7b360e01b90606401611ebf565b505050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461205d576040519150601f19603f3d011682016040523d82523d6000602084013e612062565b606091505b505090508061200b5760405162461bcd60e51b815260206004820152603160248201527f756e61626c6520746f2073656e642076616c75652c20726563697069656e74206044820152701b585e481a185d99481c995d995c9d1959607a1b606482015260840161072a565b6120d5612836565b6005805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6000610ef7825490565b600180546001600160a01b0319169055610ee781611d64565b6001600160a01b03811660009081526001830160205260408120541515611dc9565b6002546121759060416138bb565b81146121c35760405162461bcd60e51b815260206004820152601a60248201527f496e76616c6964206174746573746174696f6e206c656e677468000000000000604482015260640161072a565b60008085856040516121d69291906136e4565b6040518091039020905060005b60025481101561232f57600085856121fc6041856138bb565b90604161220981876138bb565b61221391906138d2565b92612220939291906138e5565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509394506122639250869150849050612886565b9050846001600160a01b0316816001600160a01b0316116122c65760405162461bcd60e51b815260206004820152601f60248201527f496e76616c6964207369676e6174757265206f72646572206f72206475706500604482015260640161072a565b6122cf81610eea565b61231b5760405162461bcd60e51b815260206004820152601f60248201527f496e76616c6964207369676e61747572653a206e6f7420617474657374657200604482015260640161072a565b9350612328905081613829565b90506121e3565b50505050505050565b6040805160a08101825260008082526060602083018190529282018390528282015260808101919091526040805160a0810182526000808252606060208301819052928201839052828201526080810191909152600060606123d186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250869250612892915050565b925090506123de816129a1565b6001600160a01b03168352604080516020601f8801819004810282018101909252868152612428918890889081908401838280828437600092019190915250869250612892915050565b84602001819450829052505061247586868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250869250612892915050565b84604001819450829052505060606124c487878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250879250612892915050565b935090506124e06124d4826129a1565b6001600160a01b031690565b6060850152604080516020601f8901819004810282018101909252878152612524918990899081908401838280828437600092019190915250879250612892915050565b506080850152509195945050505050565b60085460408051632c12192160e01b815290516000926001600160a01b031691632c1219219160048083019260209291908290030181865afa15801561257f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d95919061390f565b6040516001600160a01b03831660248201526044810182905261200b90849063a9059cbb60e01b90606401611ebf565b6125db611e3e565b6005805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586121053390565b6000611dc98383612a08565b600081815260018301602052604081205461266957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610ef7565b506000610ef7565b6000818152600183016020526040812054801561275a5760006126956001836137c3565b85549091506000906126a9906001906137c3565b905081811461270e5760008660000182815481106126c9576126c9613813565b90600052602060002001549050808760000184815481106126ec576126ec613813565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061271f5761271f61392c565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610ef7565b6000915050610ef7565b60006127b9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612a329092919063ffffffff16565b80519091501561200b57808060200190518101906127d7919061378b565b61200b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161072a565b600554600160a01b900460ff16610cc75760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161072a565b6000611dc98383612a41565b60606000806128a18585612a65565b86519095509091506128b382866138d2565b111580156128ca57506128c681856138d2565b8411155b6129225760405162461bcd60e51b8152602060048201526024808201527f4e65787456617242797465732c206f66667365742065786365656473206d6178604482015263696d756d60e01b606482015260840161072a565b60608115801561293d57604051915060208201604052612987565b6040519150601f8316801560200281840101848101888315602002848c0101015b8183101561297657805183526020928301920161295e565b5050848452601f01601f1916604052505b508061299383876138d2565b9350935050505b9250929050565b60008151601414612a005760405162461bcd60e51b815260206004820152602360248201527f6279746573206c656e67746820646f6573206e6f74206d61746368206164647260448201526265737360e81b606482015260840161072a565b506014015190565b6000826000018281548110612a1f57612a1f613813565b9060005260206000200154905092915050565b60606115e38484600085612bd9565b6000806000612a508585612cb4565b91509150612a5d81612cf6565b509392505050565b6000806000612a748585612e40565b9450905060006001600160f81b0319821660fd60f81b03612b0c57612a998686612ed4565b955061ffff16905060fd8110801590612ab4575061ffff8111155b612b005760405162461bcd60e51b815260206004820152601f60248201527f4e65787455696e7431362c2076616c7565206f7574736964652072616e676500604482015260640161072a565b925083915061299a9050565b6001600160f81b03198216607f60f91b03612b6657612b2b8686612f8d565b955063ffffffff16905061ffff81118015612b4a575063ffffffff8111155b612b005760405162461bcd60e51b815260040161072a90613942565b6001600160f81b03198083169003612bb357612b82868661305e565b955067ffffffffffffffff16905063ffffffff8111612b005760405162461bcd60e51b815260040161072a90613942565b5060f881901c60fd8110612b005760405162461bcd60e51b815260040161072a90613942565b606082471015612c3a5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161072a565b600080866001600160a01b03168587604051612c569190613977565b60006040518083038185875af1925050503d8060008114612c93576040519150601f19603f3d011682016040523d82523d6000602084013e612c98565b606091505b5091509150612ca98783838761312f565b979650505050505050565b6000808251604103612cea5760208301516040840151606085015160001a612cde878285856131a8565b9450945050505061299a565b5060009050600261299a565b6000816004811115612d0a57612d0a613993565b03612d125750565b6001816004811115612d2657612d26613993565b03612d735760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161072a565b6002816004811115612d8757612d87613993565b03612dd45760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161072a565b6003816004811115612de857612de8613993565b03610ee75760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161072a565b6000808351836001612e5291906138d2565b11158015612e695750612e668360016138d2565b83105b612eb55760405162461bcd60e51b815260206004820181905260248201527f4e657874427974652c204f66667365742065786365656473206d6178696d756d604482015260640161072a565b8383016020015180612ec88560016138d2565b92509250509250929050565b6000808351836002612ee691906138d2565b11158015612efd5750612efa8360026138d2565b83105b612f545760405162461bcd60e51b815260206004820152602260248201527f4e65787455696e7431362c206f66667365742065786365656473206d6178696d604482015261756d60f01b606482015260840161072a565b6000604051846020870101518060011a82538060001a60018301535060028101604052601e81035191505080846002612ec891906138d2565b6000808351836004612f9f91906138d2565b11158015612fb65750612fb38360046138d2565b83105b61300d5760405162461bcd60e51b815260206004820152602260248201527f4e65787455696e7433322c206f66667365742065786365656473206d6178696d604482015261756d60f01b606482015260840161072a565b600060405160046000600182038760208a0101515b838310156130425780821a83860153600183019250600182039150613022565b505050016040819052601f190151905080612ec88560046138d2565b600080835183600861307091906138d2565b1115801561308757506130848360086138d2565b83105b6130de5760405162461bcd60e51b815260206004820152602260248201527f4e65787455696e7436342c206f66667365742065786365656473206d6178696d604482015261756d60f01b606482015260840161072a565b600060405160086000600182038760208a0101515b838310156131135780821a838601536001830192506001820391506130f3565b505050016040819052601f190151905080612ec88560086138d2565b6060831561319e578251600003613197576001600160a01b0385163b6131975760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161072a565b50816115e3565b6115e3838361326c565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156131df5750600090506003613263565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015613233573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661325c57600060019250925050613263565b9150600090505b94509492505050565b81511561327c5781518083602001fd5b8060405162461bcd60e51b815260040161072a91906139a9565b6001600160a01b0381168114610ee757600080fd5b6000602082840312156132bd57600080fd5b8135611dc981613296565b803563ffffffff811681146132dc57600080fd5b919050565b60008083601f8401126132f357600080fd5b50813567ffffffffffffffff81111561330b57600080fd5b60208301915083602082850101111561299a57600080fd5b60008060008060008060a0878903121561333c57600080fd5b863561334781613296565b95506020870135945061335c604088016132c8565b935060608701359250608087013567ffffffffffffffff81111561337f57600080fd5b61338b89828a016132e1565b979a9699509497509295939492505050565b600080604083850312156133b057600080fd5b82356133bb81613296565b91506133c9602084016132c8565b90509250929050565b6000806000604084860312156133e757600080fd5b83356133f281613296565b9250602084013567ffffffffffffffff81111561340e57600080fd5b61341a868287016132e1565b9497909650939450505050565b6000806000806040858703121561343d57600080fd5b843567ffffffffffffffff8082111561345557600080fd5b613461888389016132e1565b9096509450602087013591508082111561347a57600080fd5b50613487878288016132e1565b95989497509550505050565b600080604083850312156134a657600080fd5b6134af836132c8565b946020939093013593505050565b6000602082840312156134cf57600080fd5b611dc9826132c8565b60008083601f8401126134ea57600080fd5b50813567ffffffffffffffff81111561350257600080fd5b6020830191508360208260051b850101111561299a57600080fd5b6000806000806040858703121561353357600080fd5b843567ffffffffffffffff8082111561354b57600080fd5b613557888389016134d8565b9096509450602087013591508082111561357057600080fd5b50613487878288016134d8565b60006020828403121561358f57600080fd5b5035919050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601b908201527f43616c6c6572206e6f74206174746573746572206d616e616765720000000000604082015260600190565b6020808252601c908201527f746f6b656e20616464726573732063616e6e6f74206265207a65726f00000000604082015260600190565b60006020828403121561364b57600080fd5b815167ffffffffffffffff81168114611dc957600080fd5b6001600160a01b038a811682528916602082015263ffffffff881660408201526060810187905267ffffffffffffffff8616608082015260a0810185905261010060c0820181905281018390526000610120848682850137600083860182015260e083019390935250601f909201601f191690910101979650505050505050565b8183823760009101908152919050565b60006020828403121561370657600080fd5b5051919050565b60005b83811015613728578181015183820152602001613710565b50506000910152565b6000815180845261374981602086016020860161370d565b601f01601f19169290920160200192915050565b6040815260006137706040830185613731565b82810360208401526137828185613731565b95945050505050565b60006020828403121561379d57600080fd5b81518015158114611dc957600080fd5b634e487b7160e01b600052601160045260246000fd5b81810381811115610ef757610ef76137ad565b6001600160a01b038581168252602082018590528316604082015260806060820181905260009061380990830184613731565b9695505050505050565b634e487b7160e01b600052603260045260246000fd5b60006001820161383b5761383b6137ad565b5060010190565b6040808252810184905260008560608301825b878110156138805763ffffffff61386b846132c8565b16825260209283019290910190600101613855565b5083810360208501528481526001600160fb1b038511156138a057600080fd5b8460051b915081866020830137016020019695505050505050565b8082028115828204841417610ef757610ef76137ad565b80820180821115610ef757610ef76137ad565b600080858511156138f557600080fd5b8386111561390257600080fd5b5050820193919092039150565b60006020828403121561392157600080fd5b8151611dc981613296565b634e487b7160e01b600052603160045260246000fd5b6020808252818101527f4e65787456617255696e742c2076616c7565206f7574736964652072616e6765604082015260600190565b6000825161398981846020870161370d565b9190910192915050565b634e487b7160e01b600052602160045260246000fd5b602081526000611dc9602083018461373156fea2646970667358221220592f65a6057e732a10e0c910599ad06f8808589723472c56f994ee99e1c023f464736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af315500000000000000000000000001e2fffebe57c9f8b82c22cf15dec28de2e56ee4000000000000000000000000a81dc97fc2f5df4c1dc39cd9dc20ec778ee31700
-----Decoded View---------------
Arg [0] : _tokenMessenger (address): 0xBd3fa81B58Ba92a82136038B25aDec7066af3155
Arg [1] : _attester (address): 0x01E2fffeBE57C9f8b82c22cf15dec28DE2E56ee4
Arg [2] : _feeCollector (address): 0xa81Dc97Fc2f5Df4c1dc39cd9dC20ec778ee31700
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155
Arg [1] : 00000000000000000000000001e2fffebe57c9f8b82c22cf15dec28de2e56ee4
Arg [2] : 000000000000000000000000a81dc97fc2f5df4c1dc39cd9dc20ec778ee31700
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.