Source Code
Overview
ETH Balance
0 ETH
Token Holdings
More Info
ContractCreator
TokenTracker
Multichain Info
N/A
Latest 25 from a total of 46,512 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Approve | 7644927 | 2 days ago | IN | 0 ETH | 0.00086066 | ||||
Permit | 7631908 | 4 days ago | IN | 0 ETH | 0.0021981 | ||||
Approve | 7271166 | 56 days ago | IN | 0 ETH | 0.00066667 | ||||
Approve | 7243595 | 60 days ago | IN | 0 ETH | 0.0005866 | ||||
Approve | 6814292 | 126 days ago | IN | 0 ETH | 0.01082922 | ||||
Approve | 6790366 | 129 days ago | IN | 0 ETH | 0.003833 | ||||
Permit | 6740254 | 138 days ago | IN | 0 ETH | 0.00108893 | ||||
Approve | 6676293 | 148 days ago | IN | 0 ETH | 0.00061668 | ||||
Approve | 6676293 | 148 days ago | IN | 0 ETH | 0.00109278 | ||||
Approve | 6555818 | 168 days ago | IN | 0 ETH | 0.00014964 | ||||
Approve | 6444465 | 185 days ago | IN | 0 ETH | 0.00062124 | ||||
Permit | 6361128 | 199 days ago | IN | 0 ETH | 0.00083205 | ||||
Approve | 6360556 | 199 days ago | IN | 0 ETH | 0.00003349 | ||||
Mint | 6357075 | 200 days ago | IN | 0 ETH | 0.00076348 | ||||
Mint | 6357013 | 200 days ago | IN | 0 ETH | 0.00084068 | ||||
Mint | 6356995 | 200 days ago | IN | 0 ETH | 0.00084843 | ||||
Mint | 6342721 | 202 days ago | IN | 0 ETH | 0.00018185 | ||||
Mint | 6342258 | 202 days ago | IN | 0 ETH | 0.00018185 | ||||
Mint | 6341058 | 202 days ago | IN | 0 ETH | 0.00018603 | ||||
Permit | 6317453 | 206 days ago | IN | 0 ETH | 0.00005709 | ||||
Permit | 6291051 | 211 days ago | IN | 0 ETH | 0.00023093 | ||||
Approve | 6238026 | 219 days ago | IN | 0 ETH | 0.00098877 | ||||
Approve | 6238023 | 219 days ago | IN | 0 ETH | 0.00093792 | ||||
Approve | 6238008 | 219 days ago | IN | 0 ETH | 0.0006298 | ||||
Approve | 6237999 | 219 days ago | IN | 0 ETH | 0.00062754 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
lnBTC
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-FileCopyrightText: 2022 STROOM <[email protected]> // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; // NOTE: We're not using OZ ERC20 implementation because it's not compatible with solmate import {ERC20} from "solmate/tokens/ERC20.sol"; import "openzeppelin-contracts/contracts/access/Ownable.sol"; import "openzeppelin-contracts/contracts/security/Pausable.sol"; import "openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol"; import "openzeppelin-contracts/contracts/utils/cryptography/SignatureChecker.sol"; import "./lib/BitcoinUtils.sol"; import "./lib/ValidatorMessageReceiver.sol"; import "./lib/LnBtcUtils.sol"; import "./ILnBTC.sol"; /** * @title lnBTC * @dev The lnBTC contract is an ERC20 implementation representing Bitcoins staked into Lightning Network via Stroom.network */ contract lnBTC is ERC20, ValidatorMessageReceiver, BitcoinUtils, Pausable, ILnBTC { BitcoinUtils.Network public network; event RedeemBtcEvent( address indexed _from, string _BTCAddress, uint256 _value, uint256 _id ); event MintBtcEvent( address indexed _to, uint256 _value, bytes32 _btcDepositId ); uint256 public constant DUST_LIMIT = 546; // sat /** * @dev `minWithdrawAmount` represents the minimum amount of satoshis that can be withdrawn. */ uint256 public minWithdrawAmount = 100_000; // 0.001 BTC uint256 public redeemCounter; address public minter; mapping(bytes32 => bool) public btcDepositIds; constructor( BitcoinUtils.Network _network ) ERC20("Stroom Bitcoin", "stBTC", 8) { redeemCounter = 0; // TODO: deduce from chain id network = _network; minter = msg.sender; } // ========= Minting Signature ====== /** * @dev Calculates the hash of an invoice. * @return The hash of the invoice. */ function getMintInvoiceHash( MintInvoice calldata invoice ) public pure returns (bytes32) { return getInvoiceHash(invoice); } // ========= Owner-only ======== /** * @dev Function to stop the contract (Pausable pattern). */ function pause() public onlyOwner { _pause(); } /** * @dev Function to resume the contract (Pausable pattern). */ function unpause() public onlyOwner { _unpause(); } /** * @dev Sets the minimum withdrawal amount. * @param _minWithdrawAmount The new minimum withdrawal amount. * @notice Only the contract owner can call this function. */ function setMinWithdrawAmount(uint256 _minWithdrawAmount) public onlyOwner { require( _minWithdrawAmount >= DUST_LIMIT, "Min withdraw amount should be greater or equal to dust limit" ); minWithdrawAmount = _minWithdrawAmount; } /** * @dev Sets the minter address. * @param _minter The address of the minter. * @notice Only the contract owner can call this function. */ function setMinter(address _minter) public onlyOwner { minter = _minter; } /** * @dev Mint new tokens. * Only the minter can call this function. * @param _amount The amount of tokens to mint. * @param _recipient The address that will receive the minted tokens. * @param _btcDepositId The id of the BTC deposit = keccak256(txHash, vout) */ function mint( uint256 _amount, address _recipient, bytes32 _btcDepositId ) public whenNotPaused { require(msg.sender == minter, "lnBTC: only minter allowed to mint"); _mint(_amount, _recipient, _btcDepositId); } /** * @dev Mints `_amount` of BTC to `_recipient` with a signature. * Anyone can use if they have valid signature from the owner. */ function mint( MintInvoice calldata invoice, bytes calldata signature ) public whenNotPaused onlyValidator(getMintInvoiceHash(invoice), signature) { // TODO: maybe emit different event when minted by signature _mint(invoice.amount, invoice.recipient, invoice.btcDepositId); } /** * @dev Mint new tokens. * @param _amount The amount of tokens to mint. * @param _recipient The address that will receive the minted tokens. * @param _btcDepositId The id of the BTC deposit = keccak256(txHash, vout) */ function _mint( uint256 _amount, address _recipient, bytes32 _btcDepositId ) internal { require(_amount > 0, "MINT_AMOUNT_ZERO"); require(_amount < 21_000_000 * BTC, "MINT_AMOUNT_TOO_BIG"); require(_recipient != address(this), "MINT_TO_THE_CONTRACT_ADDRESS"); require( btcDepositIds[_btcDepositId] == false, "MINT_ALREADY_PROCESSED" ); btcDepositIds[_btcDepositId] = true; _mint(_recipient, _amount); emit MintBtcEvent(_recipient, _amount, _btcDepositId); } /** * @dev Burns `_amount` of BTC. * Function is called by the user. * @param _amount The amount of tokens to burn. * @param BTCAddress The BTC address to send the BTC to. * @notice The BTC address must be valid. */ function redeem( uint256 _amount, string calldata BTCAddress ) public whenNotPaused { require( _amount >= minWithdrawAmount, "The sent value must be greater or equal to min withdraw amount" ); require( validateBitcoinAddress(network, BTCAddress), "The sent BTC address is not valid" ); // balance check in the following function _burn(msg.sender, _amount); redeemCounter += 1; emit RedeemBtcEvent(msg.sender, BTCAddress, _amount, redeemCounter); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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 message) { // 32 is the length in bytes of hash, // enforced by the type signature above /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") mstore(0x1c, hash) message := keccak256(0x00, 0x3c) } } /** * @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 data) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, "\x19\x01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) data := keccak256(ptr, 0x42) } } /** * @dev Returns an Ethereum Signed Data with intended validator, created from a * `validator` and `data` according to the version 0 of EIP-191. * * See {recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x00", validator, data)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/SignatureChecker.sol) pragma solidity ^0.8.0; import "./ECDSA.sol"; import "../../interfaces/IERC1271.sol"; /** * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like * Argent and Gnosis Safe. * * _Available since v4.1._ */ library SignatureChecker { /** * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`. * * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus * change through time. It could return true at block N and false at block N+1 (or the opposite). */ function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) { (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature); return (error == ECDSA.RecoverError.NoError && recovered == signer) || isValidERC1271SignatureNow(signer, hash, signature); } /** * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated * against the signer smart contract using ERC1271. * * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus * change through time. It could return true at block N and false at block N+1 (or the opposite). */ function isValidERC1271SignatureNow( address signer, bytes32 hash, bytes memory signature ) internal view returns (bool) { (bool success, bytes memory result) = signer.staticcall( abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature) ); return (success && result.length >= 32 && abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "forge-std/console.sol"; // TODO: import from submodules instead including in the project? import "./Base58.sol"; // TODO: make it a library, and auto-link inside go-bindings contract BitcoinUtils { // There are currently three invoice address formats in use: // P2PKH which begin with the number 1, eg: 1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2 // P2SH type starting with the number 3, eg: 3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy // Bech32 type starting with bc1, eg: bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq // Testnet: // P2PKH which begin with the number m or n, eg: mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn // P2SH type starting with the number 2, eg: 2MzQwSSnBHWHqSAqtTVQ6v47XtaisrJa1Vc // Bech32 type starting with tb1, eg: tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx // Regtest: // P2PKH which begin with the number m or n, eg: mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn // P2SH type starting with the number 2, eg: 2MzQwSSnBHWHqSAqtTVQ6v47XtaisrJa1Vc // Bech32 type starting with bcrt1, eg: bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx //NB: don't forget to update `lnbtc_ext.go` when changing this enum! enum Network { Mainnet, Testnet, Regtest } string constant BECH32_ALPHABET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; function BECH32_ALPHABET_MAP(bytes1 char) public view returns (uint8) { // '{"0":15,"2":10,"3":17,"4":21,"5":20,"6":26,"7":30,"8":7,"9":5,"q":0,"p":1,"z":2,"r":3,"y":4,"x":6,"g":8,"f":9,"t":11,"v":12,"d":13,"w":14,"s":16,"j":18,"n":19,"k":22,"h":23,"c":24,"e":25,"m":27,"u":28,"a":29,"l":31}' if (char == bytes1("0")) return 15; if (char == bytes1("2")) return 10; if (char == bytes1("3")) return 17; if (char == bytes1("4")) return 21; if (char == bytes1("5")) return 20; if (char == bytes1("6")) return 26; if (char == bytes1("8")) return 7; if (char == bytes1("7")) return 30; if (char == bytes1("9")) return 5; if (char == bytes1("q")) return 0; if (char == bytes1("p")) return 1; if (char == bytes1("z")) return 2; if (char == bytes1("r")) return 3; if (char == bytes1("y")) return 4; if (char == bytes1("x")) return 6; if (char == bytes1("g")) return 8; if (char == bytes1("f")) return 9; if (char == bytes1("t")) return 11; if (char == bytes1("v")) return 12; if (char == bytes1("d")) return 13; if (char == bytes1("w")) return 14; if (char == bytes1("s")) return 16; if (char == bytes1("j")) return 18; if (char == bytes1("n")) return 19; if (char == bytes1("k")) return 22; if (char == bytes1("h")) return 23; if (char == bytes1("c")) return 24; if (char == bytes1("e")) return 25; if (char == bytes1("m")) return 27; if (char == bytes1("u")) return 28; if (char == bytes1("a")) return 29; if (char == bytes1("l")) return 31; console.log("Invalid character"); console.logBytes1(char); // revert("Invalid character"); return type(uint8).max; } // const ALPHABET_MAP: { [key: string]: number } = {}; // for (let z = 0; z < ALPHABET.length; z++) { // const x = ALPHABET.charAt(z); // ALPHABET_MAP[x] = z; // } bytes constant BTC_P2PKH = hex"31"; // prefix = 1 bytes constant BTC_P2SH = hex"33"; // prefix = 3 bytes constant BTC_BECH32_MAINNET = hex"626331"; // prefix = bc1 bytes constant BTC_BECH32_REGTEST = hex"6263727431"; // prefix = bcrt1 bytes constant BTC_BECH32_TESTNET = hex"746231"; // prefix = tb1 function getBtcBech32Prefix(Network network) public pure returns (bytes memory) { if (network == Network.Mainnet) { return BTC_BECH32_MAINNET; } else if (network == Network.Regtest) { return BTC_BECH32_REGTEST; } else if (network == Network.Testnet) { return BTC_BECH32_TESTNET; } else { revert("Unknown network type"); } } function validateBitcoinAddress(Network network, string calldata BTCAddress) public view returns (bool) { bytes memory empty; if (equalBytes(bytes(BTCAddress), empty)) return false; if (equalBytes(bytes(BTCAddress)[: 1], BTC_P2PKH) || equalBytes(bytes(BTCAddress)[: 1], BTC_P2SH)) { if (bytes(BTCAddress).length < 26 || bytes(BTCAddress).length > 35 || !alphabetCheck(bytes(BTCAddress))) { return false; } // check base58 checksum and encoding return validateBase58Checksum(BTCAddress); } bytes memory prefix = getBtcBech32Prefix(network); if (equalBytes(bytes(BTCAddress)[: prefix.length], prefix)) { if (network == Network.Regtest) { if (bytes(BTCAddress).length < 43 || bytes(BTCAddress).length > 63) return false; } else { if (bytes(BTCAddress).length < 42 || bytes(BTCAddress).length > 62) return false; } // check bech32 checksum and encoding return validateBech32Checksum(BTCAddress); } return false; } function equalBytes(bytes memory one, bytes memory two) public pure returns (bool) { if (!(one.length == two.length)) { return false; } for (uint256 i = 0; i < one.length; i++) { if (!(one[i] == two[i])) { return false; } } return true; } function alphabetCheck(bytes memory BTCAddress) public pure returns (bool) { for (uint256 i = 0; i < BTCAddress.length; i++) { uint8 charCode = uint8(BTCAddress[i]); bool contains = isLetter(charCode); if (!contains) return false; } return true; } function isLetter(uint8 charCode) internal pure returns (bool) { if (charCode == 73 || charCode == 79 || charCode == 108) { return false; } if (charCode >= 49 && charCode <= 57) { return true; } if (charCode >= 65 && charCode <= 90) { return true; } if (charCode >= 97 && charCode <= 122) { return true; } return false; } function validateBech32Checksum(string memory btcAddress) public view returns (bool) { // TODO: DOESNT SUPPORT TAPROOT ADDRESSES // from https://github.com/bitcoinjs/bech32/blob/master/src/index.ts // function __decode(str: string, LIMIT?: number): Decoded | string { // LIMIT = LIMIT || 90; // if (str.length < 8) return str + ' too short'; // if (str.length > LIMIT) return 'Exceeds length limit'; // // don't allow mixed case // const lowered = str.toLowerCase(); // const uppered = str.toUpperCase(); // if (str !== lowered && str !== uppered) return 'Mixed-case string ' + str; // str = lowered; // const split = str.lastIndexOf('1'); // if (split === -1) return 'No separator character for ' + str; // if (split === 0) return 'Missing prefix for ' + str; // const prefix = str.slice(0, split); // const wordChars = str.slice(split + 1); // if (wordChars.length < 6) return 'Data too short'; // let chk = prefixChk(prefix); // if (typeof chk === 'string') return chk; // const words = []; // for (let i = 0; i < wordChars.length; ++i) { // const c = wordChars.charAt(i); // const v = ALPHABET_MAP[c]; // if (v === undefined) return 'Unknown character ' + c; // chk = polymodStep(chk) ^ v; // // not in the checksum? // if (i + 6 >= wordChars.length) continue; // words.push(v); // } // if (chk !== ENCODING_CONST) return 'Invalid checksum for ' + str; // return { prefix, words }; // } console.log("\nvalidate bech32 checksum"); console.log("address"); console.log(btcAddress); bytes memory _btcAddress = bytes(btcAddress); if (_btcAddress.length < 8) { console.log("too short"); return false; } if (_btcAddress.length > 90) { console.log("too long"); return false; } // TODO: don't allow mixed case // bytes memory lowered = bytes(toLower(btcAddress)); // bytes memory uppered = bytes(toUpper(btcAddress)); // if ( // !equalBytes(_btcAddress, lowered) && // !equalBytes(_btcAddress, uppered) // ) { // console.log("mixed case"); // return false; // } _btcAddress = bytes(btcAddress); uint256 split = 0; for (uint256 i = 0; i < _btcAddress.length; i++) { if (_btcAddress[i] == "1") { split = i; break; } } if (split == 0) { console.log("no separator"); return false; } if (split == 1) { console.log("missing prefix"); return false; } bytes memory prefix = new bytes(split); bytes memory wordChars = new bytes(_btcAddress.length - split - 1); for (uint256 i = 0; i < split; i++) { prefix[i] = _btcAddress[i]; } for (uint256 i = 0; i < wordChars.length; i++) { wordChars[i] = _btcAddress[i + split + 1]; } console.log("prefix"); console.logBytes(prefix); // console.log("wordChars"); // console.logBytes(wordChars); if (wordChars.length < 6) { console.log("data too short"); return false; } uint256 chk = prefixChk(bytes(prefix)); if (chk == 0) { console.log("invalid prefix"); return false; } bytes memory words = new bytes(wordChars.length); for (uint256 i = 0; i < wordChars.length; i++) { bytes1 c = wordChars[i]; uint8 v = BECH32_ALPHABET_MAP(c); // ALPHABET_MAP reverts if the character is not in the map, so this is not needed if (v == type(uint8).max) { console.log("unknown character"); console.log(i); console.logBytes1(c); console.log("char", string(abi.encodePacked(c))); return false; } // console.log("v", v); // console.log("char", string(abi.encodePacked(c))); chk = polymodStep(chk) ^ v; // not in the checksum? if (i + 6 >= wordChars.length) continue; words[i] = bytes1(v); } console.log("words"); console.logBytes(words); // ENCODING_CONST is bech32 or bech32m if (chk != uint256(0x2bc830a3) && chk != 1) { console.log("invalid checksum", chk); return false; } console.log("valid checksum", chk); return true; } function polymodStep(uint256 pre) public pure returns (uint256) { uint256 b = pre >> 25; return ( ((pre & 0x1ffffff) << 5) ^ ((b >> 0) & 1 == 1 ? 0x3b6a57b2 : 0) ^ ((b >> 1) & 1 == 1 ? 0x26508e6d : 0) ^ ((b >> 2) & 1 == 1 ? 0x1ea119fa : 0) ^ ((b >> 3) & 1 == 1 ? 0x3d4233dd : 0) ^ ((b >> 4) & 1 == 1 ? 0x2a1462b3 : 0) ); } function prefixChk(bytes memory prefix) public pure returns (uint256) { uint256 chk = 1; for (uint256 i = 0; i < bytes(prefix).length; ++i) { uint256 c = uint8(prefix[i]); if (c < 33 || c > 126) revert("Invalid prefix"); chk = polymodStep(chk) ^ (c >> 5); } chk = polymodStep(chk); for (uint256 i = 0; i < prefix.length; ++i) { uint256 v = uint8(prefix[i]); chk = polymodStep(chk) ^ (v & 0x1f); } return chk; } function validateBase58Checksum(string calldata btcAddress) public view returns (bool) { bytes memory rawData = decodeFromString(btcAddress); console.log("validateBase58Checksum"); console.log("payload"); console.logBytes(rawData); // raw data is: 1 byte version + 20 bytes of data + 4 bytes of checksum if (rawData.length != 25) return false; // version is 1 byte bytes memory version = new bytes(1); version[0] = rawData[0]; console.log("version"); console.logBytes(version); bytes memory payload = new bytes(rawData.length - 1 - 4); for (uint256 i = 0; i < rawData.length - 1 - 4; i++) { payload[i] = rawData[i + 1]; } console.log("payload"); console.logBytes(payload); if (payload.length != 20) return false; bytes memory checksum = new bytes(4); for (uint256 i = 0; i < 4; i++) { checksum[i] = rawData[rawData.length - 4 + i]; } console.log("checksum"); console.logBytes(checksum); bytes32 calculateChecksum = sha256(abi.encodePacked(sha256(abi.encodePacked(version, payload)))); console.log("calculated checksum"); console.logBytes32(calculateChecksum); // if (checksum[0] ^ newChecksum[0] | // checksum[1] ^ newChecksum[1] | // checksum[2] ^ newChecksum[2] | // checksum[3] ^ newChecksum[3]) return if ( (checksum[0] ^ calculateChecksum[0]) | (checksum[1] ^ calculateChecksum[1]) | (checksum[2] ^ calculateChecksum[2]) | (checksum[3] ^ calculateChecksum[3]) != 0 ) return false; return true; } }
// SPDX-License-Identifier: MIT // SPDX-FileCopyrightText: 2023 STROOM <[email protected]> pragma solidity ^0.8.18; import "openzeppelin-contracts/contracts/access/Ownable.sol"; import "bip340-solidity/src/Bip340Ecrec.sol"; contract ValidatorMessageReceiver is Ownable, Bip340Ecrec { // public key of combined FROST based validator consensus network bytes32 public validatorPublicKey; constructor() {} function getUpdateValidatorPublicKeyMessage( bytes32 _validatorPublicKey ) public pure returns (bytes32) { return keccak256(abi.encodePacked("STROOM_UPDATE_VALIDATOR_PUBLIC_KEY", _validatorPublicKey)); } function setValidatorPublicKey( bytes32 _validatorPublicKey ) public onlyOwner { validatorPublicKey = _validatorPublicKey; } function setValidatorPublicKeySigned( bytes32 _validatorPublicKey, bytes calldata signature ) public onlyValidator(getUpdateValidatorPublicKeyMessage(_validatorPublicKey), signature) { validatorPublicKey = _validatorPublicKey; } modifier onlyValidator( bytes32 hash, bytes calldata signature ) { require(validateMessage(hash, signature), "ValidatorMessageReceiver: INVALID_SIGNATURE"); _; } function validateMessage( bytes32 hash, bytes calldata signature ) public view returns (bool) { require(validatorPublicKey != 0, "ValidatorMessageReceiver: NO_VALIDATOR_PUBLIC_KEY"); // slice signature in two bytes32 blocks, rx and s uint256 rx = uint256(bytes32(signature[0 : 32])); uint256 s = uint256(bytes32(signature[32 : 64])); return verify(uint256(validatorPublicKey), rx, s, hash); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; bool constant ADD_SUPPLY = false; bool constant SUB_SUPPLY = true; uint256 constant BTC = 1e8; // sat uint256 constant SHARES_PER_BTC = 1e6; struct MintInvoice { bytes32 btcDepositId; address recipient; uint256 amount; } /** * @dev The prefix used for minting invoices. */ bytes32 constant MINT_INVOICE_PREFIX = keccak256("STROOM_MINT_INVOICE"); /** * @dev Calculates the hash of an invoice. * @return The hash of the invoice. */ function getInvoiceHash(MintInvoice calldata invoice) pure returns (bytes32) { return keccak256( abi.encodePacked( MINT_INVOICE_PREFIX, invoice.recipient, invoice.amount, invoice.btcDepositId ) ); } function roundDiv(uint256 a, uint256 b) pure returns (uint256) { return (a + b / 2) / b; }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface ILnBTC { function mint(uint256 amount, address to, bytes32 hash) external; function redeem(uint256 _amount, string calldata BTCAddress) external; }
// 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.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.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 `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @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); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. * * _Available since v4.1._ */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
// SPDX-License-Identifier: MIT pragma solidity >=0.4.22 <0.9.0; library console { address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67); function _sendLogPayload(bytes memory payload) private view { uint256 payloadLength = payload.length; address consoleAddress = CONSOLE_ADDRESS; /// @solidity memory-safe-assembly assembly { let payloadStart := add(payload, 32) let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) } } function log() internal view { _sendLogPayload(abi.encodeWithSignature("log()")); } function logInt(int p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(int)", p0)); } function logUint(uint p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); } function logString(string memory p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } function logBool(bool p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); } function logAddress(address p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); } function logBytes(bytes memory p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); } function logBytes1(bytes1 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); } function logBytes2(bytes2 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); } function logBytes3(bytes3 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); } function logBytes4(bytes4 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); } function logBytes5(bytes5 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); } function logBytes6(bytes6 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); } function logBytes7(bytes7 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); } function logBytes8(bytes8 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); } function logBytes9(bytes9 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); } function logBytes10(bytes10 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); } function logBytes11(bytes11 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); } function logBytes12(bytes12 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); } function logBytes13(bytes13 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); } function logBytes14(bytes14 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); } function logBytes15(bytes15 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); } function logBytes16(bytes16 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); } function logBytes17(bytes17 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); } function logBytes18(bytes18 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); } function logBytes19(bytes19 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); } function logBytes20(bytes20 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); } function logBytes21(bytes21 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); } function logBytes22(bytes22 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); } function logBytes23(bytes23 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); } function logBytes24(bytes24 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); } function logBytes25(bytes25 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); } function logBytes26(bytes26 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); } function logBytes27(bytes27 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); } function logBytes28(bytes28 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); } function logBytes29(bytes29 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); } function logBytes30(bytes30 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); } function logBytes31(bytes31 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); } function logBytes32(bytes32 p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); } function log(uint p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint)", p0)); } function log(string memory p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } function log(bool p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); } function log(address p0) internal view { _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); } function log(uint p0, uint p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1)); } function log(uint p0, string memory p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1)); } function log(uint p0, bool p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1)); } function log(uint p0, address p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1)); } function log(string memory p0, uint p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1)); } function log(string memory p0, string memory p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); } function log(string memory p0, bool p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); } function log(string memory p0, address p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); } function log(bool p0, uint p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1)); } function log(bool p0, string memory p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); } function log(bool p0, bool p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); } function log(bool p0, address p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); } function log(address p0, uint p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1)); } function log(address p0, string memory p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); } function log(address p0, bool p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); } function log(address p0, address p1) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); } function log(uint p0, uint p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2)); } function log(uint p0, uint p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2)); } function log(uint p0, uint p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2)); } function log(uint p0, uint p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2)); } function log(uint p0, string memory p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2)); } function log(uint p0, string memory p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2)); } function log(uint p0, string memory p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2)); } function log(uint p0, string memory p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2)); } function log(uint p0, bool p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2)); } function log(uint p0, bool p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2)); } function log(uint p0, bool p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2)); } function log(uint p0, bool p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2)); } function log(uint p0, address p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2)); } function log(uint p0, address p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2)); } function log(uint p0, address p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2)); } function log(uint p0, address p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2)); } function log(string memory p0, uint p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2)); } function log(string memory p0, uint p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2)); } function log(string memory p0, uint p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2)); } function log(string memory p0, uint p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2)); } function log(string memory p0, string memory p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2)); } function log(string memory p0, string memory p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); } function log(string memory p0, string memory p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); } function log(string memory p0, string memory p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); } function log(string memory p0, bool p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2)); } function log(string memory p0, bool p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); } function log(string memory p0, bool p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); } function log(string memory p0, bool p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); } function log(string memory p0, address p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2)); } function log(string memory p0, address p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); } function log(string memory p0, address p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); } function log(string memory p0, address p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); } function log(bool p0, uint p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2)); } function log(bool p0, uint p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2)); } function log(bool p0, uint p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2)); } function log(bool p0, uint p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2)); } function log(bool p0, string memory p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2)); } function log(bool p0, string memory p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); } function log(bool p0, string memory p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); } function log(bool p0, string memory p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); } function log(bool p0, bool p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2)); } function log(bool p0, bool p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); } function log(bool p0, bool p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); } function log(bool p0, bool p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); } function log(bool p0, address p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2)); } function log(bool p0, address p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); } function log(bool p0, address p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); } function log(bool p0, address p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); } function log(address p0, uint p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2)); } function log(address p0, uint p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2)); } function log(address p0, uint p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2)); } function log(address p0, uint p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2)); } function log(address p0, string memory p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2)); } function log(address p0, string memory p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); } function log(address p0, string memory p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); } function log(address p0, string memory p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); } function log(address p0, bool p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2)); } function log(address p0, bool p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); } function log(address p0, bool p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); } function log(address p0, bool p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); } function log(address p0, address p1, uint p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2)); } function log(address p0, address p1, string memory p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); } function log(address p0, address p1, bool p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); } function log(address p0, address p1, address p2) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); } function log(uint p0, uint p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3)); } function log(uint p0, uint p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3)); } function log(uint p0, uint p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3)); } function log(uint p0, uint p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3)); } function log(uint p0, uint p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3)); } function log(uint p0, uint p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3)); } function log(uint p0, uint p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3)); } function log(uint p0, uint p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3)); } function log(uint p0, uint p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3)); } function log(uint p0, uint p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3)); } function log(uint p0, uint p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3)); } function log(uint p0, uint p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3)); } function log(uint p0, uint p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3)); } function log(uint p0, uint p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3)); } function log(uint p0, uint p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3)); } function log(uint p0, uint p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3)); } function log(uint p0, string memory p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3)); } function log(uint p0, bool p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3)); } function log(uint p0, bool p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3)); } function log(uint p0, bool p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3)); } function log(uint p0, bool p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3)); } function log(uint p0, bool p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3)); } function log(uint p0, bool p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3)); } function log(uint p0, bool p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3)); } function log(uint p0, bool p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3)); } function log(uint p0, bool p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3)); } function log(uint p0, bool p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3)); } function log(uint p0, bool p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3)); } function log(uint p0, bool p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3)); } function log(uint p0, bool p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3)); } function log(uint p0, bool p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3)); } function log(uint p0, bool p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3)); } function log(uint p0, bool p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3)); } function log(uint p0, address p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3)); } function log(uint p0, address p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3)); } function log(uint p0, address p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3)); } function log(uint p0, address p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3)); } function log(uint p0, address p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3)); } function log(uint p0, address p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3)); } function log(uint p0, address p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3)); } function log(uint p0, address p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3)); } function log(uint p0, address p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3)); } function log(uint p0, address p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3)); } function log(uint p0, address p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3)); } function log(uint p0, address p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3)); } function log(uint p0, address p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3)); } function log(uint p0, address p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3)); } function log(uint p0, address p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3)); } function log(uint p0, address p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); } function log(bool p0, uint p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3)); } function log(bool p0, uint p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3)); } function log(bool p0, uint p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3)); } function log(bool p0, uint p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3)); } function log(bool p0, uint p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3)); } function log(bool p0, uint p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3)); } function log(bool p0, uint p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3)); } function log(bool p0, uint p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3)); } function log(bool p0, uint p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3)); } function log(bool p0, uint p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3)); } function log(bool p0, uint p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, uint p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3)); } function log(bool p0, uint p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3)); } function log(bool p0, uint p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3)); } function log(bool p0, uint p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3)); } function log(bool p0, uint p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); } function log(address p0, uint p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3)); } function log(address p0, uint p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3)); } function log(address p0, uint p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3)); } function log(address p0, uint p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3)); } function log(address p0, uint p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3)); } function log(address p0, uint p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3)); } function log(address p0, uint p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3)); } function log(address p0, uint p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3)); } function log(address p0, uint p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3)); } function log(address p0, uint p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3)); } function log(address p0, uint p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3)); } function log(address p0, uint p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3)); } function log(address p0, uint p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3)); } function log(address p0, uint p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3)); } function log(address p0, uint p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3)); } function log(address p0, uint p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); } function log(address p0, address p1, uint p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3)); } function log(address p0, address p1, uint p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3)); } function log(address p0, address p1, uint p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, uint p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, uint p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, string memory p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, bool p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, address p3) internal view { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; bytes constant ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; /** * @notice encode is used to encode the given bytes in base58 standard. * @param data_ raw data, passed in as bytes. * @return base58 encoded data_, returned as bytes. */ function encode(bytes memory data_) pure returns (bytes memory) { unchecked { uint256 size = data_.length; uint256 zeroCount; while (zeroCount < size && data_[zeroCount] == 0) { zeroCount++; } size = zeroCount + ((size - zeroCount) * 8351) / 6115 + 1; bytes memory slot = new bytes(size); uint32 carry; int256 m; int256 high = int256(size) - 1; for (uint256 i = 0; i < data_.length; i++) { m = int256(size - 1); for (carry = uint8(data_[i]); m > high || carry != 0; m--) { carry = carry + 256 * uint8(slot[uint256(m)]); slot[uint256(m)] = bytes1(uint8(carry % 58)); carry /= 58; } high = m; } uint256 n; for (n = zeroCount; n < size && slot[n] == 0; n++) {} size = slot.length - (n - zeroCount); bytes memory out = new bytes(size); for (uint256 i = 0; i < size; i++) { uint256 j = i + n - zeroCount; out[i] = ALPHABET[uint8(slot[j])]; } return out; } } /** * @notice decode is used to decode the given string in base58 standard. * @param data_ data encoded with base58, passed in as bytes. * @return raw data, returned as bytes. */ function decode(bytes memory data_) pure returns (bytes memory) { unchecked { uint256 zero = 49; uint256 b58sz = data_.length; uint256 zcount = 0; for (uint256 i = 0; i < b58sz && uint8(data_[i]) == zero; i++) { zcount++; } uint256 t; uint256 c; bool f; bytes memory binu = new bytes(2 * (((b58sz * 8351) / 6115) + 1)); uint32[] memory outi = new uint32[]((b58sz + 3) / 4); for (uint256 i = 0; i < data_.length; i++) { bytes1 r = data_[i]; (c, f) = indexOf(ALPHABET, r); require(f, "invalid base58 digit"); for (int256 k = int256(outi.length) - 1; k >= 0; k--) { t = uint64(outi[uint256(k)]) * 58 + c; c = t >> 32; outi[uint256(k)] = uint32(t & 0xffffffff); } } uint64 mask = uint64(b58sz % 4) * 8; if (mask == 0) { mask = 32; } mask -= 8; uint256 outLen = 0; for (uint256 j = 0; j < outi.length; j++) { while (mask < 32) { binu[outLen] = bytes1(uint8(outi[j] >> mask)); outLen++; if (mask < 8) { break; } mask -= 8; } mask = 24; } for (uint256 msb = zcount; msb < binu.length; msb++) { if (binu[msb] > 0) { return slice(binu, msb - zcount, outLen); } } return slice(binu, 0, outLen); } } /** * @notice encodeToString is used to encode the given byte in base58 standard. * @param data_ raw data, passed in as bytes. * @return base58 encoded data_, returned as a string. */ function encodeToString(bytes memory data_) pure returns (string memory) { return string(encode(data_)); } /** * @notice encodeFromString is used to encode the given string in base58 standard. * @param data_ raw data, passed in as a string. * @return base58 encoded data_, returned as bytes. */ function encodeFromString(string memory data_) pure returns (bytes memory) { return encode(bytes(data_)); } /** * @notice decode is used to decode the given string in base58 standard. * @param data_ data encoded with base58, passed in as string. * @return raw data, returned as bytes. */ function decodeFromString(string memory data_) pure returns (bytes memory) { return decode(bytes(data_)); } /** * @notice slice is used to slice the given byte, returns the bytes in the range of [start_, end_) * @param data_ raw data, passed in as bytes. * @param start_ start index. * @param end_ end index. * @return slice data */ function slice(bytes memory data_, uint256 start_, uint256 end_) pure returns (bytes memory) { unchecked { bytes memory ret = new bytes(end_ - start_); for (uint256 i = 0; i < end_ - start_; i++) { ret[i] = data_[i + start_]; } return ret; } } /** * @notice indexOf is used to find where char_ appears in data_. * @param data_ raw data, passed in as bytes. * @param char_ target byte. * @return index, and whether the search was successful. */ function indexOf(bytes memory data_, bytes1 char_) pure returns (uint256, bool) { unchecked { for (uint256 i = 0; i < data_.length; i++) { if (data_[i] == char_) { return (i, true); } } return (0, false); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import "./Secp256k1.sol"; import "./Bip340.sol"; import "./Bip340Util.sol"; contract Bip340Ecrec is Bip340Verifier { /// Uses the ecrecover hack to verify a schnorr signature more efficiently than it should. /// // Based on `https://hackmd.io/@nZ-twauPRISEa6G9zg3XRw/SyjJzSLt9` // ^ this line is un-doc-commented because solc is annoying function verify(uint256 px, uint256 rx, uint256 s, bytes32 m) public pure override returns (bool) { // Check pubkey, rx, and s are in-range. if (px >= Secp256k1.PP || rx >= Secp256k1.PP || s >= Secp256k1.NN) { return false; } (address exp, bool ok) = Bip340Util.convToFakeAddr(rx); if (!ok) { return false; } uint256 e = Bip340Util.computeChallenge(bytes32(rx), bytes32(px), m); bytes32 sp = bytes32(Secp256k1.NN - mulmod(s, px, Secp256k1.NN)); bytes32 ep = bytes32(Secp256k1.NN - mulmod(e, px, Secp256k1.NN)); // 27 apparently used to signal even parity (which it will always have). address rvh = ecrecover(sp, 27, bytes32(px), ep); return rvh == exp; // if recovery fails we fail anyways } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 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 256, 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 << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // // Modified from https://raw.githubusercontent.com/witnet/elliptic-curve-solidity/master/examples/Secp256k1.sol // // See license terms from the above original source. pragma solidity >=0.8.0; import "./EllipticCurve.sol"; /** * @title Secp256k1 Elliptic Curve * @notice Example of particularization of Elliptic Curve for secp256k1 curve * @author Witnet Foundation */ library Secp256k1 { uint256 public constant GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798; uint256 public constant GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8; uint256 public constant AA = 0; uint256 public constant BB = 7; uint256 public constant PP = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; uint256 public constant NN = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; // curve order /// @notice Public Key derivation from private key /// Warning: this is just an example. Do not expose your private key. /// @param privKey The private key /// @return (qx, qy) The Public Key function derivePubKey(uint256 privKey) external pure returns (uint256, uint256) { return EllipticCurve.ecMul( privKey, GX, GY, AA, PP ); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface Bip340Verifier { /// Verifies a BIP340 signature parsed as `(rx, s)` form against a message /// `m` and a pubkey's x coord `px`. /// /// px - public key x coordinate /// rx - signature r commitment /// s - signature s proof /// m - message hash function verify(uint256 px, uint256 rx, uint256 s, bytes32 m) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import "./EllipticCurve.sol"; import "./Secp256k1.sol"; library Bip340Util { /// BIP340 challenge function. /// /// Hopefully the first SHA256 call gets inlined. function computeChallenge(bytes32 rx, bytes32 px, bytes32 m) internal pure returns (uint256) { // Precomputed `sha256("BIP0340/challenge")`. // // Saves ~10k gas, mostly from byte shuffling to prepare the call. //bytes32 tag = sha256("BIP0340/challenge"); bytes32 tag = 0x7bb52d7a9fef58323eb1bf7a407db382d2f3f2d81bb1224f49fe518f6d48d37c; // Let e = int(hashBIP0340/challenge(bytes(r) || bytes(P) || m)) mod n. return uint256(sha256(abi.encodePacked(tag, tag, rx, px, m))) % Secp256k1.NN; } /// Given an x coordinate, returns the y coordinate of an even point on /// the secp256k1 curve. This can be used to precompute the pubkey Y as /// mentioned in a few places. /// /// The second return value specifies if the operation was successful. function liftX(uint256 _x) internal pure returns (uint256, bool) { uint256 _pp = Secp256k1.PP; uint256 _aa = Secp256k1.AA; uint256 _bb = Secp256k1.BB; if (_x >= _pp) { return (0, false); } // Taken from the EllipticCurve code. uint256 y2 = addmod(mulmod(_x, mulmod(_x, _x, _pp), _pp), addmod(mulmod(_x, _aa, _pp), _bb, _pp), _pp); y2 = EllipticCurve.expMod(y2, (_pp + 1) / 4, _pp); uint256 y = (y2 & 1) == 0 ? y2 : _pp - y2; //require(y % 2 == 0, "not even???"); return (y, true); } /// Internal function for doing the affine conversion for only the x coordinate. function xToAffine(uint256 _x, uint256 _z, uint256 _pp) internal pure returns (uint256) { uint256 zInv = EllipticCurve.invMod(_z, _pp); uint256 zInv2 = mulmod(zInv, zInv, _pp); return mulmod(_x, zInv2, _pp); } /// Converts a BIP340 pubkey X coord to what it would look like as an /// Ethereum address. function convToFakeAddr(uint256 px) internal pure returns (address, bool) { (uint256 py, bool ok) = liftX(px); if (!ok) { return (address(0), false); } bytes32 h = keccak256(abi.encodePacked(bytes32(px), bytes32(py))); return (address(uint160(uint256(h))), true); } }
// SPDX-License-Identifier: MIT // // Taken from https://github.com/witnet/elliptic-curve-solidity/blob/master/contracts/EllipticCurve.sol // // See license terms from the above original source. pragma solidity >=0.8.0; /** * @title Elliptic Curve Library * @dev Library providing arithmetic operations over elliptic curves. * This library does not check whether the inserted points belong to the curve * `isOnCurve` function should be used by the library user to check the aforementioned statement. * @author Witnet Foundation */ library EllipticCurve { // Pre-computed constant for 2 ** 255 uint256 constant private U255_MAX_PLUS_1 = 57896044618658097711785492504343953926634992332820282019728792003956564819968; /// @dev Modular euclidean inverse of a number (mod p). /// @param _x The number /// @param _pp The modulus /// @return q such that x*q = 1 (mod _pp) function invMod(uint256 _x, uint256 _pp) internal pure returns (uint256) { require(_x != 0 && _x != _pp && _pp != 0, "Invalid number"); uint256 q = 0; uint256 newT = 1; uint256 r = _pp; uint256 t; while (_x != 0) { t = r / _x; (q, newT) = (newT, addmod(q, (_pp - mulmod(t, newT, _pp)), _pp)); (r, _x) = (_x, r - t * _x); } return q; } /// @dev Modular exponentiation, b^e % _pp. /// Source: https://github.com/androlo/standard-contracts/blob/master/contracts/src/crypto/ECCMath.sol /// @param _base base /// @param _exp exponent /// @param _pp modulus /// @return r such that r = b**e (mod _pp) function expMod(uint256 _base, uint256 _exp, uint256 _pp) internal pure returns (uint256) { require(_pp!=0, "Modulus is zero"); if (_base == 0) return 0; if (_exp == 0) return 1; uint256 r = 1; uint256 bit = U255_MAX_PLUS_1; assembly { for { } gt(bit, 0) { }{ r := mulmod(mulmod(r, r, _pp), exp(_base, iszero(iszero(and(_exp, bit)))), _pp) r := mulmod(mulmod(r, r, _pp), exp(_base, iszero(iszero(and(_exp, div(bit, 2))))), _pp) r := mulmod(mulmod(r, r, _pp), exp(_base, iszero(iszero(and(_exp, div(bit, 4))))), _pp) r := mulmod(mulmod(r, r, _pp), exp(_base, iszero(iszero(and(_exp, div(bit, 8))))), _pp) bit := div(bit, 16) } } return r; } /// @dev Converts a point (x, y, z) expressed in Jacobian coordinates to affine coordinates (x', y', 1). /// @param _x coordinate x /// @param _y coordinate y /// @param _z coordinate z /// @param _pp the modulus /// @return (x', y') affine coordinates function toAffine( uint256 _x, uint256 _y, uint256 _z, uint256 _pp) internal pure returns (uint256, uint256) { uint256 zInv = invMod(_z, _pp); uint256 zInv2 = mulmod(zInv, zInv, _pp); uint256 x2 = mulmod(_x, zInv2, _pp); uint256 y2 = mulmod(_y, mulmod(zInv, zInv2, _pp), _pp); return (x2, y2); } /// @dev Derives the y coordinate from a compressed-format point x [[SEC-1]](https://www.secg.org/SEC1-Ver-1.0.pdf). /// @param _prefix parity byte (0x02 even, 0x03 odd) /// @param _x coordinate x /// @param _aa constant of curve /// @param _bb constant of curve /// @param _pp the modulus /// @return y coordinate y function deriveY( uint8 _prefix, uint256 _x, uint256 _aa, uint256 _bb, uint256 _pp) internal pure returns (uint256) { require(_prefix == 0x02 || _prefix == 0x03, "Invalid compressed EC point prefix"); // x^3 + ax + b uint256 y2 = addmod(mulmod(_x, mulmod(_x, _x, _pp), _pp), addmod(mulmod(_x, _aa, _pp), _bb, _pp), _pp); y2 = expMod(y2, (_pp + 1) / 4, _pp); // uint256 cmp = yBit ^ y_ & 1; uint256 y = (y2 + _prefix) % 2 == 0 ? y2 : _pp - y2; return y; } /// @dev Check whether point (x,y) is on curve defined by a, b, and _pp. /// @param _x coordinate x of P1 /// @param _y coordinate y of P1 /// @param _aa constant of curve /// @param _bb constant of curve /// @param _pp the modulus /// @return true if x,y in the curve, false else function isOnCurve( uint _x, uint _y, uint _aa, uint _bb, uint _pp) internal pure returns (bool) { if (0 == _x || _x >= _pp || 0 == _y || _y >= _pp) { return false; } // y^2 uint lhs = mulmod(_y, _y, _pp); // x^3 uint rhs = mulmod(mulmod(_x, _x, _pp), _x, _pp); if (_aa != 0) { // x^3 + a*x rhs = addmod(rhs, mulmod(_x, _aa, _pp), _pp); } if (_bb != 0) { // x^3 + a*x + b rhs = addmod(rhs, _bb, _pp); } return lhs == rhs; } /// @dev Calculate inverse (x, -y) of point (x, y). /// @param _x coordinate x of P1 /// @param _y coordinate y of P1 /// @param _pp the modulus /// @return (x, -y) function ecInv( uint256 _x, uint256 _y, uint256 _pp) internal pure returns (uint256, uint256) { return (_x, (_pp - _y) % _pp); } /// @dev Add two points (x1, y1) and (x2, y2) in affine coordinates. /// @param _x1 coordinate x of P1 /// @param _y1 coordinate y of P1 /// @param _x2 coordinate x of P2 /// @param _y2 coordinate y of P2 /// @param _aa constant of the curve /// @param _pp the modulus /// @return (qx, qy) = P1+P2 in affine coordinates function ecAdd( uint256 _x1, uint256 _y1, uint256 _x2, uint256 _y2, uint256 _aa, uint256 _pp) internal pure returns(uint256, uint256) { uint x = 0; uint y = 0; uint z = 0; // Double if x1==x2 else add if (_x1==_x2) { // y1 = -y2 mod p if (addmod(_y1, _y2, _pp) == 0) { return(0, 0); } else { // P1 = P2 (x, y, z) = jacDouble( _x1, _y1, 1, _aa, _pp); } } else { (x, y, z) = jacAdd( _x1, _y1, 1, _x2, _y2, 1, _pp); } // Get back to affine return toAffine( x, y, z, _pp); } /// @dev Substract two points (x1, y1) and (x2, y2) in affine coordinates. /// @param _x1 coordinate x of P1 /// @param _y1 coordinate y of P1 /// @param _x2 coordinate x of P2 /// @param _y2 coordinate y of P2 /// @param _aa constant of the curve /// @param _pp the modulus /// @return (qx, qy) = P1-P2 in affine coordinates function ecSub( uint256 _x1, uint256 _y1, uint256 _x2, uint256 _y2, uint256 _aa, uint256 _pp) internal pure returns(uint256, uint256) { // invert square (uint256 x, uint256 y) = ecInv(_x2, _y2, _pp); // P1-square return ecAdd( _x1, _y1, x, y, _aa, _pp); } /// @dev Multiply point (x1, y1, z1) times d in affine coordinates. /// @param _k scalar to multiply /// @param _x coordinate x of P1 /// @param _y coordinate y of P1 /// @param _aa constant of the curve /// @param _pp the modulus /// @return (qx, qy) = d*P in affine coordinates function ecMul( uint256 _k, uint256 _x, uint256 _y, uint256 _aa, uint256 _pp) internal pure returns(uint256, uint256) { // Jacobian multiplication (uint256 x1, uint256 y1, uint256 z1) = jacMul( _k, _x, _y, 1, _aa, _pp); // Get back to affine return toAffine( x1, y1, z1, _pp); } /// @dev Adds two points (x1, y1, z1) and (x2 y2, z2). /// @param _x1 coordinate x of P1 /// @param _y1 coordinate y of P1 /// @param _z1 coordinate z of P1 /// @param _x2 coordinate x of square /// @param _y2 coordinate y of square /// @param _z2 coordinate z of square /// @param _pp the modulus /// @return (qx, qy, qz) P1+square in Jacobian function jacAdd( uint256 _x1, uint256 _y1, uint256 _z1, uint256 _x2, uint256 _y2, uint256 _z2, uint256 _pp) internal pure returns (uint256, uint256, uint256) { if (_x1==0 && _y1==0) return (_x2, _y2, _z2); if (_x2==0 && _y2==0) return (_x1, _y1, _z1); // We follow the equations described in https://pdfs.semanticscholar.org/5c64/29952e08025a9649c2b0ba32518e9a7fb5c2.pdf Section 5 uint[4] memory zs; // z1^2, z1^3, z2^2, z2^3 zs[0] = mulmod(_z1, _z1, _pp); zs[1] = mulmod(_z1, zs[0], _pp); zs[2] = mulmod(_z2, _z2, _pp); zs[3] = mulmod(_z2, zs[2], _pp); // u1, s1, u2, s2 zs = [ mulmod(_x1, zs[2], _pp), mulmod(_y1, zs[3], _pp), mulmod(_x2, zs[0], _pp), mulmod(_y2, zs[1], _pp) ]; // In case of zs[0] == zs[2] && zs[1] == zs[3], double function should be used require(zs[0] != zs[2] || zs[1] != zs[3], "Use jacDouble function instead"); uint[4] memory hr; //h hr[0] = addmod(zs[2], _pp - zs[0], _pp); //r hr[1] = addmod(zs[3], _pp - zs[1], _pp); //h^2 hr[2] = mulmod(hr[0], hr[0], _pp); // h^3 hr[3] = mulmod(hr[2], hr[0], _pp); // qx = -h^3 -2u1h^2+r^2 uint256 qx = addmod(mulmod(hr[1], hr[1], _pp), _pp - hr[3], _pp); qx = addmod(qx, _pp - mulmod(2, mulmod(zs[0], hr[2], _pp), _pp), _pp); // qy = -s1*z1*h^3+r(u1*h^2 -x^3) uint256 qy = mulmod(hr[1], addmod(mulmod(zs[0], hr[2], _pp), _pp - qx, _pp), _pp); qy = addmod(qy, _pp - mulmod(zs[1], hr[3], _pp), _pp); // qz = h*z1*z2 uint256 qz = mulmod(hr[0], mulmod(_z1, _z2, _pp), _pp); return(qx, qy, qz); } /// @dev Doubles a points (x, y, z). /// @param _x coordinate x of P1 /// @param _y coordinate y of P1 /// @param _z coordinate z of P1 /// @param _aa the a scalar in the curve equation /// @param _pp the modulus /// @return (qx, qy, qz) 2P in Jacobian function jacDouble( uint256 _x, uint256 _y, uint256 _z, uint256 _aa, uint256 _pp) internal pure returns (uint256, uint256, uint256) { if (_z == 0) return (_x, _y, _z); // We follow the equations described in https://pdfs.semanticscholar.org/5c64/29952e08025a9649c2b0ba32518e9a7fb5c2.pdf Section 5 // Note: there is a bug in the paper regarding the m parameter, M=3*(x1^2)+a*(z1^4) // x, y, z at this point represent the squares of _x, _y, _z uint256 x = mulmod(_x, _x, _pp); //x1^2 uint256 y = mulmod(_y, _y, _pp); //y1^2 uint256 z = mulmod(_z, _z, _pp); //z1^2 // s uint s = mulmod(4, mulmod(_x, y, _pp), _pp); // m uint m = addmod(mulmod(3, x, _pp), mulmod(_aa, mulmod(z, z, _pp), _pp), _pp); // x, y, z at this point will be reassigned and rather represent qx, qy, qz from the paper // This allows to reduce the gas cost and stack footprint of the algorithm // qx x = addmod(mulmod(m, m, _pp), _pp - addmod(s, s, _pp), _pp); // qy = -8*y1^4 + M(S-T) y = addmod(mulmod(m, addmod(s, _pp - x, _pp), _pp), _pp - mulmod(8, mulmod(y, y, _pp), _pp), _pp); // qz = 2*y1*z1 z = mulmod(2, mulmod(_y, _z, _pp), _pp); return (x, y, z); } /// @dev Multiply point (x, y, z) times d. /// @param _d scalar to multiply /// @param _x coordinate x of P1 /// @param _y coordinate y of P1 /// @param _z coordinate z of P1 /// @param _aa constant of curve /// @param _pp the modulus /// @return (qx, qy, qz) d*P1 in Jacobian function jacMul( uint256 _d, uint256 _x, uint256 _y, uint256 _z, uint256 _aa, uint256 _pp) internal pure returns (uint256, uint256, uint256) { // Early return in case that `_d == 0` if (_d == 0) { return (_x, _y, _z); } uint256 remaining = _d; uint256 qx = 0; uint256 qy = 0; uint256 qz = 1; // Double and add algorithm while (remaining != 0) { if ((remaining & 1) != 0) { (qx, qy, qz) = jacAdd( qx, qy, qz, _x, _y, _z, _pp); } remaining = remaining / 2; (_x, _y, _z) = jacDouble( _x, _y, _z, _aa, _pp); } return (qx, qy, qz); } }
{ "remappings": [ "ERC4626/=lib/ERC4626/src/", "base58-solidity/=lib/base58-solidity/contracts/", "bip340-solidity/=lib/bip340-solidity/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin/=lib/openzeppelin-contracts/contracts/", "solmate/=lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
[{"inputs":[{"internalType":"enum BitcoinUtils.Network","name":"_network","type":"uint8"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_btcDepositId","type":"bytes32"}],"name":"MintBtcEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"string","name":"_BTCAddress","type":"string"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_id","type":"uint256"}],"name":"RedeemBtcEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"bytes1","name":"char","type":"bytes1"}],"name":"BECH32_ALPHABET_MAP","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DUST_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"BTCAddress","type":"bytes"}],"name":"alphabetCheck","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"btcDepositIds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"one","type":"bytes"},{"internalType":"bytes","name":"two","type":"bytes"}],"name":"equalBytes","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"enum BitcoinUtils.Network","name":"network","type":"uint8"}],"name":"getBtcBech32Prefix","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"btcDepositId","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct MintInvoice","name":"invoice","type":"tuple"}],"name":"getMintInvoiceHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_validatorPublicKey","type":"bytes32"}],"name":"getUpdateValidatorPublicKeyMessage","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"minWithdrawAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"bytes32","name":"_btcDepositId","type":"bytes32"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"btcDepositId","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct MintInvoice","name":"invoice","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"network","outputs":[{"internalType":"enum BitcoinUtils.Network","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"pre","type":"uint256"}],"name":"polymodStep","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"prefix","type":"bytes"}],"name":"prefixChk","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"string","name":"BTCAddress","type":"string"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redeemCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minWithdrawAmount","type":"uint256"}],"name":"setMinWithdrawAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"setMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_validatorPublicKey","type":"bytes32"}],"name":"setValidatorPublicKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_validatorPublicKey","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"setValidatorPublicKeySigned","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"btcAddress","type":"string"}],"name":"validateBase58Checksum","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"btcAddress","type":"string"}],"name":"validateBech32Checksum","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum BitcoinUtils.Network","name":"network","type":"uint8"},{"internalType":"string","name":"BTCAddress","type":"string"}],"name":"validateBitcoinAddress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"validateMessage","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"validatorPublicKey","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"px","type":"uint256"},{"internalType":"uint256","name":"rx","type":"uint256"},{"internalType":"uint256","name":"s","type":"uint256"},{"internalType":"bytes32","name":"m","type":"bytes32"}],"name":"verify","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}]
Contract Creation Code
60e0604052620186a06009553480156200001857600080fd5b506040516200440b3803806200440b8339810160408190526200003b9162000207565b6040518060400160405280600e81526020016d29ba3937b7b6902134ba31b7b4b760911b81525060405180604001604052806005815260200164737442544360d81b81525060088260009081620000939190620002d6565b506001620000a28382620002d6565b5060ff81166080524660a052620000b862000119565b60c05250620000cb9150339050620001b5565b6008805460ff19811682556000600a5582919061ffff1916610100836002811115620000fb57620000fb620003a2565b021790555050600b80546001600160a01b0319163317905562000436565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60006040516200014d9190620003b8565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000602082840312156200021a57600080fd5b8151600381106200022a57600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200025c57607f821691505b6020821081036200027d57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002d157600081815260208120601f850160051c81016020861015620002ac5750805b601f850160051c820191505b81811015620002cd57828155600101620002b8565b5050505b505050565b81516001600160401b03811115620002f257620002f262000231565b6200030a8162000303845462000247565b8462000283565b602080601f831160018114620003425760008415620003295750858301515b600019600386901b1c1916600185901b178555620002cd565b600085815260208120601f198616915b82811015620003735788860151825594840194600190910190840162000352565b5085821015620003925787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052602160045260246000fd5b6000808354620003c88162000247565b60018281168015620003e35760018114620003f9576200042a565b60ff19841687528215158302870194506200042a565b8760005260208060002060005b85811015620004215781548a82015290840190820162000406565b50505082870194505b50929695505050505050565b60805160a05160c051613fa5620004666000396000610daf01526000610d7a0152600061038c0152613fa56000f3fe608060405234801561001057600080fd5b506004361061027f5760003560e01c8063780f8df31161015c578063a9059cbb116100ce578063d9ab380111610087578063d9ab380114610591578063dd62ed3e146105a4578063e07fbd00146105cf578063f2fde38b146105e2578063f9a8bc48146105f5578063fca3b5aa1461060857600080fd5b8063a9059cbb1461051f578063af7b817014610532578063b35fc44e14610545578063d354c65d14610558578063d3b6d7f51461056b578063d505accf1461057e57600080fd5b80638da5cb5b116101205780638da5cb5b146104ce57806395d89b41146104df5780639647ea37146104e757806399f4a506146104fa5780639fd9568714610503578063a7ce45651461051657600080fd5b8063780f8df31461046d5780637b8d3cb4146104805780637ecebe001461049357806380cf79c8146104b35780638456cb59146104c657600080fd5b80633644e515116101f55780634cac70ff116101b95780634cac70ff146103f55780635abdb0dc146104085780635c975abb1461041b5780636739afca1461042657806370a0823114610445578063715018a61461046557600080fd5b80633644e515146103c05780633cc85e79146103c85780633f4ba83a146103db57806342193473146103e3578063457e1a49146103ec57600080fd5b80630b2aeb6c116102475780630b2aeb6c146103245780630fde6e551461033757806318160ddd1461034a57806323b872dd1461036157806324b76fd514610374578063313ce5671461038757600080fd5b8063026034f0146102845780630356b1a5146102bc57806306fdde03146102d157806307546172146102e6578063095ea7b314610311575b600080fd5b6102a7610292366004613663565b600c6020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6102cf6102ca366004613663565b61061b565b005b6102d9610628565b6040516102b391906136cc565b600b546102f9906001600160a01b031681565b6040516001600160a01b0390911681526020016102b3565b6102a761031f3660046136f6565b6106b6565b6102a7610332366004613770565b610723565b6102a76103453660046137c2565b6109d5565b61035360025481565b6040519081526020016102b3565b6102a761036f3660046137f4565b610b3d565b6102cf610382366004613830565b610c1d565b6103ae7f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff90911681526020016102b3565b610353610d76565b6102cf6103d6366004613830565b610dd1565b6102cf610e10565b61035361022281565b61035360095481565b6102a761040336600461390d565b610e22565b6102cf610416366004613663565b610eb4565b60085460ff166102a7565b60085461043890610100900460ff1681565b6040516102b39190613986565b6103536104533660046139ae565b60036020526000908152604090205481565b6102cf610f39565b6102cf61047b3660046139c9565b610f4b565b6103ae61048e3660046139ee565b610fc8565b6103536104a13660046139ae565b60056020526000908152604090205481565b6103536104c1366004613663565b6113ad565b6102cf61146d565b6006546001600160a01b03166102f9565b6102d961147d565b6102a76104f5366004613a18565b61148a565b61035360075481565b6102cf610511366004613a71565b6119d4565b610353600a5481565b6102a761052d3660046136f6565b611a34565b6102a7610540366004613aab565b611a9a565b610353610553366004613663565b611b00565b6102a7610566366004613adf565b611b67565b610353610579366004613aab565b6121c0565b6102cf61058c366004613b27565b6122bc565b6102d961059f366004613b9a565b612500565b6103536105b2366004613bb5565b600460209081526000928352604080842090915290825290205481565b6103536105dd366004613be8565b6125f0565b6102cf6105f03660046139ae565b6125fb565b6102a7610603366004613830565b612674565b6102cf6106163660046139ae565b612731565b61062361275b565b600755565b6000805461063590613c04565b80601f016020809104026020016040519081016040528092919081815260200182805461066190613c04565b80156106ae5780601f10610683576101008083540402835291602001916106ae565b820191906000526020600020905b81548152906001019060200180831161069157829003601f168201915b505050505081565b3360008181526004602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906107119086815260200190565b60405180910390a35060015b92915050565b6000606061076884848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250859250610e22915050565b156107775760009150506109ce565b6107db610788600160008688613c38565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260018152603160f81b60208201529150610e229050565b8061084557506108456107f2600160008688613c38565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260018152603360f81b60208201529150610e229050565b156108c157601a8310806108595750602383115b806108a0575061089e84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a9a92505050565b155b156108af5760009150506109ce565b6108b9848461148a565b9150506109ce565b60006108cc86612500565b805190915061091e906108e29060008789613c38565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250859250610e22915050565b156109c757600286600281111561093757610937613970565b0361096057602b84108061094b5750603f84115b1561095b576000925050506109ce565b61097f565b602a84108061096f5750603e84115b1561097f576000925050506109ce565b6109be85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b6792505050565b925050506109ce565b6000925050505b9392505050565b60006401000003d019851015806109f257506401000003d0198410155b80610a0f575070014551231950b75fc4402da1732fc9bebe198310155b15610a1c57506000610b35565b600080610a28866127b5565b9150915080610a3c57600092505050610b35565b6000610a49878987612810565b9050600070014551231950b75fc4402da1732fc9bebe19898809610a7f9070014551231950b75fc4402da1732fc9bebe19613c8e565b9050600070014551231950b75fc4402da1732fc9bebe198a8409610ab59070014551231950b75fc4402da1732fc9bebe19613c8e565b60408051600080825260208201808452869052601b92820192909252606081018d9052608081018390529192509060019060a0016020604051602081039080840390855afa158015610b0b573d6000803e3d6000fd5b505050602060405103519050856001600160a01b0316816001600160a01b03161496505050505050505b949350505050565b6001600160a01b03831660009081526004602090815260408083203384529091528120546000198114610b9957610b748382613c8e565b6001600160a01b03861660009081526004602090815260408083203384529091529020555b6001600160a01b03851660009081526003602052604081208054859290610bc1908490613c8e565b90915550506001600160a01b0380851660008181526003602052604090819020805487019055519091871690600080516020613f1683398151915290610c0a9087815260200190565b60405180910390a3506001949350505050565b610c256128e2565b600954831015610ca25760405162461bcd60e51b815260206004820152603e60248201527f5468652073656e742076616c7565206d7573742062652067726561746572206f60448201527f7220657175616c20746f206d696e20776974686472617720616d6f756e74000060648201526084015b60405180910390fd5b600854610cb890610100900460ff168383610723565b610d0e5760405162461bcd60e51b815260206004820152602160248201527f5468652073656e74204254432061646472657373206973206e6f742076616c696044820152601960fa1b6064820152608401610c99565b610d183384612928565b6001600a6000828254610d2b9190613ca1565b9091555050600a5460405133917f83c16822c691a011b471d2653b84faff158a050c4e117390a6c008ecdefcc14e91610d6991869186918991613cb4565b60405180910390a2505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610dac57610da7612992565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b610dda83611b00565b8282610de7838383612674565b610e035760405162461bcd60e51b8152600401610c9990613cf4565b5050506007929092555050565b610e1861275b565b610e20612a2c565b565b60008151835114610e355750600061071d565b60005b8351811015610eaa57828181518110610e5357610e53613d3f565b602001015160f81c60f81b6001600160f81b031916848281518110610e7a57610e7a613d3f565b01602001516001600160f81b03191614610e9857600091505061071d565b80610ea281613d55565b915050610e38565b5060019392505050565b610ebc61275b565b610222811015610f345760405162461bcd60e51b815260206004820152603c60248201527f4d696e20776974686472617720616d6f756e742073686f756c6420626520677260448201527f6561746572206f7220657175616c20746f2064757374206c696d6974000000006064820152608401610c99565b600955565b610f4161275b565b610e206000612a7e565b610f536128e2565b600b546001600160a01b03163314610fb85760405162461bcd60e51b815260206004820152602260248201527f6c6e4254433a206f6e6c79206d696e74657220616c6c6f77656420746f206d696044820152611b9d60f21b6064820152608401610c99565b610fc3838383612ad0565b505050565b6000600d60fc1b6001600160f81b0319831601610fe75750600f919050565b606760f91b6001600160f81b03198316016110045750600a919050565b60cd60f81b6001600160f81b031983160161102157506011919050565b603360fa1b6001600160f81b031983160161103e57506015919050565b60cb60f81b6001600160f81b031983160161105b57506014919050565b606560f91b6001600160f81b03198316016110785750601a919050565b601960fb1b6001600160f81b031983160161109557506007919050565b60c960f81b6001600160f81b03198316016110b25750601e919050565b60c760f81b6001600160f81b03198316016110cf57506005919050565b608f60f81b6001600160f81b03198316016110ec57506000919050565b600960fc1b6001600160f81b031983160161110957506001919050565b604360f91b6001600160f81b031983160161112657506002919050565b604760f91b6001600160f81b031983160161114357506003919050565b608760f81b6001600160f81b031983160161116057506004919050565b601160fb1b6001600160f81b031983160161117d57506006919050565b609960f81b6001600160f81b031983160161119a57506008919050565b604d60f91b6001600160f81b03198316016111b757506009919050565b602360fa1b6001600160f81b03198316016111d45750600b919050565b604560f91b6001600160f81b03198316016111f15750600c919050565b602760fa1b6001600160f81b031983160161120e5750600d919050565b608960f81b6001600160f81b031983160161122b5750600e919050565b608d60f81b6001600160f81b031983160161124857506010919050565b604b60f91b6001600160f81b031983160161126557506012919050565b604960f91b6001600160f81b031983160161128257506013919050565b609560f81b6001600160f81b031983160161129f57506016919050565b601360fb1b6001600160f81b03198316016112bc57506017919050565b609d60f81b6001600160f81b03198316016112d957506018919050565b609b60f81b6001600160f81b03198316016112f657506019919050565b609360f81b6001600160f81b03198316016113135750601b919050565b608b60f81b6001600160f81b03198316016113305750601c919050565b609f60f81b6001600160f81b031983160161134d5750601d919050565b602560fa1b6001600160f81b031983160161136a5750601f919050565b61139c6040518060400160405280601181526020017024b73b30b634b21031b430b930b1ba32b960791b815250612c7d565b6113a582612cc0565b5060ff919050565b6000601982901c6001601d84901c8116146113c95760006113cf565b632a1462b35b63ffffffff16600382901c6001166001146113eb5760006113f1565b633d4233dd5b63ffffffff16600283901c60011660011461140d576000611413565b631ea119fa5b63ffffffff16600184811c81161461142c576000611432565b6326508e6d5b63ffffffff1660018086161461144957600061144f565b633b6a57b25b63ffffffff166005886301ffffff16901b1818181818915050919050565b61147561275b565b610e20612d09565b6001805461063590613c04565b6000806114cc84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d4692505050565b90506115056040518060400160405280601681526020017576616c6964617465426173653538436865636b73756d60501b815250612c7d565b61152d604051806040016040528060078152602001661c185e5b1bd85960ca1b815250612c7d565b61153681612d51565b805160191461154957600091505061071d565b6040805160018082528183019092526000916020820181803683370190505090508160008151811061157d5761157d613d3f565b602001015160f81c60f81b8160008151811061159b5761159b613d3f565b60200101906001600160f81b031916908160001a9053506115da604051806040016040528060078152602001663b32b939b4b7b760c91b815250612c7d565b6115e381612d51565b60006004600184516115f59190613c8e565b6115ff9190613c8e565b6001600160401b0381111561161657611616613862565b6040519080825280601f01601f191660200182016040528015611640576020820181803683370190505b50905060005b6004600185516116569190613c8e565b6116609190613c8e565b8110156116c95783611673826001613ca1565b8151811061168357611683613d3f565b602001015160f81c60f81b8282815181106116a0576116a0613d3f565b60200101906001600160f81b031916908160001a905350806116c181613d55565b915050611646565b506116f2604051806040016040528060078152602001661c185e5b1bd85960ca1b815250612c7d565b6116fb81612d51565b8051601414611710576000935050505061071d565b60408051600480825281830190925260009160208201818036833701905050905060005b60048110156117ad5784816004875161174d9190613c8e565b6117579190613ca1565b8151811061176757611767613d3f565b602001015160f81c60f81b82828151811061178457611784613d3f565b60200101906001600160f81b031916908160001a905350806117a581613d55565b915050611734565b506117d760405180604001604052806008815260200167636865636b73756d60c01b815250612c7d565b6117e081612d51565b600060028085856040516020016117f8929190613d6e565b60408051601f198184030181529082905261181291613d9d565b602060405180830381855afa15801561182f573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906118529190613db9565b60405160200161186491815260200190565b60408051601f198184030181529082905261187e91613d9d565b602060405180830381855afa15801561189b573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906118be9190613db9565b90506118f46040518060400160405280601381526020017263616c63756c6174656420636865636b73756d60681b815250612c7d565b6118fd81612d94565b8060031a60f81b8260038151811061191757611917613d3f565b01602001516001600160f81b031916188160021a60f81b8360028151811061194157611941613d3f565b01602001516001600160f81b031916188260011a60f81b8460018151811061196b5761196b613d3f565b01602001516001600160f81b031916188360001a60f81b8560008151811061199557611995613d3f565b602001015160f81c60f81b181717176001600160f81b031916600060f81b146119c65760009550505050505061071d565b506001979650505050505050565b6119dc6128e2565b6119e5836125f0565b82826119f2838383612674565b611a0e5760405162461bcd60e51b8152600401610c9990613cf4565b611a2c60408701803590611a259060208a016139ae565b8835612ad0565b505050505050565b33600090815260036020526040812080548391908390611a55908490613c8e565b90915550506001600160a01b03831660008181526003602052604090819020805485019055513390600080516020613f16833981519152906107119086815260200190565b6000805b8251811015611af7576000838281518110611abb57611abb613d3f565b016020015160f81c90506000611ad082612dd9565b905080611ae257506000949350505050565b50508080611aef90613d55565b915050611a9e565b50600192915050565b600081604051602001611b4a91907f5354524f4f4d5f5550444154455f56414c494441544f525f5055424c49435f4b815261455960f01b6020820152602281019190915260420190565b604051602081830303815290604052805190602001209050919050565b6000611ba76040518060400160405280601981526020017f0a76616c69646174652062656368333220636865636b73756d00000000000000815250612c7d565b611bcf604051806040016040528060078152602001666164647265737360c81b815250612c7d565b611bd882612c7d565b8151829060081115611c1757611c0e604051806040016040528060098152602001681d1bdbc81cda1bdc9d60ba1b815250612c7d565b50600092915050565b605a81511115611c4a57611c0e60405180604001604052806008815260200167746f6f206c6f6e6760c01b815250612c7d565b50816000805b8251811015611c9e57828181518110611c6b57611c6b613d3f565b01602001516001600160f81b031916603160f81b03611c8c57809150611c9e565b80611c9681613d55565b915050611c50565b5080600003611cde57611cd46040518060400160405280600c81526020016b37379039b2b830b930ba37b960a11b815250612c7d565b5060009392505050565b80600103611d1557611cd46040518060400160405280600e81526020016d0dad2e6e6d2dcce40e0e4caccd2f60931b815250612c7d565b6000816001600160401b03811115611d2f57611d2f613862565b6040519080825280601f01601f191660200182016040528015611d59576020820181803683370190505b50905060006001838551611d6d9190613c8e565b611d779190613c8e565b6001600160401b03811115611d8e57611d8e613862565b6040519080825280601f01601f191660200182016040528015611db8576020820181803683370190505b50905060005b83811015611e1e57848181518110611dd857611dd8613d3f565b602001015160f81c60f81b838281518110611df557611df5613d3f565b60200101906001600160f81b031916908160001a90535080611e1681613d55565b915050611dbe565b5060005b8151811015611e975784611e368583613ca1565b611e41906001613ca1565b81518110611e5157611e51613d3f565b602001015160f81c60f81b828281518110611e6e57611e6e613d3f565b60200101906001600160f81b031916908160001a90535080611e8f81613d55565b915050611e22565b50611ebf604051806040016040528060068152602001650e0e4caccd2f60d31b815250612c7d565b611ec882612d51565b600681511015611f0d57611f016040518060400160405280600e81526020016d19185d18481d1bdbc81cda1bdc9d60921b815250612c7d565b50600095945050505050565b6000611f18836121c0565b905080600003611f5e57611f516040518060400160405280600e81526020016d0d2dcecc2d8d2c840e0e4caccd2f60931b815250612c7d565b5060009695505050505050565b600082516001600160401b03811115611f7957611f79613862565b6040519080825280601f01601f191660200182016040528015611fa3576020820181803683370190505b50905060005b8351811015612106576000848281518110611fc657611fc6613d3f565b01602001516001600160f81b03191690506000611fe282610fc8565b905060fe1960ff82160161209a57612022604051806040016040528060118152602001703ab735b737bbb71031b430b930b1ba32b960791b815250612c7d565b61202b83612e82565b61203482612cc0565b6120896040518060400160405280600481526020016331b430b960e11b8152508360405160200161207591906001600160f81b031991909116815260010190565b604051602081830303815290604052612ec7565b5060009a9950505050505050505050565b8060ff166120a7866113ad565b8751911895506120b8846006613ca1565b106120c45750506120f4565b8060f81b8484815181106120da576120da613d3f565b60200101906001600160f81b031916908160001a90535050505b806120fe81613d55565b915050611fa9565b5061212d60405180604001604052806005815260200164776f72647360d81b815250612c7d565b61213681612d51565b632bc830a3821415801561214b575081600114155b15612190576121826040518060400160405280601081526020016f696e76616c696420636865636b73756d60801b81525083612f10565b506000979650505050505050565b6119c66040518060400160405280600e81526020016d76616c696420636865636b73756d60901b81525083612f10565b60006001815b835181101561225d5760008482815181106121e3576121e3613d3f565b016020015160f81c905060218110806121fc5750607e81115b1561223a5760405162461bcd60e51b815260206004820152600e60248201526d092dcecc2d8d2c840e0e4caccd2f60931b6044820152606401610c99565b600581901c612248846113ad565b189250508061225690613d55565b90506121c6565b50612267816113ad565b905060005b83518110156122b557600084828151811061228957612289613d3f565b016020015160f81c9050601f81166122a0846113ad565b18925050806122ae90613d55565b905061226c565b5092915050565b4284101561230c5760405162461bcd60e51b815260206004820152601760248201527f5045524d49545f444541444c494e455f455850495245440000000000000000006044820152606401610c99565b60006001612318610d76565b6001600160a01b038a811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e08301909152805192019190912061190160f01b6101008301526101028201929092526101228101919091526101420160408051601f198184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015612424573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580159061245a5750876001600160a01b0316816001600160a01b0316145b6124975760405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa9a4a3a722a960911b6044820152606401610c99565b6001600160a01b0390811660009081526004602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b6060600082600281111561251657612516613970565b0361253a57505060408051808201909152600381526262633160e81b602082015290565b600282600281111561254e5761254e613970565b03612574575050604080518082019091526005815264626372743160d81b602082015290565b600182600281111561258857612588613970565b036125ac57505060408051808201909152600381526274623160e81b602082015290565b60405162461bcd60e51b8152602060048201526014602482015273556e6b6e6f776e206e6574776f726b207479706560601b6044820152606401610c99565b919050565b600061071d82612f55565b61260361275b565b6001600160a01b0381166126685760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c99565b61267181612a7e565b50565b60075460009081036126e25760405162461bcd60e51b815260206004820152603160248201527f56616c696461746f724d65737361676552656365697665723a204e4f5f56414c604482015270494441544f525f5055424c49435f4b455960781b6064820152608401610c99565b60006126f16020828587613c38565b6126fa91613dd2565b9050600061270c604060208688613c38565b61271591613dd2565b600754909150612727908383896109d5565b9695505050505050565b61273961275b565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b6006546001600160a01b03163314610e205760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c99565b6000806000806127c485612fc4565b91509150806127da575060009485945092505050565b50604080516020808201969096528082019290925280518083038201815260609092019052805193019290922092600192509050565b604080517f7bb52d7a9fef58323eb1bf7a407db382d2f3f2d81bb1224f49fe518f6d48d37c60208201819052918101829052606081018590526080810184905260a081018390526000919070014551231950b75fc4402da1732fc9bebe199060029060c00160408051601f198184030181529082905261288f91613d9d565b602060405180830381855afa1580156128ac573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906128cf9190613db9565b6128d99190613df0565b95945050505050565b60085460ff1615610e205760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610c99565b6001600160a01b03821660009081526003602052604081208054839290612950908490613c8e565b90915550506002805482900390556040518181526000906001600160a01b03841690600080516020613f16833981519152906020015b60405180910390a35050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60006040516129c49190613e04565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b612a34613089565b6008805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008311612b135760405162461bcd60e51b815260206004820152601060248201526f4d494e545f414d4f554e545f5a45524f60801b6044820152606401610c99565b612b256305f5e1006301406f40613ea3565b8310612b695760405162461bcd60e51b81526020600482015260136024820152724d494e545f414d4f554e545f544f4f5f42494760681b6044820152606401610c99565b306001600160a01b03831603612bc15760405162461bcd60e51b815260206004820152601c60248201527f4d494e545f544f5f5448455f434f4e54524143545f41444452455353000000006044820152606401610c99565b6000818152600c602052604090205460ff1615612c195760405162461bcd60e51b81526020600482015260166024820152751352539517d053149150511657d41493d0d154d4d15160521b6044820152606401610c99565b6000818152600c60205260409020805460ff19166001179055612c3c82846130d2565b60408051848152602081018390526001600160a01b038416917fb73f3e96d1e157f064cb3a8d0abed06bcec05e5515bf7486364c027dab6aa4699101610d69565b61267181604051602401612c9191906136cc565b60408051601f198184030181529190526020810180516001600160e01b031663104c13eb60e21b179052613124565b6040516001600160f81b0319821660248201526126719060440160408051601f198184030181529190526020810180516001600160e01b0316630dc3142560e31b179052613124565b612d116128e2565b6008805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612a613390565b606061071d82613145565b61267181604051602401612d6591906136cc565b60408051601f198184030181529190526020810180516001600160e01b03166305f3bfab60e11b179052613124565b61267181604051602401612daa91815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166327b7cf8560e01b179052613124565b60008160ff1660491480612df057508160ff16604f145b80612dfe57508160ff16606c145b15612e0b57506000919050565b60318260ff1610158015612e23575060398260ff1611155b15612e3057506001919050565b60418260ff1610158015612e485750605a8260ff1611155b15612e5557506001919050565b60618260ff1610158015612e6d5750607a8260ff1611155b15612e7a57506001919050565b506000919050565b61267181604051602401612e9891815260200190565b60408051601f198184030181529190526020810180516001600160e01b031663f5b1bba960e01b179052613124565b612f0c8282604051602401612edd929190613eba565b60408051601f198184030181529190526020810180516001600160e01b0316634b5c427760e01b179052613124565b5050565b612f0c8282604051602401612f26929190613edf565b60408051601f198184030181529190526020810180516001600160e01b03166309710a9d60e41b179052613124565b60007f7d21eae75cdfb1cf6d27ca9a73c6341b49bc05072228b51a7cd4df444c1c8710612f8860408401602085016139ae565b60408051602081019390935260609190911b6bffffffffffffffffffffffff191682820152830135605482015282356074820152609401611b4a565b6000806401000003d019816007828610612fe657506000958695509350505050565b60008380612ff657612ff6613c62565b848061300457613004613c62565b83868061301357613013613c62565b868b0908858061302557613025613c62565b868061303357613033613c62565b8a8b098a0908905061305c81600461304c876001613ca1565b6130569190613f01565b8661348f565b905060006001821615613078576130738286613c8e565b61307a565b815b98600198509650505050505050565b60085460ff16610e205760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610c99565b80600260008282546130e49190613ca1565b90915550506001600160a01b038216600081815260036020908152604080832080548601905551848152600080516020613f168339815191529101612986565b80516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b80516060906031906000805b828110801561317857508386828151811061316e5761316e613d3f565b016020015160f81c145b156131895760019182019101613151565b5060008080806117e361209f8702046001016002026001600160401b038111156131b5576131b5613862565b6040519080825280601f01601f1916602001820160405280156131df576020820181803683370190505b5090506000600460038801046001600160401b0381111561320257613202613862565b60405190808252806020026020018201604052801561322b578160200160208202803683370190505b50905060005b8a5181101561334d5760008b828151811061324e5761324e613d3f565b602001015160f81c60f81b905061327d6040518060600160405280603a8152602001613f36603a913982613558565b9096509450846132c65760405162461bcd60e51b81526020600482015260146024820152731a5b9d985b1a590818985cd94d4e08191a59da5d60621b6044820152606401610c99565b8251600019015b6000811261334357868482815181106132e8576132e8613d3f565b602002602001015163ffffffff16603a026001600160401b0316019750602088901c96508763ffffffff1684828151811061332557613325613d3f565b63ffffffff90921660209283029190910190910152600019016132cd565b5050600101613231565b50600860038816026001600160401b03811660000361336a575060205b600719016000805b8351811015613414575b6020836001600160401b0316101561340857826001600160401b03168482815181106133aa576133aa613d3f565b602002602001015163ffffffff16901c60f81b8583815181106133cf576133cf613d3f565b60200101906001600160f81b031916908160001a90535060019091019060086001600160401b038416106134085760088303925061337c565b60189250600101613372565b50875b845181101561347257600060f81b85828151811061343757613437613d3f565b01602001516001600160f81b031916111561346a57613459858a8303846135bb565b9d9c50505050505050505050505050565b600101613417565b5061347f846000836135bb565b9c9b505050505050505050505050565b6000816000036134d35760405162461bcd60e51b815260206004820152600f60248201526e4d6f64756c7573206973207a65726f60881b6044820152606401610c99565b836000036134e3575060006109ce565b826000036134f3575060016109ce565b6001600160ff1b5b801561354f57838186161515870a85848509099150836002820486161515870a85848509099150836004820486161515870a85848509099150836008820486161515870a85848509099150601090046134fb565b50949350505050565b60008060005b84518110156135ab57836001600160f81b03191685828151811061358457613584613d3f565b01602001516001600160f81b031916036135a3579150600190506135b4565b60010161355e565b50600080915091505b9250929050565b606060008383036001600160401b038111156135d9576135d9613862565b6040519080825280601f01601f191660200182016040528015613603576020820181803683370190505b50905060005b84840381101561354f57858582018151811061362757613627613d3f565b602001015160f81c60f81b82828151811061364457613644613d3f565b60200101906001600160f81b031916908160001a905350600101613609565b60006020828403121561367557600080fd5b5035919050565b60005b8381101561369757818101518382015260200161367f565b50506000910152565b600081518084526136b881602086016020860161367c565b601f01601f19169290920160200192915050565b6020815260006109ce60208301846136a0565b80356001600160a01b03811681146125eb57600080fd5b6000806040838503121561370957600080fd5b613712836136df565b946020939093013593505050565b8035600381106125eb57600080fd5b60008083601f84011261374157600080fd5b5081356001600160401b0381111561375857600080fd5b6020830191508360208285010111156135b457600080fd5b60008060006040848603121561378557600080fd5b61378e84613720565b925060208401356001600160401b038111156137a957600080fd5b6137b58682870161372f565b9497909650939450505050565b600080600080608085870312156137d857600080fd5b5050823594602084013594506040840135936060013592509050565b60008060006060848603121561380957600080fd5b613812846136df565b9250613820602085016136df565b9150604084013590509250925092565b60008060006040848603121561384557600080fd5b8335925060208401356001600160401b038111156137a957600080fd5b634e487b7160e01b600052604160045260246000fd5b60006001600160401b038084111561389257613892613862565b604051601f8501601f19908116603f011681019082821181831017156138ba576138ba613862565b816040528093508581528686860111156138d357600080fd5b858560208301376000602087830101525050509392505050565b600082601f8301126138fe57600080fd5b6109ce83833560208501613878565b6000806040838503121561392057600080fd5b82356001600160401b038082111561393757600080fd5b613943868387016138ed565b9350602085013591508082111561395957600080fd5b50613966858286016138ed565b9150509250929050565b634e487b7160e01b600052602160045260246000fd5b60208101600383106139a857634e487b7160e01b600052602160045260246000fd5b91905290565b6000602082840312156139c057600080fd5b6109ce826136df565b6000806000606084860312156139de57600080fd5b83359250613820602085016136df565b600060208284031215613a0057600080fd5b81356001600160f81b0319811681146109ce57600080fd5b60008060208385031215613a2b57600080fd5b82356001600160401b03811115613a4157600080fd5b613a4d8582860161372f565b90969095509350505050565b600060608284031215613a6b57600080fd5b50919050565b600080600060808486031215613a8657600080fd5b613a908585613a59565b925060608401356001600160401b038111156137a957600080fd5b600060208284031215613abd57600080fd5b81356001600160401b03811115613ad357600080fd5b610b35848285016138ed565b600060208284031215613af157600080fd5b81356001600160401b03811115613b0757600080fd5b8201601f81018413613b1857600080fd5b610b3584823560208401613878565b600080600080600080600060e0888a031215613b4257600080fd5b613b4b886136df565b9650613b59602089016136df565b95506040880135945060608801359350608088013560ff81168114613b7d57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600060208284031215613bac57600080fd5b6109ce82613720565b60008060408385031215613bc857600080fd5b613bd1836136df565b9150613bdf602084016136df565b90509250929050565b600060608284031215613bfa57600080fd5b6109ce8383613a59565b600181811c90821680613c1857607f821691505b602082108103613a6b57634e487b7160e01b600052602260045260246000fd5b60008085851115613c4857600080fd5b83861115613c5557600080fd5b5050820193919092039150565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8181038181111561071d5761071d613c78565b8082018082111561071d5761071d613c78565b606081528360608201528385608083013760006080858301015260006080601f19601f870116830101905083602083015282604083015295945050505050565b6020808252602b908201527f56616c696461746f724d65737361676552656365697665723a20494e56414c4960408201526a445f5349474e415455524560a81b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060018201613d6757613d67613c78565b5060010190565b60008351613d8081846020880161367c565b835190830190613d9481836020880161367c565b01949350505050565b60008251613daf81846020870161367c565b9190910192915050565b600060208284031215613dcb57600080fd5b5051919050565b8035602083101561071d57600019602084900360031b1b1692915050565b600082613dff57613dff613c62565b500690565b600080835481600182811c915080831680613e2057607f831692505b60208084108203613e3f57634e487b7160e01b86526022600452602486fd5b818015613e535760018114613e6857613e95565b60ff1986168952841515850289019650613e95565b60008a81526020902060005b86811015613e8d5781548b820152908501908301613e74565b505084890196505b509498975050505050505050565b808202811582820484141761071d5761071d613c78565b604081526000613ecd60408301856136a0565b82810360208401526128d981856136a0565b604081526000613ef260408301856136a0565b90508260208301529392505050565b600082613f1057613f10613c62565b50049056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef31323334353637383941424344454647484a4b4c4d4e505152535455565758595a6162636465666768696a6b6d6e6f707172737475767778797aa264697066735822122020caec933d9a13d787330ff7014afd1cebca57a4e7f475fd8eef0dc5d9b4847a64736f6c634300081300330000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061027f5760003560e01c8063780f8df31161015c578063a9059cbb116100ce578063d9ab380111610087578063d9ab380114610591578063dd62ed3e146105a4578063e07fbd00146105cf578063f2fde38b146105e2578063f9a8bc48146105f5578063fca3b5aa1461060857600080fd5b8063a9059cbb1461051f578063af7b817014610532578063b35fc44e14610545578063d354c65d14610558578063d3b6d7f51461056b578063d505accf1461057e57600080fd5b80638da5cb5b116101205780638da5cb5b146104ce57806395d89b41146104df5780639647ea37146104e757806399f4a506146104fa5780639fd9568714610503578063a7ce45651461051657600080fd5b8063780f8df31461046d5780637b8d3cb4146104805780637ecebe001461049357806380cf79c8146104b35780638456cb59146104c657600080fd5b80633644e515116101f55780634cac70ff116101b95780634cac70ff146103f55780635abdb0dc146104085780635c975abb1461041b5780636739afca1461042657806370a0823114610445578063715018a61461046557600080fd5b80633644e515146103c05780633cc85e79146103c85780633f4ba83a146103db57806342193473146103e3578063457e1a49146103ec57600080fd5b80630b2aeb6c116102475780630b2aeb6c146103245780630fde6e551461033757806318160ddd1461034a57806323b872dd1461036157806324b76fd514610374578063313ce5671461038757600080fd5b8063026034f0146102845780630356b1a5146102bc57806306fdde03146102d157806307546172146102e6578063095ea7b314610311575b600080fd5b6102a7610292366004613663565b600c6020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6102cf6102ca366004613663565b61061b565b005b6102d9610628565b6040516102b391906136cc565b600b546102f9906001600160a01b031681565b6040516001600160a01b0390911681526020016102b3565b6102a761031f3660046136f6565b6106b6565b6102a7610332366004613770565b610723565b6102a76103453660046137c2565b6109d5565b61035360025481565b6040519081526020016102b3565b6102a761036f3660046137f4565b610b3d565b6102cf610382366004613830565b610c1d565b6103ae7f000000000000000000000000000000000000000000000000000000000000000881565b60405160ff90911681526020016102b3565b610353610d76565b6102cf6103d6366004613830565b610dd1565b6102cf610e10565b61035361022281565b61035360095481565b6102a761040336600461390d565b610e22565b6102cf610416366004613663565b610eb4565b60085460ff166102a7565b60085461043890610100900460ff1681565b6040516102b39190613986565b6103536104533660046139ae565b60036020526000908152604090205481565b6102cf610f39565b6102cf61047b3660046139c9565b610f4b565b6103ae61048e3660046139ee565b610fc8565b6103536104a13660046139ae565b60056020526000908152604090205481565b6103536104c1366004613663565b6113ad565b6102cf61146d565b6006546001600160a01b03166102f9565b6102d961147d565b6102a76104f5366004613a18565b61148a565b61035360075481565b6102cf610511366004613a71565b6119d4565b610353600a5481565b6102a761052d3660046136f6565b611a34565b6102a7610540366004613aab565b611a9a565b610353610553366004613663565b611b00565b6102a7610566366004613adf565b611b67565b610353610579366004613aab565b6121c0565b6102cf61058c366004613b27565b6122bc565b6102d961059f366004613b9a565b612500565b6103536105b2366004613bb5565b600460209081526000928352604080842090915290825290205481565b6103536105dd366004613be8565b6125f0565b6102cf6105f03660046139ae565b6125fb565b6102a7610603366004613830565b612674565b6102cf6106163660046139ae565b612731565b61062361275b565b600755565b6000805461063590613c04565b80601f016020809104026020016040519081016040528092919081815260200182805461066190613c04565b80156106ae5780601f10610683576101008083540402835291602001916106ae565b820191906000526020600020905b81548152906001019060200180831161069157829003601f168201915b505050505081565b3360008181526004602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906107119086815260200190565b60405180910390a35060015b92915050565b6000606061076884848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250859250610e22915050565b156107775760009150506109ce565b6107db610788600160008688613c38565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260018152603160f81b60208201529150610e229050565b8061084557506108456107f2600160008688613c38565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260018152603360f81b60208201529150610e229050565b156108c157601a8310806108595750602383115b806108a0575061089e84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a9a92505050565b155b156108af5760009150506109ce565b6108b9848461148a565b9150506109ce565b60006108cc86612500565b805190915061091e906108e29060008789613c38565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250859250610e22915050565b156109c757600286600281111561093757610937613970565b0361096057602b84108061094b5750603f84115b1561095b576000925050506109ce565b61097f565b602a84108061096f5750603e84115b1561097f576000925050506109ce565b6109be85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b6792505050565b925050506109ce565b6000925050505b9392505050565b60006401000003d019851015806109f257506401000003d0198410155b80610a0f575070014551231950b75fc4402da1732fc9bebe198310155b15610a1c57506000610b35565b600080610a28866127b5565b9150915080610a3c57600092505050610b35565b6000610a49878987612810565b9050600070014551231950b75fc4402da1732fc9bebe19898809610a7f9070014551231950b75fc4402da1732fc9bebe19613c8e565b9050600070014551231950b75fc4402da1732fc9bebe198a8409610ab59070014551231950b75fc4402da1732fc9bebe19613c8e565b60408051600080825260208201808452869052601b92820192909252606081018d9052608081018390529192509060019060a0016020604051602081039080840390855afa158015610b0b573d6000803e3d6000fd5b505050602060405103519050856001600160a01b0316816001600160a01b03161496505050505050505b949350505050565b6001600160a01b03831660009081526004602090815260408083203384529091528120546000198114610b9957610b748382613c8e565b6001600160a01b03861660009081526004602090815260408083203384529091529020555b6001600160a01b03851660009081526003602052604081208054859290610bc1908490613c8e565b90915550506001600160a01b0380851660008181526003602052604090819020805487019055519091871690600080516020613f1683398151915290610c0a9087815260200190565b60405180910390a3506001949350505050565b610c256128e2565b600954831015610ca25760405162461bcd60e51b815260206004820152603e60248201527f5468652073656e742076616c7565206d7573742062652067726561746572206f60448201527f7220657175616c20746f206d696e20776974686472617720616d6f756e74000060648201526084015b60405180910390fd5b600854610cb890610100900460ff168383610723565b610d0e5760405162461bcd60e51b815260206004820152602160248201527f5468652073656e74204254432061646472657373206973206e6f742076616c696044820152601960fa1b6064820152608401610c99565b610d183384612928565b6001600a6000828254610d2b9190613ca1565b9091555050600a5460405133917f83c16822c691a011b471d2653b84faff158a050c4e117390a6c008ecdefcc14e91610d6991869186918991613cb4565b60405180910390a2505050565b60007f0000000000000000000000000000000000000000000000000000000000aa36a74614610dac57610da7612992565b905090565b507f2dbb407e29884e426f895ff7692f430b775109a98839b8d7483c39515b4428f090565b610dda83611b00565b8282610de7838383612674565b610e035760405162461bcd60e51b8152600401610c9990613cf4565b5050506007929092555050565b610e1861275b565b610e20612a2c565b565b60008151835114610e355750600061071d565b60005b8351811015610eaa57828181518110610e5357610e53613d3f565b602001015160f81c60f81b6001600160f81b031916848281518110610e7a57610e7a613d3f565b01602001516001600160f81b03191614610e9857600091505061071d565b80610ea281613d55565b915050610e38565b5060019392505050565b610ebc61275b565b610222811015610f345760405162461bcd60e51b815260206004820152603c60248201527f4d696e20776974686472617720616d6f756e742073686f756c6420626520677260448201527f6561746572206f7220657175616c20746f2064757374206c696d6974000000006064820152608401610c99565b600955565b610f4161275b565b610e206000612a7e565b610f536128e2565b600b546001600160a01b03163314610fb85760405162461bcd60e51b815260206004820152602260248201527f6c6e4254433a206f6e6c79206d696e74657220616c6c6f77656420746f206d696044820152611b9d60f21b6064820152608401610c99565b610fc3838383612ad0565b505050565b6000600d60fc1b6001600160f81b0319831601610fe75750600f919050565b606760f91b6001600160f81b03198316016110045750600a919050565b60cd60f81b6001600160f81b031983160161102157506011919050565b603360fa1b6001600160f81b031983160161103e57506015919050565b60cb60f81b6001600160f81b031983160161105b57506014919050565b606560f91b6001600160f81b03198316016110785750601a919050565b601960fb1b6001600160f81b031983160161109557506007919050565b60c960f81b6001600160f81b03198316016110b25750601e919050565b60c760f81b6001600160f81b03198316016110cf57506005919050565b608f60f81b6001600160f81b03198316016110ec57506000919050565b600960fc1b6001600160f81b031983160161110957506001919050565b604360f91b6001600160f81b031983160161112657506002919050565b604760f91b6001600160f81b031983160161114357506003919050565b608760f81b6001600160f81b031983160161116057506004919050565b601160fb1b6001600160f81b031983160161117d57506006919050565b609960f81b6001600160f81b031983160161119a57506008919050565b604d60f91b6001600160f81b03198316016111b757506009919050565b602360fa1b6001600160f81b03198316016111d45750600b919050565b604560f91b6001600160f81b03198316016111f15750600c919050565b602760fa1b6001600160f81b031983160161120e5750600d919050565b608960f81b6001600160f81b031983160161122b5750600e919050565b608d60f81b6001600160f81b031983160161124857506010919050565b604b60f91b6001600160f81b031983160161126557506012919050565b604960f91b6001600160f81b031983160161128257506013919050565b609560f81b6001600160f81b031983160161129f57506016919050565b601360fb1b6001600160f81b03198316016112bc57506017919050565b609d60f81b6001600160f81b03198316016112d957506018919050565b609b60f81b6001600160f81b03198316016112f657506019919050565b609360f81b6001600160f81b03198316016113135750601b919050565b608b60f81b6001600160f81b03198316016113305750601c919050565b609f60f81b6001600160f81b031983160161134d5750601d919050565b602560fa1b6001600160f81b031983160161136a5750601f919050565b61139c6040518060400160405280601181526020017024b73b30b634b21031b430b930b1ba32b960791b815250612c7d565b6113a582612cc0565b5060ff919050565b6000601982901c6001601d84901c8116146113c95760006113cf565b632a1462b35b63ffffffff16600382901c6001166001146113eb5760006113f1565b633d4233dd5b63ffffffff16600283901c60011660011461140d576000611413565b631ea119fa5b63ffffffff16600184811c81161461142c576000611432565b6326508e6d5b63ffffffff1660018086161461144957600061144f565b633b6a57b25b63ffffffff166005886301ffffff16901b1818181818915050919050565b61147561275b565b610e20612d09565b6001805461063590613c04565b6000806114cc84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d4692505050565b90506115056040518060400160405280601681526020017576616c6964617465426173653538436865636b73756d60501b815250612c7d565b61152d604051806040016040528060078152602001661c185e5b1bd85960ca1b815250612c7d565b61153681612d51565b805160191461154957600091505061071d565b6040805160018082528183019092526000916020820181803683370190505090508160008151811061157d5761157d613d3f565b602001015160f81c60f81b8160008151811061159b5761159b613d3f565b60200101906001600160f81b031916908160001a9053506115da604051806040016040528060078152602001663b32b939b4b7b760c91b815250612c7d565b6115e381612d51565b60006004600184516115f59190613c8e565b6115ff9190613c8e565b6001600160401b0381111561161657611616613862565b6040519080825280601f01601f191660200182016040528015611640576020820181803683370190505b50905060005b6004600185516116569190613c8e565b6116609190613c8e565b8110156116c95783611673826001613ca1565b8151811061168357611683613d3f565b602001015160f81c60f81b8282815181106116a0576116a0613d3f565b60200101906001600160f81b031916908160001a905350806116c181613d55565b915050611646565b506116f2604051806040016040528060078152602001661c185e5b1bd85960ca1b815250612c7d565b6116fb81612d51565b8051601414611710576000935050505061071d565b60408051600480825281830190925260009160208201818036833701905050905060005b60048110156117ad5784816004875161174d9190613c8e565b6117579190613ca1565b8151811061176757611767613d3f565b602001015160f81c60f81b82828151811061178457611784613d3f565b60200101906001600160f81b031916908160001a905350806117a581613d55565b915050611734565b506117d760405180604001604052806008815260200167636865636b73756d60c01b815250612c7d565b6117e081612d51565b600060028085856040516020016117f8929190613d6e565b60408051601f198184030181529082905261181291613d9d565b602060405180830381855afa15801561182f573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906118529190613db9565b60405160200161186491815260200190565b60408051601f198184030181529082905261187e91613d9d565b602060405180830381855afa15801561189b573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906118be9190613db9565b90506118f46040518060400160405280601381526020017263616c63756c6174656420636865636b73756d60681b815250612c7d565b6118fd81612d94565b8060031a60f81b8260038151811061191757611917613d3f565b01602001516001600160f81b031916188160021a60f81b8360028151811061194157611941613d3f565b01602001516001600160f81b031916188260011a60f81b8460018151811061196b5761196b613d3f565b01602001516001600160f81b031916188360001a60f81b8560008151811061199557611995613d3f565b602001015160f81c60f81b181717176001600160f81b031916600060f81b146119c65760009550505050505061071d565b506001979650505050505050565b6119dc6128e2565b6119e5836125f0565b82826119f2838383612674565b611a0e5760405162461bcd60e51b8152600401610c9990613cf4565b611a2c60408701803590611a259060208a016139ae565b8835612ad0565b505050505050565b33600090815260036020526040812080548391908390611a55908490613c8e565b90915550506001600160a01b03831660008181526003602052604090819020805485019055513390600080516020613f16833981519152906107119086815260200190565b6000805b8251811015611af7576000838281518110611abb57611abb613d3f565b016020015160f81c90506000611ad082612dd9565b905080611ae257506000949350505050565b50508080611aef90613d55565b915050611a9e565b50600192915050565b600081604051602001611b4a91907f5354524f4f4d5f5550444154455f56414c494441544f525f5055424c49435f4b815261455960f01b6020820152602281019190915260420190565b604051602081830303815290604052805190602001209050919050565b6000611ba76040518060400160405280601981526020017f0a76616c69646174652062656368333220636865636b73756d00000000000000815250612c7d565b611bcf604051806040016040528060078152602001666164647265737360c81b815250612c7d565b611bd882612c7d565b8151829060081115611c1757611c0e604051806040016040528060098152602001681d1bdbc81cda1bdc9d60ba1b815250612c7d565b50600092915050565b605a81511115611c4a57611c0e60405180604001604052806008815260200167746f6f206c6f6e6760c01b815250612c7d565b50816000805b8251811015611c9e57828181518110611c6b57611c6b613d3f565b01602001516001600160f81b031916603160f81b03611c8c57809150611c9e565b80611c9681613d55565b915050611c50565b5080600003611cde57611cd46040518060400160405280600c81526020016b37379039b2b830b930ba37b960a11b815250612c7d565b5060009392505050565b80600103611d1557611cd46040518060400160405280600e81526020016d0dad2e6e6d2dcce40e0e4caccd2f60931b815250612c7d565b6000816001600160401b03811115611d2f57611d2f613862565b6040519080825280601f01601f191660200182016040528015611d59576020820181803683370190505b50905060006001838551611d6d9190613c8e565b611d779190613c8e565b6001600160401b03811115611d8e57611d8e613862565b6040519080825280601f01601f191660200182016040528015611db8576020820181803683370190505b50905060005b83811015611e1e57848181518110611dd857611dd8613d3f565b602001015160f81c60f81b838281518110611df557611df5613d3f565b60200101906001600160f81b031916908160001a90535080611e1681613d55565b915050611dbe565b5060005b8151811015611e975784611e368583613ca1565b611e41906001613ca1565b81518110611e5157611e51613d3f565b602001015160f81c60f81b828281518110611e6e57611e6e613d3f565b60200101906001600160f81b031916908160001a90535080611e8f81613d55565b915050611e22565b50611ebf604051806040016040528060068152602001650e0e4caccd2f60d31b815250612c7d565b611ec882612d51565b600681511015611f0d57611f016040518060400160405280600e81526020016d19185d18481d1bdbc81cda1bdc9d60921b815250612c7d565b50600095945050505050565b6000611f18836121c0565b905080600003611f5e57611f516040518060400160405280600e81526020016d0d2dcecc2d8d2c840e0e4caccd2f60931b815250612c7d565b5060009695505050505050565b600082516001600160401b03811115611f7957611f79613862565b6040519080825280601f01601f191660200182016040528015611fa3576020820181803683370190505b50905060005b8351811015612106576000848281518110611fc657611fc6613d3f565b01602001516001600160f81b03191690506000611fe282610fc8565b905060fe1960ff82160161209a57612022604051806040016040528060118152602001703ab735b737bbb71031b430b930b1ba32b960791b815250612c7d565b61202b83612e82565b61203482612cc0565b6120896040518060400160405280600481526020016331b430b960e11b8152508360405160200161207591906001600160f81b031991909116815260010190565b604051602081830303815290604052612ec7565b5060009a9950505050505050505050565b8060ff166120a7866113ad565b8751911895506120b8846006613ca1565b106120c45750506120f4565b8060f81b8484815181106120da576120da613d3f565b60200101906001600160f81b031916908160001a90535050505b806120fe81613d55565b915050611fa9565b5061212d60405180604001604052806005815260200164776f72647360d81b815250612c7d565b61213681612d51565b632bc830a3821415801561214b575081600114155b15612190576121826040518060400160405280601081526020016f696e76616c696420636865636b73756d60801b81525083612f10565b506000979650505050505050565b6119c66040518060400160405280600e81526020016d76616c696420636865636b73756d60901b81525083612f10565b60006001815b835181101561225d5760008482815181106121e3576121e3613d3f565b016020015160f81c905060218110806121fc5750607e81115b1561223a5760405162461bcd60e51b815260206004820152600e60248201526d092dcecc2d8d2c840e0e4caccd2f60931b6044820152606401610c99565b600581901c612248846113ad565b189250508061225690613d55565b90506121c6565b50612267816113ad565b905060005b83518110156122b557600084828151811061228957612289613d3f565b016020015160f81c9050601f81166122a0846113ad565b18925050806122ae90613d55565b905061226c565b5092915050565b4284101561230c5760405162461bcd60e51b815260206004820152601760248201527f5045524d49545f444541444c494e455f455850495245440000000000000000006044820152606401610c99565b60006001612318610d76565b6001600160a01b038a811660008181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e08301909152805192019190912061190160f01b6101008301526101028201929092526101228101919091526101420160408051601f198184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015612424573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580159061245a5750876001600160a01b0316816001600160a01b0316145b6124975760405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa9a4a3a722a960911b6044820152606401610c99565b6001600160a01b0390811660009081526004602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b6060600082600281111561251657612516613970565b0361253a57505060408051808201909152600381526262633160e81b602082015290565b600282600281111561254e5761254e613970565b03612574575050604080518082019091526005815264626372743160d81b602082015290565b600182600281111561258857612588613970565b036125ac57505060408051808201909152600381526274623160e81b602082015290565b60405162461bcd60e51b8152602060048201526014602482015273556e6b6e6f776e206e6574776f726b207479706560601b6044820152606401610c99565b919050565b600061071d82612f55565b61260361275b565b6001600160a01b0381166126685760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c99565b61267181612a7e565b50565b60075460009081036126e25760405162461bcd60e51b815260206004820152603160248201527f56616c696461746f724d65737361676552656365697665723a204e4f5f56414c604482015270494441544f525f5055424c49435f4b455960781b6064820152608401610c99565b60006126f16020828587613c38565b6126fa91613dd2565b9050600061270c604060208688613c38565b61271591613dd2565b600754909150612727908383896109d5565b9695505050505050565b61273961275b565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b6006546001600160a01b03163314610e205760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c99565b6000806000806127c485612fc4565b91509150806127da575060009485945092505050565b50604080516020808201969096528082019290925280518083038201815260609092019052805193019290922092600192509050565b604080517f7bb52d7a9fef58323eb1bf7a407db382d2f3f2d81bb1224f49fe518f6d48d37c60208201819052918101829052606081018590526080810184905260a081018390526000919070014551231950b75fc4402da1732fc9bebe199060029060c00160408051601f198184030181529082905261288f91613d9d565b602060405180830381855afa1580156128ac573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906128cf9190613db9565b6128d99190613df0565b95945050505050565b60085460ff1615610e205760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610c99565b6001600160a01b03821660009081526003602052604081208054839290612950908490613c8e565b90915550506002805482900390556040518181526000906001600160a01b03841690600080516020613f16833981519152906020015b60405180910390a35050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60006040516129c49190613e04565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b612a34613089565b6008805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008311612b135760405162461bcd60e51b815260206004820152601060248201526f4d494e545f414d4f554e545f5a45524f60801b6044820152606401610c99565b612b256305f5e1006301406f40613ea3565b8310612b695760405162461bcd60e51b81526020600482015260136024820152724d494e545f414d4f554e545f544f4f5f42494760681b6044820152606401610c99565b306001600160a01b03831603612bc15760405162461bcd60e51b815260206004820152601c60248201527f4d494e545f544f5f5448455f434f4e54524143545f41444452455353000000006044820152606401610c99565b6000818152600c602052604090205460ff1615612c195760405162461bcd60e51b81526020600482015260166024820152751352539517d053149150511657d41493d0d154d4d15160521b6044820152606401610c99565b6000818152600c60205260409020805460ff19166001179055612c3c82846130d2565b60408051848152602081018390526001600160a01b038416917fb73f3e96d1e157f064cb3a8d0abed06bcec05e5515bf7486364c027dab6aa4699101610d69565b61267181604051602401612c9191906136cc565b60408051601f198184030181529190526020810180516001600160e01b031663104c13eb60e21b179052613124565b6040516001600160f81b0319821660248201526126719060440160408051601f198184030181529190526020810180516001600160e01b0316630dc3142560e31b179052613124565b612d116128e2565b6008805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612a613390565b606061071d82613145565b61267181604051602401612d6591906136cc565b60408051601f198184030181529190526020810180516001600160e01b03166305f3bfab60e11b179052613124565b61267181604051602401612daa91815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166327b7cf8560e01b179052613124565b60008160ff1660491480612df057508160ff16604f145b80612dfe57508160ff16606c145b15612e0b57506000919050565b60318260ff1610158015612e23575060398260ff1611155b15612e3057506001919050565b60418260ff1610158015612e485750605a8260ff1611155b15612e5557506001919050565b60618260ff1610158015612e6d5750607a8260ff1611155b15612e7a57506001919050565b506000919050565b61267181604051602401612e9891815260200190565b60408051601f198184030181529190526020810180516001600160e01b031663f5b1bba960e01b179052613124565b612f0c8282604051602401612edd929190613eba565b60408051601f198184030181529190526020810180516001600160e01b0316634b5c427760e01b179052613124565b5050565b612f0c8282604051602401612f26929190613edf565b60408051601f198184030181529190526020810180516001600160e01b03166309710a9d60e41b179052613124565b60007f7d21eae75cdfb1cf6d27ca9a73c6341b49bc05072228b51a7cd4df444c1c8710612f8860408401602085016139ae565b60408051602081019390935260609190911b6bffffffffffffffffffffffff191682820152830135605482015282356074820152609401611b4a565b6000806401000003d019816007828610612fe657506000958695509350505050565b60008380612ff657612ff6613c62565b848061300457613004613c62565b83868061301357613013613c62565b868b0908858061302557613025613c62565b868061303357613033613c62565b8a8b098a0908905061305c81600461304c876001613ca1565b6130569190613f01565b8661348f565b905060006001821615613078576130738286613c8e565b61307a565b815b98600198509650505050505050565b60085460ff16610e205760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610c99565b80600260008282546130e49190613ca1565b90915550506001600160a01b038216600081815260036020908152604080832080548601905551848152600080516020613f168339815191529101612986565b80516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b80516060906031906000805b828110801561317857508386828151811061316e5761316e613d3f565b016020015160f81c145b156131895760019182019101613151565b5060008080806117e361209f8702046001016002026001600160401b038111156131b5576131b5613862565b6040519080825280601f01601f1916602001820160405280156131df576020820181803683370190505b5090506000600460038801046001600160401b0381111561320257613202613862565b60405190808252806020026020018201604052801561322b578160200160208202803683370190505b50905060005b8a5181101561334d5760008b828151811061324e5761324e613d3f565b602001015160f81c60f81b905061327d6040518060600160405280603a8152602001613f36603a913982613558565b9096509450846132c65760405162461bcd60e51b81526020600482015260146024820152731a5b9d985b1a590818985cd94d4e08191a59da5d60621b6044820152606401610c99565b8251600019015b6000811261334357868482815181106132e8576132e8613d3f565b602002602001015163ffffffff16603a026001600160401b0316019750602088901c96508763ffffffff1684828151811061332557613325613d3f565b63ffffffff90921660209283029190910190910152600019016132cd565b5050600101613231565b50600860038816026001600160401b03811660000361336a575060205b600719016000805b8351811015613414575b6020836001600160401b0316101561340857826001600160401b03168482815181106133aa576133aa613d3f565b602002602001015163ffffffff16901c60f81b8583815181106133cf576133cf613d3f565b60200101906001600160f81b031916908160001a90535060019091019060086001600160401b038416106134085760088303925061337c565b60189250600101613372565b50875b845181101561347257600060f81b85828151811061343757613437613d3f565b01602001516001600160f81b031916111561346a57613459858a8303846135bb565b9d9c50505050505050505050505050565b600101613417565b5061347f846000836135bb565b9c9b505050505050505050505050565b6000816000036134d35760405162461bcd60e51b815260206004820152600f60248201526e4d6f64756c7573206973207a65726f60881b6044820152606401610c99565b836000036134e3575060006109ce565b826000036134f3575060016109ce565b6001600160ff1b5b801561354f57838186161515870a85848509099150836002820486161515870a85848509099150836004820486161515870a85848509099150836008820486161515870a85848509099150601090046134fb565b50949350505050565b60008060005b84518110156135ab57836001600160f81b03191685828151811061358457613584613d3f565b01602001516001600160f81b031916036135a3579150600190506135b4565b60010161355e565b50600080915091505b9250929050565b606060008383036001600160401b038111156135d9576135d9613862565b6040519080825280601f01601f191660200182016040528015613603576020820181803683370190505b50905060005b84840381101561354f57858582018151811061362757613627613d3f565b602001015160f81c60f81b82828151811061364457613644613d3f565b60200101906001600160f81b031916908160001a905350600101613609565b60006020828403121561367557600080fd5b5035919050565b60005b8381101561369757818101518382015260200161367f565b50506000910152565b600081518084526136b881602086016020860161367c565b601f01601f19169290920160200192915050565b6020815260006109ce60208301846136a0565b80356001600160a01b03811681146125eb57600080fd5b6000806040838503121561370957600080fd5b613712836136df565b946020939093013593505050565b8035600381106125eb57600080fd5b60008083601f84011261374157600080fd5b5081356001600160401b0381111561375857600080fd5b6020830191508360208285010111156135b457600080fd5b60008060006040848603121561378557600080fd5b61378e84613720565b925060208401356001600160401b038111156137a957600080fd5b6137b58682870161372f565b9497909650939450505050565b600080600080608085870312156137d857600080fd5b5050823594602084013594506040840135936060013592509050565b60008060006060848603121561380957600080fd5b613812846136df565b9250613820602085016136df565b9150604084013590509250925092565b60008060006040848603121561384557600080fd5b8335925060208401356001600160401b038111156137a957600080fd5b634e487b7160e01b600052604160045260246000fd5b60006001600160401b038084111561389257613892613862565b604051601f8501601f19908116603f011681019082821181831017156138ba576138ba613862565b816040528093508581528686860111156138d357600080fd5b858560208301376000602087830101525050509392505050565b600082601f8301126138fe57600080fd5b6109ce83833560208501613878565b6000806040838503121561392057600080fd5b82356001600160401b038082111561393757600080fd5b613943868387016138ed565b9350602085013591508082111561395957600080fd5b50613966858286016138ed565b9150509250929050565b634e487b7160e01b600052602160045260246000fd5b60208101600383106139a857634e487b7160e01b600052602160045260246000fd5b91905290565b6000602082840312156139c057600080fd5b6109ce826136df565b6000806000606084860312156139de57600080fd5b83359250613820602085016136df565b600060208284031215613a0057600080fd5b81356001600160f81b0319811681146109ce57600080fd5b60008060208385031215613a2b57600080fd5b82356001600160401b03811115613a4157600080fd5b613a4d8582860161372f565b90969095509350505050565b600060608284031215613a6b57600080fd5b50919050565b600080600060808486031215613a8657600080fd5b613a908585613a59565b925060608401356001600160401b038111156137a957600080fd5b600060208284031215613abd57600080fd5b81356001600160401b03811115613ad357600080fd5b610b35848285016138ed565b600060208284031215613af157600080fd5b81356001600160401b03811115613b0757600080fd5b8201601f81018413613b1857600080fd5b610b3584823560208401613878565b600080600080600080600060e0888a031215613b4257600080fd5b613b4b886136df565b9650613b59602089016136df565b95506040880135945060608801359350608088013560ff81168114613b7d57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600060208284031215613bac57600080fd5b6109ce82613720565b60008060408385031215613bc857600080fd5b613bd1836136df565b9150613bdf602084016136df565b90509250929050565b600060608284031215613bfa57600080fd5b6109ce8383613a59565b600181811c90821680613c1857607f821691505b602082108103613a6b57634e487b7160e01b600052602260045260246000fd5b60008085851115613c4857600080fd5b83861115613c5557600080fd5b5050820193919092039150565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8181038181111561071d5761071d613c78565b8082018082111561071d5761071d613c78565b606081528360608201528385608083013760006080858301015260006080601f19601f870116830101905083602083015282604083015295945050505050565b6020808252602b908201527f56616c696461746f724d65737361676552656365697665723a20494e56414c4960408201526a445f5349474e415455524560a81b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060018201613d6757613d67613c78565b5060010190565b60008351613d8081846020880161367c565b835190830190613d9481836020880161367c565b01949350505050565b60008251613daf81846020870161367c565b9190910192915050565b600060208284031215613dcb57600080fd5b5051919050565b8035602083101561071d57600019602084900360031b1b1692915050565b600082613dff57613dff613c62565b500690565b600080835481600182811c915080831680613e2057607f831692505b60208084108203613e3f57634e487b7160e01b86526022600452602486fd5b818015613e535760018114613e6857613e95565b60ff1986168952841515850289019650613e95565b60008a81526020902060005b86811015613e8d5781548b820152908501908301613e74565b505084890196505b509498975050505050505050565b808202811582820484141761071d5761071d613c78565b604081526000613ecd60408301856136a0565b82810360208401526128d981856136a0565b604081526000613ef260408301856136a0565b90508260208301529392505050565b600082613f1057613f10613c62565b50049056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef31323334353637383941424344454647484a4b4c4d4e505152535455565758595a6162636465666768696a6b6d6e6f707172737475767778797aa264697066735822122020caec933d9a13d787330ff7014afd1cebca57a4e7f475fd8eef0dc5d9b4847a64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : _network (uint8): 1
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000001
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.