Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
lnBTC
Compiler Version
v0.8.24+commit.e11b9ed9
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; import "openzeppelin-contracts-upgradeable/contracts/token/ERC20/ERC20Upgradeable.sol"; import "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "openzeppelin-contracts-upgradeable/contracts/utils/PausableUpgradeable.sol"; import "./lib/BitcoinUtils.sol"; import "./lib/ValidatorMessageReceiver.sol"; import "./lib/ValidatorRegistry.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 ERC20Upgradeable, ValidatorMessageReceiver, BitcoinUtils, PausableUpgradeable, ILnBTC { BitcoinUtils.Network public network; uint256 public constant DUST_LIMIT = 546; // sat /** * @dev `minWithdrawAmount` represents the minimum amount of satoshis that can be withdrawn. */ uint256 public minWithdrawAmount; // 0.00002 BTC uint256 public redeemCounter; address public minter; mapping(bytes32 => bool) public btcDepositIds; function initialize( BitcoinUtils.Network _network, ValidatorRegistry _validatorRegistry ) public initializer { ERC20Upgradeable.__ERC20_init("Stroom Bitcoin", "stBTC"); PausableUpgradeable.__Pausable_init(); ValidatorMessageReceiver.initialize(_validatorRegistry); minWithdrawAmount = 2_000; // 0.00002 BTC redeemCounter = 0; // TODO: deduce from chain id network = _network; minter = msg.sender; } function decimals() public pure override returns (uint8) { return 8; } function setMintedInvoiceBatch( bytes32[] calldata _btcDepositIds ) public onlyOwner { for (uint256 i = 0; i < _btcDepositIds.length; i++) { btcDepositIds[_btcDepositIds[i]] = true; } } // ========= Minting Signature ====== /** * @dev Calculates the data of an invoice. * @return The data of the invoice. */ function getMintInvoiceHash( MintInvoice calldata invoice ) public pure returns (bytes32) { return keccak256( abi.encodePacked(MINT_INVOICE_PREFIX, encodeInvoice(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); } function mintBatchMinterOnly( uint256[] calldata _amounts, address[] calldata _recipients ) public whenNotPaused { require(msg.sender == minter, "lnBTC: only minter allowed to mint"); require( _amounts.length == _recipients.length, "lnBTC: arrays length mismatch" ); for (uint256 i = 0; i < _amounts.length; i++) { if (_amounts[i] == 0) { continue; } _mint(_recipients[i], _amounts[i]); } } /** * @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( ValidatorRegistry.MessageType.Invoice, encodeInvoice(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: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {ContextUpgradeable} from "../../utils/ContextUpgradeable.sol"; import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; import {Initializable} from "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. */ abstract contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors { /// @custom:storage-location erc7201:openzeppelin.storage.ERC20 struct ERC20Storage { mapping(address account => uint256) _balances; mapping(address account => mapping(address spender => uint256)) _allowances; uint256 _totalSupply; string _name; string _symbol; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC20")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00; function _getERC20Storage() private pure returns (ERC20Storage storage $) { assembly { $.slot := ERC20StorageLocation } } /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing { __ERC20_init_unchained(name_, symbol_); } function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing { ERC20Storage storage $ = _getERC20Storage(); $._name = name_; $._symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { ERC20Storage storage $ = _getERC20Storage(); return $._name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { ERC20Storage storage $ = _getERC20Storage(); return $._symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { ERC20Storage storage $ = _getERC20Storage(); return $._allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { ERC20Storage storage $ = _getERC20Storage(); if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows $._totalSupply += value; } else { uint256 fromBalance = $._balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. $._balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. $._totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. $._balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * ``` * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { ERC20Storage storage $ = _getERC20Storage(); if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } $._allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.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. * * The initial owner is set to the address provided by the deployer. 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 OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @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) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @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 { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.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 PausableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Pausable struct PausableStorage { bool _paused; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Pausable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300; function _getPausableStorage() private pure returns (PausableStorage storage $) { assembly { $.slot := PausableStorageLocation } } /** * @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); /** * @dev The operation failed because the contract is paused. */ error EnforcedPause(); /** * @dev The operation failed because the contract is not paused. */ error ExpectedPause(); /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { PausableStorage storage $ = _getPausableStorage(); $._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) { PausableStorage storage $ = _getPausableStorage(); return $._paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { if (paused()) { revert EnforcedPause(); } } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { if (!paused()) { revert ExpectedPause(); } } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { PausableStorage storage $ = _getPausableStorage(); $._paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { PausableStorage storage $ = _getPausableStorage(); $._paused = false; emit Unpaused(_msgSender()); } }
// 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_MAINNET = hex"31"; // prefix = 1 bytes constant BTC_P2SH_MAINNET = hex"33"; // prefix = 3 bytes constant BTC_P2PKH_TESTNET = hex"32"; // prefix = 2 bytes constant BTC_P2SH_TESTNET = hex"6d"; // prefix = m bytes constant BTC_P2PKH_REGTEST = hex"32"; // prefix = 2 bytes constant BTC_P2SH_REGTEST = hex"6d"; // prefix = m 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 getBtcBase58_P2PKH(Network network) public pure returns (bytes memory) { if (network == Network.Mainnet) { return BTC_P2PKH_MAINNET; } else if (network == Network.Regtest) { return BTC_P2PKH_REGTEST; } else if (network == Network.Testnet) { return BTC_P2PKH_TESTNET; } else { revert("Unknown network type"); } } function getBtcBase58_P2SH(Network network) public pure returns (bytes memory) { if (network == Network.Mainnet) { return BTC_P2SH_MAINNET; } else if (network == Network.Regtest) { return BTC_P2SH_REGTEST; } else if (network == Network.Testnet) { return BTC_P2SH_TESTNET; } else { revert("Unknown network type"); } } 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; console.log("\nraw address data"); console.logBytes(bytes(BTCAddress)); bytes memory BTC_P2PKH = getBtcBase58_P2PKH(network); bytes memory BTC_P2SH = getBtcBase58_P2SH(network); 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-upgradeable/contracts/access/OwnableUpgradeable.sol"; import "bip340-solidity/src/Bip340Ecrec.sol"; import "./ValidatorRegistry.sol"; contract ValidatorMessageReceiver is OwnableUpgradeable, Bip340Ecrec { // Add a state variable for the ValidatorRegistry contract ValidatorRegistry public validatorRegistry; // Update the constructor to accept the ValidatorRegistry contract function initialize( ValidatorRegistry _validatorRegistry ) public onlyInitializing { OwnableUpgradeable.__Ownable_init(msg.sender); validatorRegistry = _validatorRegistry; } modifier onlyValidator( ValidatorRegistry.MessageType messageType, bytes memory data, bytes calldata signature ) { require( validatorRegistry.validateMessage( validatorRegistry.getMessageHash(messageType, data), signature ), "ValidatorMessageReceiver: INVALID_SIGNATURE" ); _; } }
// 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 ValidatorRegistry is Ownable, Bip340Ecrec { // Combined multisig key of all validators bytes32 public jointPublicKey; // Event to log the update of the validator public key event JointPublicKeyUpdated(bytes32 newjointPublicKey); // Enum for message types enum MessageType { Invoice, TotalSupplyUpdate, JointPublicKeyUpdate } constructor(bytes32 _jointPublicKey) Ownable(msg.sender) { jointPublicKey = _jointPublicKey; } // Function to get the hash of a message based on its type function getMessageHash(MessageType messageType, bytes memory data) public pure returns (bytes32) { if (messageType == MessageType.Invoice) { return keccak256(abi.encodePacked(keccak256("STROOM_MINT_INVOICE"), data)); } else if (messageType == MessageType.TotalSupplyUpdate) { return keccak256(abi.encodePacked(keccak256("STROOM_UPDATE_TOTAL_SUPPLY"), data)); } else if (messageType == MessageType.JointPublicKeyUpdate) { return keccak256(abi.encodePacked(keccak256("STROOM_UPDATE_VALIDATOR_PUBLIC_KEY"), data)); } else { revert("Unknown message type"); } } // Function to update the validator public key function setJointPublicKey( bytes32 _jointPublicKey ) public onlyOwner { jointPublicKey = _jointPublicKey; emit JointPublicKeyUpdated(_jointPublicKey); } // Function to update the validator public key with a signature function setJointPublicKeySigned( bytes32 _jointPublicKey, bytes calldata signature ) public { bytes32 hash = getMessageHash(MessageType.JointPublicKeyUpdate, abi.encodePacked(_jointPublicKey)); require( validateMessage(hash, signature), "ValidatorRegistry: INVALID_SIGNATURE" ); jointPublicKey = _jointPublicKey; emit JointPublicKeyUpdated(_jointPublicKey); } // Function to validate a message function validateMessage( bytes32 hash, bytes calldata signature ) public view returns (bool) { require( jointPublicKey != 0, "ValidatorRegistry: NO_JOINT_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(jointPublicKey), 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 inner data of an invoice. * @return The bytes data of the invoice. */ function encodeInvoice( MintInvoice calldata invoice ) pure returns (bytes memory) { return abi.encodePacked( 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; event RedeemBtcEvent( address indexed _from, string _BTCAddress, uint256 _value, uint256 _id ); event MintBtcEvent( address indexed _to, uint256 _value, bytes32 _btcDepositId ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// 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 v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../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. * * The initial owner is set to the address provided by the deployer. 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; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @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 { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @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 { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _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 // // 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 // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// 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": [ "base58-solidity/=lib/base58-solidity/contracts/", "bip340-solidity/=lib/bip340-solidity/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/", "openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "blockchain-tools/=lib/blockchain-tools/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/", "bitcoin-spv/=lib/blockchain-tools/lib/bitcoin-spv/", "elliptic-curve-solidity/=lib/elliptic-curve-solidity/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "foundry-devops/=lib/blockchain-tools/lib/foundry-devops/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/", "openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/", "solidity-stringutils/=lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/", "solmate/=lib/blockchain-tools/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":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","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":"value","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":"DUST_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","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":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","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":"pure","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":"getBtcBase58_P2PKH","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"enum BitcoinUtils.Network","name":"network","type":"uint8"}],"name":"getBtcBase58_P2SH","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"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":"enum BitcoinUtils.Network","name":"_network","type":"uint8"},{"internalType":"contract ValidatorRegistry","name":"_validatorRegistry","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ValidatorRegistry","name":"_validatorRegistry","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"address[]","name":"_recipients","type":"address[]"}],"name":"mintBatchMinterOnly","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":[],"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":"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":"bytes32[]","name":"_btcDepositIds","type":"bytes32[]"}],"name":"setMintedInvoiceBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"setMinter","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":"value","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":"value","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":[],"name":"validatorRegistry","outputs":[{"internalType":"contract ValidatorRegistry","name":"","type":"address"}],"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
608060405234801561001057600080fd5b506144ab806100206000396000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c806370a0823111610151578063a9059cbb116100c3578063d9ab380111610087578063d9ab3801146105b5578063dd62ed3e146105c8578063e07fbd00146105db578063f2fde38b146105ee578063f376ebbb14610601578063fca3b5aa1461061457600080fd5b8063a9059cbb14610556578063af7b817014610569578063c4d66de81461057c578063d354c65d1461058f578063d3b6d7f5146105a257600080fd5b80638456cb59116101155780638456cb59146104e75780638da5cb5b146104ef57806395d89b411461051f5780639647ea37146105275780639fd956871461053a578063a7ce45651461054d57600080fd5b806370a0823114610470578063715018a6146104a6578063780f8df3146104ae5780637b8d3cb4146104c157806380cf79c8146104d457600080fd5b8063313ce567116101ea5780634ae1d1e5116101ae5780634ae1d1e5146103eb5780634cac70ff146103fe5780635187599d146104115780635abdb0dc146104245780635c975abb146104375780636739afca1461044f57600080fd5b8063313ce567146103a95780633d003000146103be5780633f4ba83a146103d157806342193473146103d9578063457e1a49146103e257600080fd5b80630b2aeb6c1161023c5780630b2aeb6c146103175780630fde6e551461032a57806318160ddd1461033d57806323b872dd1461036e57806324b76fd5146103815780633082599e1461039657600080fd5b8063026034f01461027957806306fdde03146102b157806307546172146102c6578063095ea7b3146102f15780630b2a158514610304575b600080fd5b61029c6102873660046139e0565b60046020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6102b9610627565b6040516102a89190613a49565b6003546102d9906001600160a01b031681565b6040516001600160a01b0390911681526020016102a8565b61029c6102ff366004613a71565b6106ea565b6102b9610312366004613aac565b610704565b61029c610325366004613b08565b6107f1565b61029c610338366004613b5a565b610ad0565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b6040519081526020016102a8565b61029c61037c366004613b8c565b610c38565b61039461038f366004613bcd565b610c5c565b005b6102b96103a4366004613aac565b610db2565b60085b60405160ff90911681526020016102a8565b6103946103cc366004613c43565b610e56565b610394610f5a565b61036061022281565b61036060015481565b6103946103f9366004613cae565b610f6c565b61029c61040c366004613d9a565b610fcc565b61039461041f366004613dfd565b611054565b6103946104323660046139e0565b611202565b60008051602061441c8339815191525460ff1661029c565b60005461046390600160a01b900460ff1681565b6040516102a89190613e68565b61036061047e366004613e7b565b6001600160a01b031660009081526000805160206143fc833981519152602052604090205490565b610394611287565b6103946104bc366004613e98565b611299565b6103ac6104cf366004613ebf565b6112d6565b6103606104e23660046139e0565b6116bb565b61039461177b565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03166102d9565b6102b961178b565b61029c610535366004613ee9565b6117ca565b610394610548366004613f36565b611d00565b61036060025481565b61029c610564366004613a71565b611e71565b61029c610577366004613f70565b611e7f565b61039461058a366004613e7b565b611eda565b61029c61059d366004613fa4565b611f0d565b6103606105b0366004613f70565b61253e565b6102b96105c3366004613aac565b612628565b6103606105d6366004613fec565b6126d4565b6103606105e936600461400a565b61271e565b6103946105fc366004613e7b565b612778565b6000546102d9906001600160a01b031681565b610394610622366004613e7b565b6127b6565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0380546060916000805160206143fc8339815191529161066690614026565b80601f016020809104026020016040519081016040528092919081815260200182805461069290614026565b80156106df5780601f106106b4576101008083540402835291602001916106df565b820191906000526020600020905b8154815290600101906020018083116106c257829003601f168201915b505050505091505090565b6000336106f88185856127e0565b60019150505b92915050565b6060600082600281111561071a5761071a613e34565b0361073c5750506040805180820190915260018152603360f81b602082015290565b600282600281111561075057610750613e34565b036107725750506040805180820190915260018152606d60f81b602082015290565b600182600281111561078657610786613e34565b036107a85750506040805180820190915260018152606d60f81b602082015290565b60405162461bcd60e51b8152602060048201526014602482015273556e6b6e6f776e206e6574776f726b207479706560601b60448201526064015b60405180910390fd5b919050565b6000606061083684848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250859250610fcc915050565b15610845576000915050610ac9565b610877604051806040016040528060118152602001700a7261772061646472657373206461746160781b8152506127ed565b6108b684848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061283092505050565b60006108c186610db2565b905060006108ce87610704565b905061091d6108e160016000888a61405a565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250869250610fcc915050565b80610970575061097061093460016000888a61405a565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250859250610fcc915050565b156109f057601a8510806109845750602385115b806109cb57506109c986868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e7f92505050565b155b156109dc5760009350505050610ac9565b6109e686866117ca565b9350505050610ac9565b60006109fb88612628565b8051909150610a1190610934906000898b61405a565b15610ac0576002886002811115610a2a57610a2a613e34565b03610a5557602b861080610a3e5750603f86115b15610a50576000945050505050610ac9565b610a76565b602a861080610a645750603e86115b15610a76576000945050505050610ac9565b610ab587878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f0d92505050565b945050505050610ac9565b60009450505050505b9392505050565b60006401000003d01985101580610aed57506401000003d0198410155b80610b0a575070014551231950b75fc4402da1732fc9bebe198310155b15610b1757506000610c30565b600080610b2386612873565b9150915080610b3757600092505050610c30565b6000610b448789876128ce565b9050600070014551231950b75fc4402da1732fc9bebe19898809610b7a9070014551231950b75fc4402da1732fc9bebe196140b0565b9050600070014551231950b75fc4402da1732fc9bebe198a8409610bb09070014551231950b75fc4402da1732fc9bebe196140b0565b60408051600080825260208201808452869052601b92820192909252606081018d9052608081018390529192509060019060a0016020604051602081039080840390855afa158015610c06573d6000803e3d6000fd5b505050602060405103519050856001600160a01b0316816001600160a01b03161496505050505050505b949350505050565b600033610c468582856129a0565b610c51858585612a06565b506001949350505050565b610c64612a65565b600154831015610cdc5760405162461bcd60e51b815260206004820152603e60248201527f5468652073656e742076616c7565206d7573742062652067726561746572206f60448201527f7220657175616c20746f206d696e20776974686472617720616d6f756e74000060648201526084016107e3565b600054610cf490600160a01b900460ff1683836107f1565b610d4a5760405162461bcd60e51b815260206004820152602160248201527f5468652073656e74204254432061646472657373206973206e6f742076616c696044820152601960fa1b60648201526084016107e3565b610d543384612a96565b600160026000828254610d6791906140c3565b909155505060025460405133917f83c16822c691a011b471d2653b84faff158a050c4e117390a6c008ecdefcc14e91610da5918691869189916140ff565b60405180910390a2505050565b60606000826002811115610dc857610dc8613e34565b03610dea5750506040805180820190915260018152603160f81b602082015290565b6002826002811115610dfe57610dfe613e34565b03610e205750506040805180820190915260018152601960f91b602082015290565b6001826002811115610e3457610e34613e34565b036107a85750506040805180820190915260018152601960f91b602082015290565b610e5e612a65565b6003546001600160a01b03163314610e885760405162461bcd60e51b81526004016107e390614126565b828114610ed75760405162461bcd60e51b815260206004820152601d60248201527f6c6e4254433a20617272617973206c656e677468206d69736d6174636800000060448201526064016107e3565b60005b83811015610f5357848482818110610ef457610ef4614168565b9050602002013560000315610f4b57610f4b838383818110610f1857610f18614168565b9050602002016020810190610f2d9190613e7b565b868684818110610f3f57610f3f614168565b90506020020135612ad0565b600101610eda565b5050505050565b610f62612b06565b610f6a612b61565b565b610f74612b06565b60005b81811015610fc757600160046000858585818110610f9757610f97614168565b60209081029290920135835250810191909152604001600020805460ff1916911515919091179055600101610f77565b505050565b60008151835114610fdf575060006106fe565b60005b835181101561104a57828181518110610ffd57610ffd614168565b602001015160f81c60f81b6001600160f81b03191684828151811061102457611024614168565b01602001516001600160f81b031916146110425760009150506106fe565b600101610fe2565b5060019392505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03166000811580156110995750825b90506000826001600160401b031660011480156110b55750303b155b9050811580156110c3575080155b156110e15760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561110b57845460ff60401b1916600160401b1785555b6111586040518060400160405280600e81526020016d29ba3937b7b6902134ba31b7b4b760911b81525060405180604001604052806005815260200164737442544360d81b815250612bc1565b611160612bd3565b61116986611eda565b6107d060015560006002818155815489929160ff60a01b1990911690600160a01b90849081111561119c5761119c613e34565b0217905550600380546001600160a01b0319163317905583156111f957845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b61120a612b06565b6102228110156112825760405162461bcd60e51b815260206004820152603c60248201527f4d696e20776974686472617720616d6f756e742073686f756c6420626520677260448201527f6561746572206f7220657175616c20746f2064757374206c696d69740000000060648201526084016107e3565b600155565b61128f612b06565b610f6a6000612be3565b6112a1612a65565b6003546001600160a01b031633146112cb5760405162461bcd60e51b81526004016107e390614126565b610fc7838383612c54565b6000600d60fc1b6001600160f81b03198316016112f55750600f919050565b606760f91b6001600160f81b03198316016113125750600a919050565b60cd60f81b6001600160f81b031983160161132f57506011919050565b603360fa1b6001600160f81b031983160161134c57506015919050565b60cb60f81b6001600160f81b031983160161136957506014919050565b606560f91b6001600160f81b03198316016113865750601a919050565b601960fb1b6001600160f81b03198316016113a357506007919050565b60c960f81b6001600160f81b03198316016113c05750601e919050565b60c760f81b6001600160f81b03198316016113dd57506005919050565b608f60f81b6001600160f81b03198316016113fa57506000919050565b600960fc1b6001600160f81b031983160161141757506001919050565b604360f91b6001600160f81b031983160161143457506002919050565b604760f91b6001600160f81b031983160161145157506003919050565b608760f81b6001600160f81b031983160161146e57506004919050565b601160fb1b6001600160f81b031983160161148b57506006919050565b609960f81b6001600160f81b03198316016114a857506008919050565b604d60f91b6001600160f81b03198316016114c557506009919050565b602360fa1b6001600160f81b03198316016114e25750600b919050565b604560f91b6001600160f81b03198316016114ff5750600c919050565b602760fa1b6001600160f81b031983160161151c5750600d919050565b608960f81b6001600160f81b03198316016115395750600e919050565b608d60f81b6001600160f81b031983160161155657506010919050565b604b60f91b6001600160f81b031983160161157357506012919050565b604960f91b6001600160f81b031983160161159057506013919050565b609560f81b6001600160f81b03198316016115ad57506016919050565b601360fb1b6001600160f81b03198316016115ca57506017919050565b609d60f81b6001600160f81b03198316016115e757506018919050565b609b60f81b6001600160f81b031983160161160457506019919050565b609360f81b6001600160f81b03198316016116215750601b919050565b608b60f81b6001600160f81b031983160161163e5750601c919050565b609f60f81b6001600160f81b031983160161165b5750601d919050565b602560fa1b6001600160f81b03198316016116785750601f919050565b6116aa6040518060400160405280601181526020017024b73b30b634b21031b430b930b1ba32b960791b8152506127ed565b6116b382612e01565b5060ff919050565b6000601982901c6001601d84901c8116146116d75760006116dd565b632a1462b35b63ffffffff16600382901c6001166001146116f95760006116ff565b633d4233dd5b63ffffffff16600283901c60011660011461171b576000611721565b631ea119fa5b63ffffffff16600184811c81161461173a576000611740565b6326508e6d5b63ffffffff1660018086161461175757600061175d565b633b6a57b25b63ffffffff166005886301ffffff16901b1818181818915050919050565b611783612b06565b610f6a612e4a565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0480546060916000805160206143fc8339815191529161066690614026565b60008061180c84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612e9392505050565b90506118456040518060400160405280601681526020017576616c6964617465426173653538436865636b73756d60501b8152506127ed565b61186d604051806040016040528060078152602001661c185e5b1bd85960ca1b8152506127ed565b61187681612830565b80516019146118895760009150506106fe565b604080516001808252818301909252600091602082018180368337019050509050816000815181106118bd576118bd614168565b602001015160f81c60f81b816000815181106118db576118db614168565b60200101906001600160f81b031916908160001a90535061191a604051806040016040528060078152602001663b32b939b4b7b760c91b8152506127ed565b61192381612830565b600060046001845161193591906140b0565b61193f91906140b0565b6001600160401b0381111561195657611956613cef565b6040519080825280601f01601f191660200182016040528015611980576020820181803683370190505b50905060005b60046001855161199691906140b0565b6119a091906140b0565b8110156119ff57836119b38260016140c3565b815181106119c3576119c3614168565b602001015160f81c60f81b8282815181106119e0576119e0614168565b60200101906001600160f81b031916908160001a905350600101611986565b50611a28604051806040016040528060078152602001661c185e5b1bd85960ca1b8152506127ed565b611a3181612830565b8051601414611a4657600093505050506106fe565b60408051600480825281830190925260009160208201818036833701905050905060005b6004811015611ad957848160048751611a8391906140b0565b611a8d91906140c3565b81518110611a9d57611a9d614168565b602001015160f81c60f81b828281518110611aba57611aba614168565b60200101906001600160f81b031916908160001a905350600101611a6a565b50611b0360405180604001604052806008815260200167636865636b73756d60c01b8152506127ed565b611b0c81612830565b60006002808585604051602001611b2492919061417e565b60408051601f1981840301815290829052611b3e916141ad565b602060405180830381855afa158015611b5b573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190611b7e91906141c9565b604051602001611b9091815260200190565b60408051601f1981840301815290829052611baa916141ad565b602060405180830381855afa158015611bc7573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190611bea91906141c9565b9050611c206040518060400160405280601381526020017263616c63756c6174656420636865636b73756d60681b8152506127ed565b611c2981612e9e565b8060031a60f81b82600381518110611c4357611c43614168565b01602001516001600160f81b031916188160021a60f81b83600281518110611c6d57611c6d614168565b01602001516001600160f81b031916188260011a60f81b84600181518110611c9757611c97614168565b01602001516001600160f81b031916188360001a60f81b85600081518110611cc157611cc1614168565b602001015160f81c60f81b181717176001600160f81b031916600060f81b14611cf2576000955050505050506106fe565b506001979650505050505050565b611d08612a65565b6000611d1384612ee3565b6000546040516372ee4c8760e01b8152859185916001600160a01b039091169063f9a8bc489082906372ee4c8790611d5190899089906004016141e2565b602060405180830381865afa158015611d6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d9291906141c9565b84846040518463ffffffff1660e01b8152600401611db293929190614204565b602060405180830381865afa158015611dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df3919061421e565b611e535760405162461bcd60e51b815260206004820152602b60248201527f56616c696461746f724d65737361676552656365697665723a20494e56414c4960448201526a445f5349474e415455524560a81b60648201526084016107e3565b6111f960408801803590611e6a9060208b01613e7b565b8935612c54565b6000336106f8818585612a06565b6000805b8251811015611ed1576000838281518110611ea057611ea0614168565b016020015160f81c90506000611eb582612f3b565b905080611ec757506000949350505050565b5050600101611e83565b50600192915050565b611ee2612fe4565b611eeb3361302d565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000611f4d6040518060400160405280601981526020017f0a76616c69646174652062656368333220636865636b73756d000000000000008152506127ed565b611f75604051806040016040528060078152602001666164647265737360c81b8152506127ed565b611f7e826127ed565b8151829060081115611fbd57611fb4604051806040016040528060098152602001681d1bdbc81cda1bdc9d60ba1b8152506127ed565b50600092915050565b605a81511115611ff057611fb460405180604001604052806008815260200167746f6f206c6f6e6760c01b8152506127ed565b50816000805b825181101561203a5782818151811061201157612011614168565b01602001516001600160f81b031916603160f81b036120325780915061203a565b600101611ff6565b508060000361207a576120706040518060400160405280600c81526020016b37379039b2b830b930ba37b960a11b8152506127ed565b5060009392505050565b806001036120b1576120706040518060400160405280600e81526020016d0dad2e6e6d2dcce40e0e4caccd2f60931b8152506127ed565b6000816001600160401b038111156120cb576120cb613cef565b6040519080825280601f01601f1916602001820160405280156120f5576020820181803683370190505b5090506000600183855161210991906140b0565b61211391906140b0565b6001600160401b0381111561212a5761212a613cef565b6040519080825280601f01601f191660200182016040528015612154576020820181803683370190505b50905060005b838110156121b05784818151811061217457612174614168565b602001015160f81c60f81b83828151811061219157612191614168565b60200101906001600160f81b031916908160001a90535060010161215a565b5060005b815181101561221f57846121c885836140c3565b6121d39060016140c3565b815181106121e3576121e3614168565b602001015160f81c60f81b82828151811061220057612200614168565b60200101906001600160f81b031916908160001a9053506001016121b4565b50612247604051806040016040528060068152602001650e0e4caccd2f60d31b8152506127ed565b61225082612830565b600681511015612295576122896040518060400160405280600e81526020016d19185d18481d1bdbc81cda1bdc9d60921b8152506127ed565b50600095945050505050565b60006122a08361253e565b9050806000036122e6576122d96040518060400160405280600e81526020016d0d2dcecc2d8d2c840e0e4caccd2f60931b8152506127ed565b5060009695505050505050565b600082516001600160401b0381111561230157612301613cef565b6040519080825280601f01601f19166020018201604052801561232b576020820181803683370190505b50905060005b835181101561248457600084828151811061234e5761234e614168565b01602001516001600160f81b0319169050600061236a826112d6565b905060fe1960ff821601612422576123aa604051806040016040528060118152602001703ab735b737bbb71031b430b930b1ba32b960791b8152506127ed565b6123b38361303e565b6123bc82612e01565b6124116040518060400160405280600481526020016331b430b960e11b815250836040516020016123fd91906001600160f81b031991909116815260010190565b604051602081830303815290604052613083565b5060009a9950505050505050505050565b8060ff1661242f866116bb565b8751911895506124408460066140c3565b1061244c57505061247c565b8060f81b84848151811061246257612462614168565b60200101906001600160f81b031916908160001a90535050505b600101612331565b506124ab60405180604001604052806005815260200164776f72647360d81b8152506127ed565b6124b481612830565b632bc830a382141580156124c9575081600114155b1561250e576125006040518060400160405280601081526020016f696e76616c696420636865636b73756d60801b815250836130c8565b506000979650505050505050565b611cf26040518060400160405280600e81526020016d76616c696420636865636b73756d60901b815250836130c8565b60006001815b83518110156125d257600084828151811061256157612561614168565b016020015160f81c9050602181108061257a5750607e81115b156125b85760405162461bcd60e51b815260206004820152600e60248201526d092dcecc2d8d2c840e0e4caccd2f60931b60448201526064016107e3565b600581901c6125c6846116bb565b18925050600101612544565b506125dc816116bb565b905060005b83518110156126215760008482815181106125fe576125fe614168565b016020015160f81c9050601f8116612615846116bb565b189250506001016125e1565b5092915050565b6060600082600281111561263e5761263e613e34565b0361266257505060408051808201909152600381526262633160e81b602082015290565b600282600281111561267657612676613e34565b0361269c575050604080518082019091526005815264626372743160d81b602082015290565b60018260028111156126b0576126b0613e34565b036107a857505060408051808201909152600381526274623160e81b602082015290565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b60007f7d21eae75cdfb1cf6d27ca9a73c6341b49bc05072228b51a7cd4df444c1c871061274a83612ee3565b60405160200161275b929190614240565b604051602081830303815290604052805190602001209050919050565b612780612b06565b6001600160a01b0381166127aa57604051631e4fbdf760e01b8152600060048201526024016107e3565b6127b381612be3565b50565b6127be612b06565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b610fc7838383600161310d565b6127b3816040516024016128019190613a49565b60408051601f198184030181529190526020810180516001600160e01b031663104c13eb60e21b1790526131f4565b6127b3816040516024016128449190613a49565b60408051601f198184030181529190526020810180516001600160e01b03166305f3bfab60e11b1790526131f4565b60008060008061288285613215565b9150915080612898575060009485945092505050565b50604080516020808201969096528082019290925280518083038201815260609092019052805193019290922092600192509050565b604080517f7bb52d7a9fef58323eb1bf7a407db382d2f3f2d81bb1224f49fe518f6d48d37c60208201819052918101829052606081018590526080810184905260a081018390526000919070014551231950b75fc4402da1732fc9bebe199060029060c00160408051601f198184030181529082905261294d916141ad565b602060405180830381855afa15801561296a573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061298d91906141c9565b6129979190614266565b95945050505050565b60006129ac84846126d4565b90506000198114612a0057818110156129f157604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064016107e3565b612a008484848403600061310d565b50505050565b6001600160a01b038316612a3057604051634b637e8f60e11b8152600060048201526024016107e3565b6001600160a01b038216612a5a5760405163ec442f0560e01b8152600060048201526024016107e3565b610fc78383836132da565b60008051602061441c8339815191525460ff1615610f6a5760405163d93c066560e01b815260040160405180910390fd5b6001600160a01b038216612ac057604051634b637e8f60e11b8152600060048201526024016107e3565b612acc826000836132da565b5050565b6001600160a01b038216612afa5760405163ec442f0560e01b8152600060048201526024016107e3565b612acc600083836132da565b33612b387f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610f6a5760405163118cdaa760e01b81523360048201526024016107e3565b612b69613418565b60008051602061441c833981519152805460ff191681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a150565b612bc9612fe4565b612acc8282613448565b612bdb612fe4565b610f6a613499565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60008311612c975760405162461bcd60e51b815260206004820152601060248201526f4d494e545f414d4f554e545f5a45524f60801b60448201526064016107e3565b612ca96305f5e1006301406f4061427a565b8310612ced5760405162461bcd60e51b81526020600482015260136024820152724d494e545f414d4f554e545f544f4f5f42494760681b60448201526064016107e3565b306001600160a01b03831603612d455760405162461bcd60e51b815260206004820152601c60248201527f4d494e545f544f5f5448455f434f4e54524143545f414444524553530000000060448201526064016107e3565b60008181526004602052604090205460ff1615612d9d5760405162461bcd60e51b81526020600482015260166024820152751352539517d053149150511657d41493d0d154d4d15160521b60448201526064016107e3565b6000818152600460205260409020805460ff19166001179055612dc08284612ad0565b60408051848152602081018390526001600160a01b038416917fb73f3e96d1e157f064cb3a8d0abed06bcec05e5515bf7486364c027dab6aa4699101610da5565b6040516001600160f81b0319821660248201526127b39060440160408051601f198184030181529190526020810180516001600160e01b0316630dc3142560e31b1790526131f4565b612e52612a65565b60008051602061441c833981519152805460ff191660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833612ba3565b60606106fe826134ba565b6127b381604051602401612eb491815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166327b7cf8560e01b1790526131f4565b6060612ef56040830160208401613e7b565b6040805160609290921b6bffffffffffffffffffffffff191660208301528301356034820152823560548201526074016040516020818303038152906040529050919050565b60008160ff1660491480612f5257508160ff16604f145b80612f6057508160ff16606c145b15612f6d57506000919050565b60318260ff1610158015612f85575060398260ff1611155b15612f9257506001919050565b60418260ff1610158015612faa5750605a8260ff1611155b15612fb757506001919050565b60618260ff1610158015612fcf5750607a8260ff1611155b15612fdc57506001919050565b506000919050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610f6a57604051631afcd79f60e31b815260040160405180910390fd5b613035612fe4565b6127b381613804565b6127b38160405160240161305491815260200190565b60408051601f198184030181529190526020810180516001600160e01b031663f5b1bba960e01b1790526131f4565b612acc8282604051602401613099929190614291565b60408051601f198184030181529190526020810180516001600160e01b0316634b5c427760e01b1790526131f4565b612acc82826040516024016130de9291906142b6565b60408051601f198184030181529190526020810180516001600160e01b03166309710a9d60e41b1790526131f4565b6000805160206143fc8339815191526001600160a01b0385166131465760405163e602df0560e01b8152600060048201526024016107e3565b6001600160a01b03841661317057604051634a1406b160e11b8152600060048201526024016107e3565b6001600160a01b03808616600090815260018301602090815260408083209388168352929052208390558115610f5357836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925856040516131e591815260200190565b60405180910390a35050505050565b80516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b6000806401000003d01981600782861061323757506000958695509350505050565b6000838061324757613247614084565b848061325557613255614084565b83868061326457613264614084565b868b0908858061327657613276614084565b868061328457613284614084565b8a8b098a090890506132ad81600461329d8760016140c3565b6132a791906142d8565b8661380c565b9050600060018216156132c9576132c482866140b0565b6132cb565b815b98600198509650505050505050565b6000805160206143fc8339815191526001600160a01b038416613316578181600201600082825461330b91906140c3565b909155506133889050565b6001600160a01b038416600090815260208290526040902054828110156133695760405163391434e360e21b81526001600160a01b038616600482015260248101829052604481018490526064016107e3565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b0383166133a65760028101805483900390556133c5565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161340a91815260200190565b60405180910390a350505050565b60008051602061441c8339815191525460ff16610f6a57604051638dfc202b60e01b815260040160405180910390fd5b613450612fe4565b6000805160206143fc8339815191527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0361348a848261433c565b5060048101612a00838261433c565b6134a1612fe4565b60008051602061441c833981519152805460ff19169055565b80516060906031906000805b82811080156134ed5750838682815181106134e3576134e3614168565b016020015160f81c145b156134fe57600191820191016134c6565b5060008080806117e361209f8702046001016002026001600160401b0381111561352a5761352a613cef565b6040519080825280601f01601f191660200182016040528015613554576020820181803683370190505b5090506000600460038801046001600160401b0381111561357757613577613cef565b6040519080825280602002602001820160405280156135a0578160200160208202803683370190505b50905060005b8a518110156136c25760008b82815181106135c3576135c3614168565b602001015160f81c60f81b90506135f26040518060600160405280603a815260200161443c603a9139826138d5565b90965094508461363b5760405162461bcd60e51b81526020600482015260146024820152731a5b9d985b1a590818985cd94d4e08191a59da5d60621b60448201526064016107e3565b8251600019015b600081126136b8578684828151811061365d5761365d614168565b602002602001015163ffffffff16603a026001600160401b0316019750602088901c96508763ffffffff1684828151811061369a5761369a614168565b63ffffffff9092166020928302919091019091015260001901613642565b50506001016135a6565b50600860038816026001600160401b0381166000036136df575060205b600719016000805b8351811015613789575b6020836001600160401b0316101561377d57826001600160401b031684828151811061371f5761371f614168565b602002602001015163ffffffff16901c60f81b85838151811061374457613744614168565b60200101906001600160f81b031916908160001a90535060019091019060086001600160401b0384161061377d576008830392506136f1565b601892506001016136e7565b50875b84518110156137e757600060f81b8582815181106137ac576137ac614168565b01602001516001600160f81b03191611156137df576137ce858a830384613938565b9d9c50505050505050505050505050565b60010161378c565b506137f484600083613938565b9c9b505050505050505050505050565b612780612fe4565b6000816000036138505760405162461bcd60e51b815260206004820152600f60248201526e4d6f64756c7573206973207a65726f60881b60448201526064016107e3565b8360000361386057506000610ac9565b8260000361387057506001610ac9565b6001600160ff1b5b80156138cc57838186161515870a85848509099150836002820486161515870a85848509099150836004820486161515870a85848509099150836008820486161515870a8584850909915060109004613878565b50949350505050565b60008060005b845181101561392857836001600160f81b03191685828151811061390157613901614168565b01602001516001600160f81b0319160361392057915060019050613931565b6001016138db565b50600080915091505b9250929050565b606060008383036001600160401b0381111561395657613956613cef565b6040519080825280601f01601f191660200182016040528015613980576020820181803683370190505b50905060005b8484038110156138cc5785858201815181106139a4576139a4614168565b602001015160f81c60f81b8282815181106139c1576139c1614168565b60200101906001600160f81b031916908160001a905350600101613986565b6000602082840312156139f257600080fd5b5035919050565b60005b83811015613a145781810151838201526020016139fc565b50506000910152565b60008151808452613a358160208601602086016139f9565b601f01601f19169290920160200192915050565b602081526000610ac96020830184613a1d565b6001600160a01b03811681146127b357600080fd5b60008060408385031215613a8457600080fd5b8235613a8f81613a5c565b946020939093013593505050565b8035600381106107ec57600080fd5b600060208284031215613abe57600080fd5b610ac982613a9d565b60008083601f840112613ad957600080fd5b5081356001600160401b03811115613af057600080fd5b60208301915083602082850101111561393157600080fd5b600080600060408486031215613b1d57600080fd5b613b2684613a9d565b925060208401356001600160401b03811115613b4157600080fd5b613b4d86828701613ac7565b9497909650939450505050565b60008060008060808587031215613b7057600080fd5b5050823594602084013594506040840135936060013592509050565b600080600060608486031215613ba157600080fd5b8335613bac81613a5c565b92506020840135613bbc81613a5c565b929592945050506040919091013590565b600080600060408486031215613be257600080fd5b8335925060208401356001600160401b03811115613b4157600080fd5b60008083601f840112613c1157600080fd5b5081356001600160401b03811115613c2857600080fd5b6020830191508360208260051b850101111561393157600080fd5b60008060008060408587031215613c5957600080fd5b84356001600160401b0380821115613c7057600080fd5b613c7c88838901613bff565b90965094506020870135915080821115613c9557600080fd5b50613ca287828801613bff565b95989497509550505050565b60008060208385031215613cc157600080fd5b82356001600160401b03811115613cd757600080fd5b613ce385828601613bff565b90969095509350505050565b634e487b7160e01b600052604160045260246000fd5b60006001600160401b0380841115613d1f57613d1f613cef565b604051601f8501601f19908116603f01168101908282118183101715613d4757613d47613cef565b81604052809350858152868686011115613d6057600080fd5b858560208301376000602087830101525050509392505050565b600082601f830112613d8b57600080fd5b610ac983833560208501613d05565b60008060408385031215613dad57600080fd5b82356001600160401b0380821115613dc457600080fd5b613dd086838701613d7a565b93506020850135915080821115613de657600080fd5b50613df385828601613d7a565b9150509250929050565b60008060408385031215613e1057600080fd5b613e1983613a9d565b91506020830135613e2981613a5c565b809150509250929050565b634e487b7160e01b600052602160045260246000fd5b600381106127b357634e487b7160e01b600052602160045260246000fd5b60208101613e7583613e4a565b91905290565b600060208284031215613e8d57600080fd5b8135610ac981613a5c565b600080600060608486031215613ead57600080fd5b833592506020840135613bbc81613a5c565b600060208284031215613ed157600080fd5b81356001600160f81b031981168114610ac957600080fd5b60008060208385031215613efc57600080fd5b82356001600160401b03811115613f1257600080fd5b613ce385828601613ac7565b600060608284031215613f3057600080fd5b50919050565b600080600060808486031215613f4b57600080fd5b613f558585613f1e565b925060608401356001600160401b03811115613b4157600080fd5b600060208284031215613f8257600080fd5b81356001600160401b03811115613f9857600080fd5b610c3084828501613d7a565b600060208284031215613fb657600080fd5b81356001600160401b03811115613fcc57600080fd5b8201601f81018413613fdd57600080fd5b610c3084823560208401613d05565b60008060408385031215613fff57600080fd5b8235613e1981613a5c565b60006060828403121561401c57600080fd5b610ac98383613f1e565b600181811c9082168061403a57607f821691505b602082108103613f3057634e487b7160e01b600052602260045260246000fd5b6000808585111561406a57600080fd5b8386111561407757600080fd5b5050820193919092039150565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156106fe576106fe61409a565b808201808211156106fe576106fe61409a565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6060815260006141136060830186886140d6565b6020830194909452506040015292915050565b60208082526022908201527f6c6e4254433a206f6e6c79206d696e74657220616c6c6f77656420746f206d696040820152611b9d60f21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600083516141908184602088016139f9565b8351908301906141a48183602088016139f9565b01949350505050565b600082516141bf8184602087016139f9565b9190910192915050565b6000602082840312156141db57600080fd5b5051919050565b6141eb83613e4a565b828152604060208201526000610c306040830184613a1d565b8381526040602082015260006129976040830184866140d6565b60006020828403121561423057600080fd5b81518015158114610ac957600080fd5b828152600082516142588160208501602087016139f9565b919091016020019392505050565b60008261427557614275614084565b500690565b80820281158282048414176106fe576106fe61409a565b6040815260006142a46040830185613a1d565b82810360208401526129978185613a1d565b6040815260006142c96040830185613a1d565b90508260208301529392505050565b6000826142e7576142e7614084565b500490565b601f821115610fc7576000816000526020600020601f850160051c810160208610156143155750805b601f850160051c820191505b8181101561433457828155600101614321565b505050505050565b81516001600160401b0381111561435557614355613cef565b614369816143638454614026565b846142ec565b602080601f83116001811461439e57600084156143865750858301515b600019600386901b1c1916600185901b178555614334565b600085815260208120601f198616915b828110156143cd578886015182559484019460019091019084016143ae565b50858210156143eb5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00cd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330031323334353637383941424344454647484a4b4c4d4e505152535455565758595a6162636465666768696a6b6d6e6f707172737475767778797aa2646970667358221220444377d4d939bf4858dcea5516961daedd304474e0c4090136a8ef9d29f98ce064736f6c63430008180033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102745760003560e01c806370a0823111610151578063a9059cbb116100c3578063d9ab380111610087578063d9ab3801146105b5578063dd62ed3e146105c8578063e07fbd00146105db578063f2fde38b146105ee578063f376ebbb14610601578063fca3b5aa1461061457600080fd5b8063a9059cbb14610556578063af7b817014610569578063c4d66de81461057c578063d354c65d1461058f578063d3b6d7f5146105a257600080fd5b80638456cb59116101155780638456cb59146104e75780638da5cb5b146104ef57806395d89b411461051f5780639647ea37146105275780639fd956871461053a578063a7ce45651461054d57600080fd5b806370a0823114610470578063715018a6146104a6578063780f8df3146104ae5780637b8d3cb4146104c157806380cf79c8146104d457600080fd5b8063313ce567116101ea5780634ae1d1e5116101ae5780634ae1d1e5146103eb5780634cac70ff146103fe5780635187599d146104115780635abdb0dc146104245780635c975abb146104375780636739afca1461044f57600080fd5b8063313ce567146103a95780633d003000146103be5780633f4ba83a146103d157806342193473146103d9578063457e1a49146103e257600080fd5b80630b2aeb6c1161023c5780630b2aeb6c146103175780630fde6e551461032a57806318160ddd1461033d57806323b872dd1461036e57806324b76fd5146103815780633082599e1461039657600080fd5b8063026034f01461027957806306fdde03146102b157806307546172146102c6578063095ea7b3146102f15780630b2a158514610304575b600080fd5b61029c6102873660046139e0565b60046020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6102b9610627565b6040516102a89190613a49565b6003546102d9906001600160a01b031681565b6040516001600160a01b0390911681526020016102a8565b61029c6102ff366004613a71565b6106ea565b6102b9610312366004613aac565b610704565b61029c610325366004613b08565b6107f1565b61029c610338366004613b5a565b610ad0565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b6040519081526020016102a8565b61029c61037c366004613b8c565b610c38565b61039461038f366004613bcd565b610c5c565b005b6102b96103a4366004613aac565b610db2565b60085b60405160ff90911681526020016102a8565b6103946103cc366004613c43565b610e56565b610394610f5a565b61036061022281565b61036060015481565b6103946103f9366004613cae565b610f6c565b61029c61040c366004613d9a565b610fcc565b61039461041f366004613dfd565b611054565b6103946104323660046139e0565b611202565b60008051602061441c8339815191525460ff1661029c565b60005461046390600160a01b900460ff1681565b6040516102a89190613e68565b61036061047e366004613e7b565b6001600160a01b031660009081526000805160206143fc833981519152602052604090205490565b610394611287565b6103946104bc366004613e98565b611299565b6103ac6104cf366004613ebf565b6112d6565b6103606104e23660046139e0565b6116bb565b61039461177b565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03166102d9565b6102b961178b565b61029c610535366004613ee9565b6117ca565b610394610548366004613f36565b611d00565b61036060025481565b61029c610564366004613a71565b611e71565b61029c610577366004613f70565b611e7f565b61039461058a366004613e7b565b611eda565b61029c61059d366004613fa4565b611f0d565b6103606105b0366004613f70565b61253e565b6102b96105c3366004613aac565b612628565b6103606105d6366004613fec565b6126d4565b6103606105e936600461400a565b61271e565b6103946105fc366004613e7b565b612778565b6000546102d9906001600160a01b031681565b610394610622366004613e7b565b6127b6565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0380546060916000805160206143fc8339815191529161066690614026565b80601f016020809104026020016040519081016040528092919081815260200182805461069290614026565b80156106df5780601f106106b4576101008083540402835291602001916106df565b820191906000526020600020905b8154815290600101906020018083116106c257829003601f168201915b505050505091505090565b6000336106f88185856127e0565b60019150505b92915050565b6060600082600281111561071a5761071a613e34565b0361073c5750506040805180820190915260018152603360f81b602082015290565b600282600281111561075057610750613e34565b036107725750506040805180820190915260018152606d60f81b602082015290565b600182600281111561078657610786613e34565b036107a85750506040805180820190915260018152606d60f81b602082015290565b60405162461bcd60e51b8152602060048201526014602482015273556e6b6e6f776e206e6574776f726b207479706560601b60448201526064015b60405180910390fd5b919050565b6000606061083684848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250859250610fcc915050565b15610845576000915050610ac9565b610877604051806040016040528060118152602001700a7261772061646472657373206461746160781b8152506127ed565b6108b684848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061283092505050565b60006108c186610db2565b905060006108ce87610704565b905061091d6108e160016000888a61405a565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250869250610fcc915050565b80610970575061097061093460016000888a61405a565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250859250610fcc915050565b156109f057601a8510806109845750602385115b806109cb57506109c986868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e7f92505050565b155b156109dc5760009350505050610ac9565b6109e686866117ca565b9350505050610ac9565b60006109fb88612628565b8051909150610a1190610934906000898b61405a565b15610ac0576002886002811115610a2a57610a2a613e34565b03610a5557602b861080610a3e5750603f86115b15610a50576000945050505050610ac9565b610a76565b602a861080610a645750603e86115b15610a76576000945050505050610ac9565b610ab587878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f0d92505050565b945050505050610ac9565b60009450505050505b9392505050565b60006401000003d01985101580610aed57506401000003d0198410155b80610b0a575070014551231950b75fc4402da1732fc9bebe198310155b15610b1757506000610c30565b600080610b2386612873565b9150915080610b3757600092505050610c30565b6000610b448789876128ce565b9050600070014551231950b75fc4402da1732fc9bebe19898809610b7a9070014551231950b75fc4402da1732fc9bebe196140b0565b9050600070014551231950b75fc4402da1732fc9bebe198a8409610bb09070014551231950b75fc4402da1732fc9bebe196140b0565b60408051600080825260208201808452869052601b92820192909252606081018d9052608081018390529192509060019060a0016020604051602081039080840390855afa158015610c06573d6000803e3d6000fd5b505050602060405103519050856001600160a01b0316816001600160a01b03161496505050505050505b949350505050565b600033610c468582856129a0565b610c51858585612a06565b506001949350505050565b610c64612a65565b600154831015610cdc5760405162461bcd60e51b815260206004820152603e60248201527f5468652073656e742076616c7565206d7573742062652067726561746572206f60448201527f7220657175616c20746f206d696e20776974686472617720616d6f756e74000060648201526084016107e3565b600054610cf490600160a01b900460ff1683836107f1565b610d4a5760405162461bcd60e51b815260206004820152602160248201527f5468652073656e74204254432061646472657373206973206e6f742076616c696044820152601960fa1b60648201526084016107e3565b610d543384612a96565b600160026000828254610d6791906140c3565b909155505060025460405133917f83c16822c691a011b471d2653b84faff158a050c4e117390a6c008ecdefcc14e91610da5918691869189916140ff565b60405180910390a2505050565b60606000826002811115610dc857610dc8613e34565b03610dea5750506040805180820190915260018152603160f81b602082015290565b6002826002811115610dfe57610dfe613e34565b03610e205750506040805180820190915260018152601960f91b602082015290565b6001826002811115610e3457610e34613e34565b036107a85750506040805180820190915260018152601960f91b602082015290565b610e5e612a65565b6003546001600160a01b03163314610e885760405162461bcd60e51b81526004016107e390614126565b828114610ed75760405162461bcd60e51b815260206004820152601d60248201527f6c6e4254433a20617272617973206c656e677468206d69736d6174636800000060448201526064016107e3565b60005b83811015610f5357848482818110610ef457610ef4614168565b9050602002013560000315610f4b57610f4b838383818110610f1857610f18614168565b9050602002016020810190610f2d9190613e7b565b868684818110610f3f57610f3f614168565b90506020020135612ad0565b600101610eda565b5050505050565b610f62612b06565b610f6a612b61565b565b610f74612b06565b60005b81811015610fc757600160046000858585818110610f9757610f97614168565b60209081029290920135835250810191909152604001600020805460ff1916911515919091179055600101610f77565b505050565b60008151835114610fdf575060006106fe565b60005b835181101561104a57828181518110610ffd57610ffd614168565b602001015160f81c60f81b6001600160f81b03191684828151811061102457611024614168565b01602001516001600160f81b031916146110425760009150506106fe565b600101610fe2565b5060019392505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff1615906001600160401b03166000811580156110995750825b90506000826001600160401b031660011480156110b55750303b155b9050811580156110c3575080155b156110e15760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561110b57845460ff60401b1916600160401b1785555b6111586040518060400160405280600e81526020016d29ba3937b7b6902134ba31b7b4b760911b81525060405180604001604052806005815260200164737442544360d81b815250612bc1565b611160612bd3565b61116986611eda565b6107d060015560006002818155815489929160ff60a01b1990911690600160a01b90849081111561119c5761119c613e34565b0217905550600380546001600160a01b0319163317905583156111f957845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b61120a612b06565b6102228110156112825760405162461bcd60e51b815260206004820152603c60248201527f4d696e20776974686472617720616d6f756e742073686f756c6420626520677260448201527f6561746572206f7220657175616c20746f2064757374206c696d69740000000060648201526084016107e3565b600155565b61128f612b06565b610f6a6000612be3565b6112a1612a65565b6003546001600160a01b031633146112cb5760405162461bcd60e51b81526004016107e390614126565b610fc7838383612c54565b6000600d60fc1b6001600160f81b03198316016112f55750600f919050565b606760f91b6001600160f81b03198316016113125750600a919050565b60cd60f81b6001600160f81b031983160161132f57506011919050565b603360fa1b6001600160f81b031983160161134c57506015919050565b60cb60f81b6001600160f81b031983160161136957506014919050565b606560f91b6001600160f81b03198316016113865750601a919050565b601960fb1b6001600160f81b03198316016113a357506007919050565b60c960f81b6001600160f81b03198316016113c05750601e919050565b60c760f81b6001600160f81b03198316016113dd57506005919050565b608f60f81b6001600160f81b03198316016113fa57506000919050565b600960fc1b6001600160f81b031983160161141757506001919050565b604360f91b6001600160f81b031983160161143457506002919050565b604760f91b6001600160f81b031983160161145157506003919050565b608760f81b6001600160f81b031983160161146e57506004919050565b601160fb1b6001600160f81b031983160161148b57506006919050565b609960f81b6001600160f81b03198316016114a857506008919050565b604d60f91b6001600160f81b03198316016114c557506009919050565b602360fa1b6001600160f81b03198316016114e25750600b919050565b604560f91b6001600160f81b03198316016114ff5750600c919050565b602760fa1b6001600160f81b031983160161151c5750600d919050565b608960f81b6001600160f81b03198316016115395750600e919050565b608d60f81b6001600160f81b031983160161155657506010919050565b604b60f91b6001600160f81b031983160161157357506012919050565b604960f91b6001600160f81b031983160161159057506013919050565b609560f81b6001600160f81b03198316016115ad57506016919050565b601360fb1b6001600160f81b03198316016115ca57506017919050565b609d60f81b6001600160f81b03198316016115e757506018919050565b609b60f81b6001600160f81b031983160161160457506019919050565b609360f81b6001600160f81b03198316016116215750601b919050565b608b60f81b6001600160f81b031983160161163e5750601c919050565b609f60f81b6001600160f81b031983160161165b5750601d919050565b602560fa1b6001600160f81b03198316016116785750601f919050565b6116aa6040518060400160405280601181526020017024b73b30b634b21031b430b930b1ba32b960791b8152506127ed565b6116b382612e01565b5060ff919050565b6000601982901c6001601d84901c8116146116d75760006116dd565b632a1462b35b63ffffffff16600382901c6001166001146116f95760006116ff565b633d4233dd5b63ffffffff16600283901c60011660011461171b576000611721565b631ea119fa5b63ffffffff16600184811c81161461173a576000611740565b6326508e6d5b63ffffffff1660018086161461175757600061175d565b633b6a57b25b63ffffffff166005886301ffffff16901b1818181818915050919050565b611783612b06565b610f6a612e4a565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0480546060916000805160206143fc8339815191529161066690614026565b60008061180c84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612e9392505050565b90506118456040518060400160405280601681526020017576616c6964617465426173653538436865636b73756d60501b8152506127ed565b61186d604051806040016040528060078152602001661c185e5b1bd85960ca1b8152506127ed565b61187681612830565b80516019146118895760009150506106fe565b604080516001808252818301909252600091602082018180368337019050509050816000815181106118bd576118bd614168565b602001015160f81c60f81b816000815181106118db576118db614168565b60200101906001600160f81b031916908160001a90535061191a604051806040016040528060078152602001663b32b939b4b7b760c91b8152506127ed565b61192381612830565b600060046001845161193591906140b0565b61193f91906140b0565b6001600160401b0381111561195657611956613cef565b6040519080825280601f01601f191660200182016040528015611980576020820181803683370190505b50905060005b60046001855161199691906140b0565b6119a091906140b0565b8110156119ff57836119b38260016140c3565b815181106119c3576119c3614168565b602001015160f81c60f81b8282815181106119e0576119e0614168565b60200101906001600160f81b031916908160001a905350600101611986565b50611a28604051806040016040528060078152602001661c185e5b1bd85960ca1b8152506127ed565b611a3181612830565b8051601414611a4657600093505050506106fe565b60408051600480825281830190925260009160208201818036833701905050905060005b6004811015611ad957848160048751611a8391906140b0565b611a8d91906140c3565b81518110611a9d57611a9d614168565b602001015160f81c60f81b828281518110611aba57611aba614168565b60200101906001600160f81b031916908160001a905350600101611a6a565b50611b0360405180604001604052806008815260200167636865636b73756d60c01b8152506127ed565b611b0c81612830565b60006002808585604051602001611b2492919061417e565b60408051601f1981840301815290829052611b3e916141ad565b602060405180830381855afa158015611b5b573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190611b7e91906141c9565b604051602001611b9091815260200190565b60408051601f1981840301815290829052611baa916141ad565b602060405180830381855afa158015611bc7573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190611bea91906141c9565b9050611c206040518060400160405280601381526020017263616c63756c6174656420636865636b73756d60681b8152506127ed565b611c2981612e9e565b8060031a60f81b82600381518110611c4357611c43614168565b01602001516001600160f81b031916188160021a60f81b83600281518110611c6d57611c6d614168565b01602001516001600160f81b031916188260011a60f81b84600181518110611c9757611c97614168565b01602001516001600160f81b031916188360001a60f81b85600081518110611cc157611cc1614168565b602001015160f81c60f81b181717176001600160f81b031916600060f81b14611cf2576000955050505050506106fe565b506001979650505050505050565b611d08612a65565b6000611d1384612ee3565b6000546040516372ee4c8760e01b8152859185916001600160a01b039091169063f9a8bc489082906372ee4c8790611d5190899089906004016141e2565b602060405180830381865afa158015611d6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d9291906141c9565b84846040518463ffffffff1660e01b8152600401611db293929190614204565b602060405180830381865afa158015611dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df3919061421e565b611e535760405162461bcd60e51b815260206004820152602b60248201527f56616c696461746f724d65737361676552656365697665723a20494e56414c4960448201526a445f5349474e415455524560a81b60648201526084016107e3565b6111f960408801803590611e6a9060208b01613e7b565b8935612c54565b6000336106f8818585612a06565b6000805b8251811015611ed1576000838281518110611ea057611ea0614168565b016020015160f81c90506000611eb582612f3b565b905080611ec757506000949350505050565b5050600101611e83565b50600192915050565b611ee2612fe4565b611eeb3361302d565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000611f4d6040518060400160405280601981526020017f0a76616c69646174652062656368333220636865636b73756d000000000000008152506127ed565b611f75604051806040016040528060078152602001666164647265737360c81b8152506127ed565b611f7e826127ed565b8151829060081115611fbd57611fb4604051806040016040528060098152602001681d1bdbc81cda1bdc9d60ba1b8152506127ed565b50600092915050565b605a81511115611ff057611fb460405180604001604052806008815260200167746f6f206c6f6e6760c01b8152506127ed565b50816000805b825181101561203a5782818151811061201157612011614168565b01602001516001600160f81b031916603160f81b036120325780915061203a565b600101611ff6565b508060000361207a576120706040518060400160405280600c81526020016b37379039b2b830b930ba37b960a11b8152506127ed565b5060009392505050565b806001036120b1576120706040518060400160405280600e81526020016d0dad2e6e6d2dcce40e0e4caccd2f60931b8152506127ed565b6000816001600160401b038111156120cb576120cb613cef565b6040519080825280601f01601f1916602001820160405280156120f5576020820181803683370190505b5090506000600183855161210991906140b0565b61211391906140b0565b6001600160401b0381111561212a5761212a613cef565b6040519080825280601f01601f191660200182016040528015612154576020820181803683370190505b50905060005b838110156121b05784818151811061217457612174614168565b602001015160f81c60f81b83828151811061219157612191614168565b60200101906001600160f81b031916908160001a90535060010161215a565b5060005b815181101561221f57846121c885836140c3565b6121d39060016140c3565b815181106121e3576121e3614168565b602001015160f81c60f81b82828151811061220057612200614168565b60200101906001600160f81b031916908160001a9053506001016121b4565b50612247604051806040016040528060068152602001650e0e4caccd2f60d31b8152506127ed565b61225082612830565b600681511015612295576122896040518060400160405280600e81526020016d19185d18481d1bdbc81cda1bdc9d60921b8152506127ed565b50600095945050505050565b60006122a08361253e565b9050806000036122e6576122d96040518060400160405280600e81526020016d0d2dcecc2d8d2c840e0e4caccd2f60931b8152506127ed565b5060009695505050505050565b600082516001600160401b0381111561230157612301613cef565b6040519080825280601f01601f19166020018201604052801561232b576020820181803683370190505b50905060005b835181101561248457600084828151811061234e5761234e614168565b01602001516001600160f81b0319169050600061236a826112d6565b905060fe1960ff821601612422576123aa604051806040016040528060118152602001703ab735b737bbb71031b430b930b1ba32b960791b8152506127ed565b6123b38361303e565b6123bc82612e01565b6124116040518060400160405280600481526020016331b430b960e11b815250836040516020016123fd91906001600160f81b031991909116815260010190565b604051602081830303815290604052613083565b5060009a9950505050505050505050565b8060ff1661242f866116bb565b8751911895506124408460066140c3565b1061244c57505061247c565b8060f81b84848151811061246257612462614168565b60200101906001600160f81b031916908160001a90535050505b600101612331565b506124ab60405180604001604052806005815260200164776f72647360d81b8152506127ed565b6124b481612830565b632bc830a382141580156124c9575081600114155b1561250e576125006040518060400160405280601081526020016f696e76616c696420636865636b73756d60801b815250836130c8565b506000979650505050505050565b611cf26040518060400160405280600e81526020016d76616c696420636865636b73756d60901b815250836130c8565b60006001815b83518110156125d257600084828151811061256157612561614168565b016020015160f81c9050602181108061257a5750607e81115b156125b85760405162461bcd60e51b815260206004820152600e60248201526d092dcecc2d8d2c840e0e4caccd2f60931b60448201526064016107e3565b600581901c6125c6846116bb565b18925050600101612544565b506125dc816116bb565b905060005b83518110156126215760008482815181106125fe576125fe614168565b016020015160f81c9050601f8116612615846116bb565b189250506001016125e1565b5092915050565b6060600082600281111561263e5761263e613e34565b0361266257505060408051808201909152600381526262633160e81b602082015290565b600282600281111561267657612676613e34565b0361269c575050604080518082019091526005815264626372743160d81b602082015290565b60018260028111156126b0576126b0613e34565b036107a857505060408051808201909152600381526274623160e81b602082015290565b6001600160a01b0391821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b60007f7d21eae75cdfb1cf6d27ca9a73c6341b49bc05072228b51a7cd4df444c1c871061274a83612ee3565b60405160200161275b929190614240565b604051602081830303815290604052805190602001209050919050565b612780612b06565b6001600160a01b0381166127aa57604051631e4fbdf760e01b8152600060048201526024016107e3565b6127b381612be3565b50565b6127be612b06565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b610fc7838383600161310d565b6127b3816040516024016128019190613a49565b60408051601f198184030181529190526020810180516001600160e01b031663104c13eb60e21b1790526131f4565b6127b3816040516024016128449190613a49565b60408051601f198184030181529190526020810180516001600160e01b03166305f3bfab60e11b1790526131f4565b60008060008061288285613215565b9150915080612898575060009485945092505050565b50604080516020808201969096528082019290925280518083038201815260609092019052805193019290922092600192509050565b604080517f7bb52d7a9fef58323eb1bf7a407db382d2f3f2d81bb1224f49fe518f6d48d37c60208201819052918101829052606081018590526080810184905260a081018390526000919070014551231950b75fc4402da1732fc9bebe199060029060c00160408051601f198184030181529082905261294d916141ad565b602060405180830381855afa15801561296a573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061298d91906141c9565b6129979190614266565b95945050505050565b60006129ac84846126d4565b90506000198114612a0057818110156129f157604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064016107e3565b612a008484848403600061310d565b50505050565b6001600160a01b038316612a3057604051634b637e8f60e11b8152600060048201526024016107e3565b6001600160a01b038216612a5a5760405163ec442f0560e01b8152600060048201526024016107e3565b610fc78383836132da565b60008051602061441c8339815191525460ff1615610f6a5760405163d93c066560e01b815260040160405180910390fd5b6001600160a01b038216612ac057604051634b637e8f60e11b8152600060048201526024016107e3565b612acc826000836132da565b5050565b6001600160a01b038216612afa5760405163ec442f0560e01b8152600060048201526024016107e3565b612acc600083836132da565b33612b387f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610f6a5760405163118cdaa760e01b81523360048201526024016107e3565b612b69613418565b60008051602061441c833981519152805460ff191681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a150565b612bc9612fe4565b612acc8282613448565b612bdb612fe4565b610f6a613499565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60008311612c975760405162461bcd60e51b815260206004820152601060248201526f4d494e545f414d4f554e545f5a45524f60801b60448201526064016107e3565b612ca96305f5e1006301406f4061427a565b8310612ced5760405162461bcd60e51b81526020600482015260136024820152724d494e545f414d4f554e545f544f4f5f42494760681b60448201526064016107e3565b306001600160a01b03831603612d455760405162461bcd60e51b815260206004820152601c60248201527f4d494e545f544f5f5448455f434f4e54524143545f414444524553530000000060448201526064016107e3565b60008181526004602052604090205460ff1615612d9d5760405162461bcd60e51b81526020600482015260166024820152751352539517d053149150511657d41493d0d154d4d15160521b60448201526064016107e3565b6000818152600460205260409020805460ff19166001179055612dc08284612ad0565b60408051848152602081018390526001600160a01b038416917fb73f3e96d1e157f064cb3a8d0abed06bcec05e5515bf7486364c027dab6aa4699101610da5565b6040516001600160f81b0319821660248201526127b39060440160408051601f198184030181529190526020810180516001600160e01b0316630dc3142560e31b1790526131f4565b612e52612a65565b60008051602061441c833981519152805460ff191660011781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25833612ba3565b60606106fe826134ba565b6127b381604051602401612eb491815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166327b7cf8560e01b1790526131f4565b6060612ef56040830160208401613e7b565b6040805160609290921b6bffffffffffffffffffffffff191660208301528301356034820152823560548201526074016040516020818303038152906040529050919050565b60008160ff1660491480612f5257508160ff16604f145b80612f6057508160ff16606c145b15612f6d57506000919050565b60318260ff1610158015612f85575060398260ff1611155b15612f9257506001919050565b60418260ff1610158015612faa5750605a8260ff1611155b15612fb757506001919050565b60618260ff1610158015612fcf5750607a8260ff1611155b15612fdc57506001919050565b506000919050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff16610f6a57604051631afcd79f60e31b815260040160405180910390fd5b613035612fe4565b6127b381613804565b6127b38160405160240161305491815260200190565b60408051601f198184030181529190526020810180516001600160e01b031663f5b1bba960e01b1790526131f4565b612acc8282604051602401613099929190614291565b60408051601f198184030181529190526020810180516001600160e01b0316634b5c427760e01b1790526131f4565b612acc82826040516024016130de9291906142b6565b60408051601f198184030181529190526020810180516001600160e01b03166309710a9d60e41b1790526131f4565b6000805160206143fc8339815191526001600160a01b0385166131465760405163e602df0560e01b8152600060048201526024016107e3565b6001600160a01b03841661317057604051634a1406b160e11b8152600060048201526024016107e3565b6001600160a01b03808616600090815260018301602090815260408083209388168352929052208390558115610f5357836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925856040516131e591815260200190565b60405180910390a35050505050565b80516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b6000806401000003d01981600782861061323757506000958695509350505050565b6000838061324757613247614084565b848061325557613255614084565b83868061326457613264614084565b868b0908858061327657613276614084565b868061328457613284614084565b8a8b098a090890506132ad81600461329d8760016140c3565b6132a791906142d8565b8661380c565b9050600060018216156132c9576132c482866140b0565b6132cb565b815b98600198509650505050505050565b6000805160206143fc8339815191526001600160a01b038416613316578181600201600082825461330b91906140c3565b909155506133889050565b6001600160a01b038416600090815260208290526040902054828110156133695760405163391434e360e21b81526001600160a01b038616600482015260248101829052604481018490526064016107e3565b6001600160a01b03851660009081526020839052604090209083900390555b6001600160a01b0383166133a65760028101805483900390556133c5565b6001600160a01b03831660009081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161340a91815260200190565b60405180910390a350505050565b60008051602061441c8339815191525460ff16610f6a57604051638dfc202b60e01b815260040160405180910390fd5b613450612fe4565b6000805160206143fc8339815191527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0361348a848261433c565b5060048101612a00838261433c565b6134a1612fe4565b60008051602061441c833981519152805460ff19169055565b80516060906031906000805b82811080156134ed5750838682815181106134e3576134e3614168565b016020015160f81c145b156134fe57600191820191016134c6565b5060008080806117e361209f8702046001016002026001600160401b0381111561352a5761352a613cef565b6040519080825280601f01601f191660200182016040528015613554576020820181803683370190505b5090506000600460038801046001600160401b0381111561357757613577613cef565b6040519080825280602002602001820160405280156135a0578160200160208202803683370190505b50905060005b8a518110156136c25760008b82815181106135c3576135c3614168565b602001015160f81c60f81b90506135f26040518060600160405280603a815260200161443c603a9139826138d5565b90965094508461363b5760405162461bcd60e51b81526020600482015260146024820152731a5b9d985b1a590818985cd94d4e08191a59da5d60621b60448201526064016107e3565b8251600019015b600081126136b8578684828151811061365d5761365d614168565b602002602001015163ffffffff16603a026001600160401b0316019750602088901c96508763ffffffff1684828151811061369a5761369a614168565b63ffffffff9092166020928302919091019091015260001901613642565b50506001016135a6565b50600860038816026001600160401b0381166000036136df575060205b600719016000805b8351811015613789575b6020836001600160401b0316101561377d57826001600160401b031684828151811061371f5761371f614168565b602002602001015163ffffffff16901c60f81b85838151811061374457613744614168565b60200101906001600160f81b031916908160001a90535060019091019060086001600160401b0384161061377d576008830392506136f1565b601892506001016136e7565b50875b84518110156137e757600060f81b8582815181106137ac576137ac614168565b01602001516001600160f81b03191611156137df576137ce858a830384613938565b9d9c50505050505050505050505050565b60010161378c565b506137f484600083613938565b9c9b505050505050505050505050565b612780612fe4565b6000816000036138505760405162461bcd60e51b815260206004820152600f60248201526e4d6f64756c7573206973207a65726f60881b60448201526064016107e3565b8360000361386057506000610ac9565b8260000361387057506001610ac9565b6001600160ff1b5b80156138cc57838186161515870a85848509099150836002820486161515870a85848509099150836004820486161515870a85848509099150836008820486161515870a8584850909915060109004613878565b50949350505050565b60008060005b845181101561392857836001600160f81b03191685828151811061390157613901614168565b01602001516001600160f81b0319160361392057915060019050613931565b6001016138db565b50600080915091505b9250929050565b606060008383036001600160401b0381111561395657613956613cef565b6040519080825280601f01601f191660200182016040528015613980576020820181803683370190505b50905060005b8484038110156138cc5785858201815181106139a4576139a4614168565b602001015160f81c60f81b8282815181106139c1576139c1614168565b60200101906001600160f81b031916908160001a905350600101613986565b6000602082840312156139f257600080fd5b5035919050565b60005b83811015613a145781810151838201526020016139fc565b50506000910152565b60008151808452613a358160208601602086016139f9565b601f01601f19169290920160200192915050565b602081526000610ac96020830184613a1d565b6001600160a01b03811681146127b357600080fd5b60008060408385031215613a8457600080fd5b8235613a8f81613a5c565b946020939093013593505050565b8035600381106107ec57600080fd5b600060208284031215613abe57600080fd5b610ac982613a9d565b60008083601f840112613ad957600080fd5b5081356001600160401b03811115613af057600080fd5b60208301915083602082850101111561393157600080fd5b600080600060408486031215613b1d57600080fd5b613b2684613a9d565b925060208401356001600160401b03811115613b4157600080fd5b613b4d86828701613ac7565b9497909650939450505050565b60008060008060808587031215613b7057600080fd5b5050823594602084013594506040840135936060013592509050565b600080600060608486031215613ba157600080fd5b8335613bac81613a5c565b92506020840135613bbc81613a5c565b929592945050506040919091013590565b600080600060408486031215613be257600080fd5b8335925060208401356001600160401b03811115613b4157600080fd5b60008083601f840112613c1157600080fd5b5081356001600160401b03811115613c2857600080fd5b6020830191508360208260051b850101111561393157600080fd5b60008060008060408587031215613c5957600080fd5b84356001600160401b0380821115613c7057600080fd5b613c7c88838901613bff565b90965094506020870135915080821115613c9557600080fd5b50613ca287828801613bff565b95989497509550505050565b60008060208385031215613cc157600080fd5b82356001600160401b03811115613cd757600080fd5b613ce385828601613bff565b90969095509350505050565b634e487b7160e01b600052604160045260246000fd5b60006001600160401b0380841115613d1f57613d1f613cef565b604051601f8501601f19908116603f01168101908282118183101715613d4757613d47613cef565b81604052809350858152868686011115613d6057600080fd5b858560208301376000602087830101525050509392505050565b600082601f830112613d8b57600080fd5b610ac983833560208501613d05565b60008060408385031215613dad57600080fd5b82356001600160401b0380821115613dc457600080fd5b613dd086838701613d7a565b93506020850135915080821115613de657600080fd5b50613df385828601613d7a565b9150509250929050565b60008060408385031215613e1057600080fd5b613e1983613a9d565b91506020830135613e2981613a5c565b809150509250929050565b634e487b7160e01b600052602160045260246000fd5b600381106127b357634e487b7160e01b600052602160045260246000fd5b60208101613e7583613e4a565b91905290565b600060208284031215613e8d57600080fd5b8135610ac981613a5c565b600080600060608486031215613ead57600080fd5b833592506020840135613bbc81613a5c565b600060208284031215613ed157600080fd5b81356001600160f81b031981168114610ac957600080fd5b60008060208385031215613efc57600080fd5b82356001600160401b03811115613f1257600080fd5b613ce385828601613ac7565b600060608284031215613f3057600080fd5b50919050565b600080600060808486031215613f4b57600080fd5b613f558585613f1e565b925060608401356001600160401b03811115613b4157600080fd5b600060208284031215613f8257600080fd5b81356001600160401b03811115613f9857600080fd5b610c3084828501613d7a565b600060208284031215613fb657600080fd5b81356001600160401b03811115613fcc57600080fd5b8201601f81018413613fdd57600080fd5b610c3084823560208401613d05565b60008060408385031215613fff57600080fd5b8235613e1981613a5c565b60006060828403121561401c57600080fd5b610ac98383613f1e565b600181811c9082168061403a57607f821691505b602082108103613f3057634e487b7160e01b600052602260045260246000fd5b6000808585111561406a57600080fd5b8386111561407757600080fd5b5050820193919092039150565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156106fe576106fe61409a565b808201808211156106fe576106fe61409a565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6060815260006141136060830186886140d6565b6020830194909452506040015292915050565b60208082526022908201527f6c6e4254433a206f6e6c79206d696e74657220616c6c6f77656420746f206d696040820152611b9d60f21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600083516141908184602088016139f9565b8351908301906141a48183602088016139f9565b01949350505050565b600082516141bf8184602087016139f9565b9190910192915050565b6000602082840312156141db57600080fd5b5051919050565b6141eb83613e4a565b828152604060208201526000610c306040830184613a1d565b8381526040602082015260006129976040830184866140d6565b60006020828403121561423057600080fd5b81518015158114610ac957600080fd5b828152600082516142588160208501602087016139f9565b919091016020019392505050565b60008261427557614275614084565b500690565b80820281158282048414176106fe576106fe61409a565b6040815260006142a46040830185613a1d565b82810360208401526129978185613a1d565b6040815260006142c96040830185613a1d565b90508260208301529392505050565b6000826142e7576142e7614084565b500490565b601f821115610fc7576000816000526020600020601f850160051c810160208610156143155750805b601f850160051c820191505b8181101561433457828155600101614321565b505050505050565b81516001600160401b0381111561435557614355613cef565b614369816143638454614026565b846142ec565b602080601f83116001811461439e57600084156143865750858301515b600019600386901b1c1916600185901b178555614334565b600085815260208120601f198616915b828110156143cd578886015182559484019460019091019084016143ae565b50858210156143eb5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00cd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f0330031323334353637383941424344454647484a4b4c4d4e505152535455565758595a6162636465666768696a6b6d6e6f707172737475767778797aa2646970667358221220444377d4d939bf4858dcea5516961daedd304474e0c4090136a8ef9d29f98ce064736f6c63430008180033
Loading...
Loading
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.