Contract Overview
Balance:
0 MATIC
My Name Tag:
Not Available
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Similar Match Source Code
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0xe296F851f6644637f3Da91132f6b817742B143f8
Contract Name:
CCBurnRouter
Compiler Version
v0.8.2+commit.661d1103
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./interfaces/ICCBurnRouter.sol"; import "../erc20/interfaces/ITeleBTC.sol"; import "../relay/interfaces/IBitcoinRelay.sol"; import "../lockers/interfaces/ILockers.sol"; import "../libraries/BitcoinHelper.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "hardhat/console.sol"; contract CCBurnRouter is ICCBurnRouter, Ownable, ReentrancyGuard { modifier nonZeroAddress(address _address) { require(_address != address(0), "CCBurnRouter: address is zero"); _; } modifier nonZeroValue(uint _value) { require(_value > 0, "CCBurnRouter: value is zero"); _; } // Constants uint constant MAX_PROTOCOL_FEE = 10000; uint constant MAX_SLASHER_REWARD = 100; // Public variables address public override relay; address public override lockers; address public override teleBTC; address public override treasury; uint public override transferDeadline; uint public override protocolPercentageFee; // Min amount is %0.01 uint public override slasherPercentageReward; // Min amount is %1 uint public override bitcoinFee; // Fee of submitting a tx on Bitcoin mapping(address => burnRequest[]) public burnRequests; // Mapping from locker target address to assigned burn requests mapping(address => uint) public burnRequestCounter; mapping(bytes32 => bool) public override isUsedAsBurnProof; // Mapping that shows a txId has been submitted to pay a burn request /// @notice Handles cross-chain burn requests /// @param _relay Address of relay contract /// @param _lockers Address of lockers contract /// @param _treasury Address of the treasury of the protocol /// @param _transferDeadline Dealine of sending BTC to user (aster submitting a burn request) /// @param _protocolPercentageFee Percentage of tokens that user pays to protocol for burning /// @param _slasherPercentageReward Percentage of tokens that slasher receives after slashing a locker /// @param _bitcoinFee Fee of submitting a transaction on Bitcoin constructor( address _relay, address _lockers, address _treasury, uint _transferDeadline, uint _protocolPercentageFee, uint _slasherPercentageReward, uint _bitcoinFee ) { relay = _relay; lockers = _lockers; treasury = _treasury; transferDeadline = _transferDeadline; protocolPercentageFee = _protocolPercentageFee; slasherPercentageReward = _slasherPercentageReward; bitcoinFee = _bitcoinFee; } receive() external payable {} /// @notice Shows if a burn request has been done or not /// @param _lockerTargetAddress Locker's address on the target chain /// @param _index The index of the request for the locker function isTransferred( address _lockerTargetAddress, uint _index ) external view override returns (bool) { return burnRequests[_lockerTargetAddress][_index].isTransferred; } /// @notice Changes relay contract address /// @dev Only owner can call this /// @param _relay The new relay contract address function setRelay(address _relay) external nonZeroAddress(_relay) override onlyOwner { relay = _relay; } /// @notice Changes lockers contract address /// @dev Only owner can call this /// @param _lockers The new lockers contract address function setLockers(address _lockers) external nonZeroAddress(_lockers) override onlyOwner { lockers = _lockers; } /// @notice Changes teleBTC contract address /// @dev Only owner can call this /// @param _teleBTC The new teleBTC contract address function setTeleBTC(address _teleBTC) external nonZeroAddress(_teleBTC) override onlyOwner { teleBTC = _teleBTC; } /// @notice Changes protocol treasury address /// @dev Only owner can call this /// @param _treasury The new treasury address function setTreasury(address _treasury) external nonZeroAddress(_treasury) override onlyOwner { treasury = _treasury; } /// @notice Changes deadline of executing burn requests /// @dev Only owner can call this /// Deadline shoudl be greater than relay finalization parameter /// @param _transferDeadline The new transfer deadline function setTransferDeadline(uint _transferDeadline) external override onlyOwner { uint _finalizationParameter = IBitcoinRelay(relay).finalizationParameter(); // Gives lockers enough time to pay cc burn requests require(_transferDeadline > _finalizationParameter, "CCBurnRouter: transfer deadline is too low"); transferDeadline = _transferDeadline; } /// @notice Changes protocol percentage fee for burning tokens /// @dev Only owner can call this /// @param _protocolPercentageFee The new protocol percentage fee function setProtocolPercentageFee(uint _protocolPercentageFee) external override onlyOwner { require(MAX_PROTOCOL_FEE >= _protocolPercentageFee, "CCBurnRouter: protocol fee is out of range"); protocolPercentageFee = _protocolPercentageFee; } /// @notice Changes slasher percentage reward for disputing lockers /// @dev Only owner can call this /// @param _slasherPercentageReward The new slasher percentage reward function setSlasherPercentageReward(uint _slasherPercentageReward) external override onlyOwner { require(MAX_SLASHER_REWARD >= _slasherPercentageReward, "CCBurnRouter: slasher percentage reward is out of range"); slasherPercentageReward = _slasherPercentageReward; } /// @notice Changes Bitcoin transaction fee /// @dev Only owner can call this /// @param _bitcoinFee The new Bitcoin transaction fee function setBitcoinFee(uint _bitcoinFee) external override onlyOwner { bitcoinFee = _bitcoinFee; } /// @notice Burns teleBTC and records the burn request /// @dev After submitting the burn request, lockers have a limited time /// to send BTC and provide burn proof /// @param _amount Amount of teleBTC that user wants to burn /// @param _userScript User's script /// @param _lockerLockingScript Locking script of locker that should execute the burn request /// @return _burntAmount Amount of teleBTC that user will receive (after reducing fees) function ccBurn( uint _amount, bytes memory _userScript, ScriptTypes _scriptType, bytes calldata _lockerLockingScript ) external nonReentrant nonZeroValue(_amount) override returns (uint _burntAmount) { // Checks validity of user's script _checkScriptType(_userScript, _scriptType); // Checks if the given locking script is locker require( ILockers(lockers).isLocker(_lockerLockingScript), "CCBurnRouter: given locking script is not locker" ); /* Gets the target address of locker note: we don't check whether _lockerTargetAddress is equal to zero or not since _lockerLockingScript is locker */ address _lockerTargetAddress = ILockers(lockers) .getLockerTargetAddress(_lockerLockingScript); // Transfers users's teleBTC ITeleBTC(teleBTC).transferFrom(_msgSender(), address(this), _amount); uint remainedAmount = _getFees( _amount, _lockerTargetAddress ); // Burns remained teleBTC ITeleBTC(teleBTC).approve(lockers, remainedAmount); _burntAmount = ILockers(lockers).burn(_lockerLockingScript, remainedAmount); _saveBurnRequest( _amount, _burntAmount, _userScript, _scriptType, IBitcoinRelay(relay).lastSubmittedHeight(), _lockerTargetAddress ); emit CCBurn( _msgSender(), _userScript, _scriptType, _amount, _burntAmount, _lockerTargetAddress, _lockerLockingScript, burnRequests[_lockerTargetAddress][burnRequests[_lockerTargetAddress].length - 1].requestIdOfLocker, burnRequests[_lockerTargetAddress][burnRequests[_lockerTargetAddress].length - 1].deadline ); } /// @notice Checks the correctness of burn proof /// @dev Makes isTransferred flag true for the paid requests /// @param _version Version of the transaction containing the burn transaction /// @param _vin Inputs of the transaction containing the burn transaction /// @param _vout Outputs of the transaction containing the burn transaction /// @param _locktime Lock time of the transaction containing the burn transaction /// @param _blockNumber Height of the block containing the burn transaction /// @param _intermediateNodes Merkle inclusion proof for transaction containing the burn transaction /// @param _index Index of transaction containing the burn transaction in the block /// @param _lockerLockingScript Locker's locking script (on Bitcoin) that this burn request belongs to /// @param _burnReqIndexes Indexes of requests that locker wants to provide proof for them /// @param _voutIndexes Indexes of outputs that were used to pay burn requests (_voutIndexes[i] belongs to _burnReqIndexes[i]) /// @return function burnProof( bytes4 _version, bytes memory _vin, bytes memory _vout, bytes4 _locktime, uint256 _blockNumber, bytes memory _intermediateNodes, uint _index, bytes memory _lockerLockingScript, uint[] memory _burnReqIndexes, uint[] memory _voutIndexes ) external payable nonReentrant override returns (bool) { // Checks that locker's tx doesn't have any locktime require(_locktime == bytes4(0), "CCBurnRouter: non-zero lock time"); // Checks if the locking script is valid require( ILockers(lockers).isLocker(_lockerLockingScript), "CCBurnRouter: given locking script is not locker" ); // Get the target address of the locker from its locking script address _lockerTargetAddress = ILockers(lockers) .getLockerTargetAddress(_lockerLockingScript); require( _burnReqIndexes.length == _voutIndexes.length, "CCBurnRouter: wrong indexes" ); // Checks inclusion of transaction bytes32 txId = BitcoinHelper.calculateTxId(_version, _vin, _vout, _locktime); require( _isConfirmed( txId, _blockNumber, _intermediateNodes, _index ), "CCBurnRouter: transaction has not finalized yet" ); // Checks the paid burn requests uint paidOutputCounter = _checkPaidBurnRequests( txId, _blockNumber, _lockerTargetAddress, _vout, _burnReqIndexes, _voutIndexes ); /* Checks if there is an output that goes back to the locker Sets isUsedAsBurnProof of txId true if all the outputs (except one) were used to pay cc burn requests */ _updateIsUsedAsBurnProof(paidOutputCounter, _vout, _lockerLockingScript, txId); return true; } /// @notice Slashes a locker if she did not paid a cc burn request before its deadline /// @param _lockerLockingScript locker's locking script that the unpaid request belongs to /// @param _indices Array of indices of the requests that their deadline has passed /// @return True if dispute is successfull function disputeBurn( bytes calldata _lockerLockingScript, uint[] memory _indices ) external nonReentrant override returns (bool) { // Checks if the locking script is valid require( ILockers(lockers).isLocker(_lockerLockingScript), "CCBurnRouter: given locking script is not locker" ); // Get the target address of the locker from its locking script address _lockerTargetAddress = ILockers(lockers) .getLockerTargetAddress(_lockerLockingScript); uint _lastSubmittedHeight = IBitcoinRelay(relay).lastSubmittedHeight(); // Goes through provided indexes of burn requests to see if locker should be slashed for (uint i = 0; i < _indices.length; i++) { // Checks that locker has not provided burn proof require( !burnRequests[_lockerTargetAddress][_indices[i]].isTransferred, "CCBurnRouter: request has been paid before" ); // Checks that payback deadline has passed require( burnRequests[_lockerTargetAddress][_indices[i]].deadline < _lastSubmittedHeight, "CCBurnRouter: payback deadline has not passed yet" ); // Sets "isTransferred = true" to prevent slashing the locker again burnRequests[_lockerTargetAddress][_indices[i]].isTransferred = true; // Slashes locker and sends the slashed amount to the user ILockers(lockers).slashIdleLocker( _lockerTargetAddress, burnRequests[_lockerTargetAddress][_indices[i]].amount*slasherPercentageReward/MAX_SLASHER_REWARD, // Slasher reward _msgSender(), // Slasher address burnRequests[_lockerTargetAddress][_indices[i]].amount, burnRequests[_lockerTargetAddress][_indices[i]].sender // User address ); emit BurnDispute( burnRequests[_lockerTargetAddress][_indices[i]].sender, _lockerTargetAddress, _lockerLockingScript, burnRequests[_lockerTargetAddress][_indices[i]].requestIdOfLocker ); } return true; } /// @notice Slashes a locker if they issue a tx that doesn't match any burn request /// @dev Input tx is a malicious tx which shows that locker spent BTC /// Output tx is the tx that was spent by locker in input tx /// Output tx --> money goes to locker --> Input tx --> locker steals the funds /// @param _lockerLockingScript Suspicious locker's locking script /// @param _versions Versions of input and output tx /// @param _inputVin Inputs of the malicious transaction /// @param _inputVout Outputs of the malicious transaction /// @param _outputVin Inputs of the spent transaction /// @param _outputVout Outputs of the spent transaction /// @param _locktimes Locktimes of input and output tx /// @param _inputIntermediateNodes Merkle inclusion proof for the malicious transaction /// @param _indexesAndBlockNumbers Indices of malicious input in input tx, input tx in block and block number of input tx /// @return True if dispute is successfull function disputeLocker( bytes memory _lockerLockingScript, bytes4[] memory _versions, // [inputTxVersion, outputTxVersion] bytes memory _inputVin, bytes memory _inputVout, bytes memory _outputVin, bytes memory _outputVout, bytes4[] memory _locktimes, // [inputTxLocktime, outputTxLocktime] bytes memory _inputIntermediateNodes, uint[] memory _indexesAndBlockNumbers // [inputIndex, inputTxIndex, inputTxBlockNumber] ) external payable nonReentrant override returns (bool) { // Checks input array sizes require( _versions.length == 2 && _locktimes.length == 2 && _indexesAndBlockNumbers.length == 3, "CCBurnRouter: wrong inputs" ); // Checks if the locking script is valid require( ILockers(lockers).isLocker(_lockerLockingScript), "CCBurnRouter: given locking script is not locker" ); // Finds input tx id and checks its inclusion bytes32 _inputTxId = BitcoinHelper.calculateTxId(_versions[0], _inputVin, _inputVout, _locktimes[0]); require( _isConfirmed( _inputTxId, _indexesAndBlockNumbers[2], // Block number _inputIntermediateNodes, _indexesAndBlockNumbers[1] // Index of input tx in the block ), "CCBurnRouter: input transaction is not finalized" ); /* Checks that input tx has not been provided as a burn proof note: if a locker executes a cc burn request but doesn't provide burn proof before deadline, we consider the transaction as a malicious tx */ require( !isUsedAsBurnProof[_inputTxId], "CCBurnRouter: transaction has been used as burn proof" ); // Extracts outpoint id and index from input tx (bytes32 _outpointId, uint _outpointIndex) = BitcoinHelper.extractOutpoint( _inputVin, _indexesAndBlockNumbers[0] // Index of malicious input in input tx ); // Checks that "outpoint tx id == output tx id" require( _outpointId == BitcoinHelper.calculateTxId(_versions[1], _outputVin, _outputVout, _locktimes[1]), "CCBurnRouter: outpoint tx doesn't match with output tx" ); // Checks that _outpointIndex of _outpointId belongs to locker locking script require( keccak256(BitcoinHelper.getLockingScript(_outputVout, _outpointIndex)) == keccak256(_lockerLockingScript), "CCBurnRouter: output tx doesn't belong to locker" ); // Checks that deadline for using the tx as burn proof has passed require( IBitcoinRelay(relay).lastSubmittedHeight() > transferDeadline + _indexesAndBlockNumbers[2], "CCBurnRouter: payback deadline has not passed yet" ); // Slashes locker _slashLockerForDispute( _inputVout, _lockerLockingScript, _inputTxId, _indexesAndBlockNumbers[2] // Block number ); return true; } /// @notice Slashes the malicious locker /// @param _inputVout Inputs of the malicious transaction /// @param _lockerLockingScript Malicious locker's locking script /// @param _inputTxId Tx id of the malicious transaction /// @param _inputBlockNumber Block number of the malicious transaction function _slashLockerForDispute( bytes memory _inputVout, bytes memory _lockerLockingScript, bytes32 _inputTxId, uint _inputBlockNumber ) private { // Finds total value of malicious transaction uint totalValue = BitcoinHelper.parseOutputsTotalValue(_inputVout); // Gets the target address of the locker from its Bitcoin address address _lockerTargetAddress = ILockers(lockers) .getLockerTargetAddress(_lockerLockingScript); ILockers(lockers).slashTheifLocker( _lockerTargetAddress, totalValue*slasherPercentageReward/MAX_SLASHER_REWARD, // Slasher reward _msgSender(), // Slasher address totalValue ); // Emits the event emit LockerDispute( _lockerTargetAddress, _lockerLockingScript, _inputBlockNumber, _inputTxId, totalValue + totalValue*slasherPercentageReward/MAX_SLASHER_REWARD ); } /// @notice Checks the burn requests that get paid by this transaction /// @param _paidBlockNumber Block number in which locker paid the burn request /// @param _lockerTargetAddress Address of the locker on the target chain /// @param _vout Outputs of a transaction /// @param _burnReqIndexes Indexes of requests that locker wants to provide proof for them /// @param _voutIndexes Indexes of outputs that were used to pay burn requests (_voutIndexes[i] belongs to _burnReqIndexes[i]) /// @return paidOutputCounter Number of executed burn requests function _checkPaidBurnRequests( bytes32 txId, uint _paidBlockNumber, address _lockerTargetAddress, bytes memory _vout, uint[] memory _burnReqIndexes, uint[] memory _voutIndexes ) private returns (uint paidOutputCounter) { uint parsedAmount; /* Below variable is for checking that every output in vout (except one) is related to a cc burn request so that we can set "isUsedAsBurnProof = true" for the whole txId */ paidOutputCounter = 0; for (uint i = 0; i < _burnReqIndexes.length; i++) { uint _burnReqIndex = _burnReqIndexes[i]; // Checks that the request has not been paid and its deadline has not passed if ( !burnRequests[_lockerTargetAddress][_burnReqIndex].isTransferred && burnRequests[_lockerTargetAddress][_burnReqIndex].deadline >= _paidBlockNumber ) { parsedAmount = BitcoinHelper.parseValueFromSpecificOutputHavingScript( _vout, _voutIndexes[i], burnRequests[_lockerTargetAddress][_burnReqIndex].userScript, ScriptTypes(uint(burnRequests[_lockerTargetAddress][_burnReqIndex].scriptType)) ); // Checks that locker has sent required teleBTC amount if (burnRequests[_lockerTargetAddress][_burnReqIndex].burntAmount == parsedAmount) { burnRequests[_lockerTargetAddress][_burnReqIndex].isTransferred = true; paidOutputCounter = paidOutputCounter + 1; emit PaidCCBurn( // burnRequests[_lockerTargetAddress][_burnReqIndex].sender, // burnRequests[_lockerTargetAddress][_burnReqIndex].userScript, // burnRequests[_lockerTargetAddress][_burnReqIndex].scriptType, // parsedAmount, _lockerTargetAddress, burnRequests[_lockerTargetAddress][_burnReqIndex].requestIdOfLocker, txId, _voutIndexes[i] ); } } } } /// @notice Checks if all outputs of the transaction used to pay a cc burn request /// @dev One output might return the remaining value to the locker /// @param _paidOutputCounter Number of the tx outputs that pay a cc burn request /// @param _vout Outputs of a transaction /// @param _lockerLockingScript Locking script of locker /// @param _txId Transaction id function _updateIsUsedAsBurnProof( uint _paidOutputCounter, bytes memory _vout, bytes memory _lockerLockingScript, bytes32 _txId ) private { uint parsedAmount = BitcoinHelper.parseValueHavingLockingScript(_vout, _lockerLockingScript); uint numberOfOutputs = BitcoinHelper.numberOfOutputs(_vout); if (parsedAmount != 0 && _paidOutputCounter + 1 == numberOfOutputs) { // One output sends the remained value to locker isUsedAsBurnProof[_txId] = true; } else if (_paidOutputCounter == numberOfOutputs) { // All output pays cc burn requests isUsedAsBurnProof[_txId] = true; } } function _checkScriptType(bytes memory _userScript, ScriptTypes _scriptType) private pure { if (_scriptType == ScriptTypes.P2PK || _scriptType == ScriptTypes.P2WSH) { require(_userScript.length == 32, "CCBurnRouter: invalid user script"); } else { require(_userScript.length == 20, "CCBurnRouter: invalid user script"); } } /// @notice Records burn request of user /// @param _amount Amount of wrapped token that user wants to burn /// @param _burntAmount Amount of wrapped token that actually gets burnt after deducting fees from the original value (_amount) /// @param _userScript User's Bitcoin address /// @param _lastSubmittedHeight Last block header height submitted on the relay contract /// @param _lockerTargetAddress Locker's target chain address that the request belongs to function _saveBurnRequest( uint _amount, uint _burntAmount, bytes memory _userScript, ScriptTypes _scriptType, uint _lastSubmittedHeight, address _lockerTargetAddress ) private { burnRequest memory request; request.amount = _amount; request.burntAmount = _burntAmount; request.sender = _msgSender(); request.userScript = _userScript; request.scriptType = _scriptType; request.deadline = _lastSubmittedHeight + transferDeadline; request.isTransferred = false; request.requestIdOfLocker = burnRequestCounter[_lockerTargetAddress]; burnRequestCounter[_lockerTargetAddress] = burnRequestCounter[_lockerTargetAddress] + 1; burnRequests[_lockerTargetAddress].push(request); } /// @notice Checks inclusion of the transaction in the specified block /// @dev Calls the relay contract to check Merkle inclusion proof /// @param _txId Id of the transaction /// @param _blockNumber Height of the block containing the transaction /// @param _intermediateNodes Merkle inclusion proof for the transaction /// @param _index Index of transaction in the block /// @return True if the transaction was included in the block function _isConfirmed( bytes32 _txId, uint256 _blockNumber, bytes memory _intermediateNodes, uint _index ) private returns (bool) { // Finds fee amount uint feeAmount = IBitcoinRelay(relay).getBlockHeaderFee(_blockNumber, 0); require(msg.value >= feeAmount, "CCBurnRouter: relay fee is not sufficient"); // Calls relay contract bytes memory data = Address.functionCallWithValue( relay, abi.encodeWithSignature( "checkTxProof(bytes32,uint256,bytes,uint256)", _txId, _blockNumber, _intermediateNodes, _index ), feeAmount ); // Sends extra ETH back to _msgSender() Address.sendValue(payable(_msgSender()), msg.value - feeAmount); return abi.decode(data, (bool)); } /// @notice Checks inclusion of the transaction in the specified block /// @dev Calls the relay contract to check Merkle inclusion proof /// @param _amount Id of the transaction /// @param _lockerTargetAddress Id of the transaction /// @return Remained amount after reducing fees function _getFees( uint _amount, address _lockerTargetAddress ) private returns (uint) { // Calculates protocol fee uint protocolFee = _amount*protocolPercentageFee/MAX_PROTOCOL_FEE; require(_amount > protocolFee + bitcoinFee, "CCBurnRouter: amount is too low"); uint remainedAmount = _amount - protocolFee - bitcoinFee; // Transfers protocol fee ITeleBTC(teleBTC).transfer(treasury, protocolFee); // Transfers bitcoin fee to locker ITeleBTC(teleBTC).transfer(_lockerTargetAddress, bitcoinFee); return remainedAmount; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../../types/ScriptTypesEnum.sol"; interface ICCBurnRouter { // Structures /// @notice Structure for recording cc burn requests /// @param amount Amount of tokens that user wants to burn /// @param burntAmount Amount that user will receive (after reducing fees from amount) /// @param sender Address of user who requests burning /// @param userScript Locking script of the user on Bitcoin /// @param deadline Deadline of locker for executing the request /// @param isTransferred True if the request has been executed struct burnRequest { uint amount; uint burntAmount; address sender; bytes userScript; uint deadline; bool isTransferred; ScriptTypes scriptType; uint requestIdOfLocker; } // Events /// @notice Emits when a burn request gets submitted /// @param userTargetAddress Target address of the user /// @param userScript Locking script of user on Bitcoin /// @param amount Toral requested amount /// @param burntAmount Amount that user will receive (after reducing fees) /// @param lockerTargetAddress Locker's address on the target chain /// @param deadline Deadline of locker for executing the request event CCBurn( address indexed userTargetAddress, bytes userScript, ScriptTypes scriptType, uint amount, uint burntAmount, address indexed lockerTargetAddress, bytes lockerLockingScript, uint requestIdOfLocker, uint indexed deadline ); /// @notice Emits when a burn proof is provided event PaidCCBurn( address indexed lockerTargetAddress, uint requestIdOfLocker, bytes32 bitcoinTxId, uint bitcoinTxOutputIndex ); /// @notice Emits when a locker gets slashed for withdrawing BTC without proper reason /// @param _lockerTargetAddress Locker's address on the target chain /// @param _blockNumber Block number of the malicious tx /// @param txId Transaction ID of the malicious tx /// @param amount Slashed amount event LockerDispute( address indexed _lockerTargetAddress, bytes lockerLockingScript, uint _blockNumber, bytes32 txId, uint amount ); /// @notice Emits when a locker gets slashed for withdrawing BTC without proper reason /// @param _lockerTargetAddress Locker's address on the target chain event BurnDispute( address indexed userTargetAddress, address indexed _lockerTargetAddress, bytes lockerLockingScript, uint requestIdOfLocker ); // Read-only functions function relay() external view returns (address); function lockers() external view returns (address); function teleBTC() external view returns (address); function treasury() external view returns (address); function transferDeadline() external view returns (uint); function protocolPercentageFee() external view returns (uint); function slasherPercentageReward() external view returns (uint); function bitcoinFee() external view returns (uint); // Bitcoin transaction fee function isTransferred(address _lockerTargetAddress, uint _index) external view returns (bool); function isUsedAsBurnProof(bytes32 _txId) external view returns (bool); // State-changing functions function setRelay(address _relay) external; function setLockers(address _lockers) external; function setTeleBTC(address _teleBTC) external; function setTreasury(address _treasury) external; function setTransferDeadline(uint _transferDeadline) external; function setProtocolPercentageFee(uint _protocolPercentageFee) external; function setSlasherPercentageReward(uint _slasherPercentageReward) external; function setBitcoinFee(uint _bitcoinFee) external; function ccBurn( uint _amount, bytes calldata _userScript, ScriptTypes _scriptType, bytes calldata _lockerLockingScript ) external returns (uint); function burnProof( bytes4 _version, bytes memory _vin, bytes memory _vout, bytes4 _locktime, uint256 _blockNumber, bytes memory _intermediateNodes, uint _index, bytes memory _lockerLockingScript, uint[] memory _burnReqIndexes, uint[] memory _voutIndexes ) external payable returns (bool); function disputeBurn( bytes calldata _lockerLockingScript, uint[] memory _indices ) external returns (bool); function disputeLocker( bytes memory _lockerLockingScript, bytes4[] memory _versions, // [inputTxVersion, outputTxVersion] bytes memory _inputVin, bytes memory _inputVout, bytes memory _outputVin, bytes memory _outputVout, bytes4[] memory _locktimes, // [inputTxLocktime, outputTxLocktime] bytes memory _inputIntermediateNodes, uint[] memory _indexesAndBlockNumbers // [inputIndex, inputTxIndex, outputTxIndex, inputTxBlockNumber, outputTxBlockNumber] ) external payable returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import './IERC20.sol'; interface ITeleBTC is IERC20 { // Events event Mint(address indexed to, uint value); event Burn(address indexed from, uint value); event NewMinterAdded(address indexed newMinter); event MinterRemoved(address indexed minter); event NewBurnerAdded(address indexed newBurner); event BurnerRemoved(address indexed burner); // state-changing functions function addMinter(address account) external; function removeMinter(address account) external; function addBurner(address account) external; function removeBurner(address account) external; function mint(address receiver, uint amount) external returns(bool); function burn(uint256 amount) external returns(bool); function mintTestToken() external; // Just for test }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IBitcoinRelay { // Structures /// @notice Structure for recording block header /// @param selfHash Hash of block header /// @param parentHash Hash of parent block header /// @param merkleRoot Merkle root of transactions in the block /// @param relayer Address of relayer who submitted the block header /// @param gasPrice Gas price of tx that relayer submitted the block header struct blockHeader { bytes32 selfHash; bytes32 parentHash; bytes32 merkleRoot; address relayer; uint gasPrice; } // Events /// @notice Emits when a block header is added /// @param height Height of submitted header /// @param selfHash Hash of submitted header /// @param parentHash Parent hash of submitted header /// @param relayer Address of relayer who submitted the block header event BlockAdded( uint indexed height, bytes32 selfHash, bytes32 indexed parentHash, address indexed relayer, uint gasPrice ); /// @notice Emits when a block header gets finalized /// @param height Height of the header /// @param selfHash Hash of the header /// @param parentHash Parent hash of the header /// @param relayer Address of relayer who submitted the block header /// @param rewardAmountTNT Amount of reward that the relayer receives in target native token /// @param rewardAmountTDT Amount of reward that the relayer receives in TDT event BlockFinalized( uint indexed height, bytes32 selfHash, bytes32 indexed parentHash, address indexed relayer, uint rewardAmountTNT, uint rewardAmountTDT, uint gasPrice ); // Read-only functions function relayGenesisHash() external view returns (bytes32); function initialHeight() external view returns(uint); function lastSubmittedHeight() external view returns(uint); function finalizationParameter() external view returns(uint); function TeleportDAOToken() external view returns(address); function relayerPercentageFee() external view returns(uint); function epochLength() external view returns(uint); function lastEpochQueries() external view returns(uint); function currentEpochQueries() external view returns(uint); function baseQueries() external view returns(uint); function submissionGasUsed() external view returns(uint); function getBlockHeaderHash(uint height, uint index) external view returns(bytes32); function getBlockHeaderFee (uint _height, uint _index) external view returns(uint); function getNumberOfSubmittedHeaders(uint height) external view returns (uint); function availableTDT() external view returns(uint); function availableTNT() external view returns(uint); function findHeight(bytes32 _hash) external view returns (uint256); function findAncestor(bytes32 _hash, uint256 _offset) external view returns (bytes32); // see if it's needed function isAncestor(bytes32 _ancestor, bytes32 _descendant, uint256 _limit) external view returns (bool); // see if it's needed function rewardAmountInTDT() external view returns (uint); // State-changing functions function pauseRelay() external; function unpauseRelay() external; function setRewardAmountInTDT(uint _rewardAmountInTDT) external; function setFinalizationParameter(uint _finalizationParameter) external; function setRelayerPercentageFee(uint _relayerPercentageFee) external; function setEpochLength(uint _epochLength) external; function setBaseQueries(uint _baseQueries) external; function setSubmissionGasUsed(uint _submissionGasUsed) external; function checkTxProof( bytes32 txid, uint blockHeight, bytes calldata intermediateNodes, uint index ) external payable returns (bool); function addHeaders(bytes calldata _anchor, bytes calldata _headers) external returns (bool); function addHeadersWithRetarget( bytes calldata _oldPeriodStartHeader, bytes calldata _oldPeriodEndHeader, bytes calldata _headers ) external returns (bool); function ownerAddHeaders(bytes calldata _anchor, bytes calldata _headers) external returns (bool); function ownerAddHeadersWithRetarget( bytes calldata _oldPeriodStartHeader, bytes calldata _oldPeriodEndHeader, bytes calldata _headers ) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../../types/ScriptTypesEnum.sol"; interface ILockers { // Events event RequestAddLocker( address indexed lockerTargetAddress, bytes lockerLockingScript, uint TDTLockedAmount, uint nativeTokenLockedAmount ); event RevokeAddLockerRequest( address indexed lockerTargetAddress, bytes lockerLockingScript, uint TDTLockedAmount, uint nativeTokenLockedAmount ); event RequestRemoveLocker( address indexed lockerTargetAddress, bytes lockerLockingScript, uint TDTUnlockedAmount, uint nativeTokenUnlockedAmount, uint netMinted // = totalMinted - totalBurnt which needs to be burnt ); event LockerAdded( address indexed lockerTargetAddress, bytes lockerLockingScript, uint TDTLockedAmount, uint nativeTokenLockedAmount, uint addingTime ); event LockerRemoved( address indexed lockerTargetAddress, bytes lockerLockingScript, uint TDTUnlockedAmount, uint nativeTokenUnlockedAmount ); event LockerSlashed( address indexed lockerTargetAddress, uint rewardAmount, address rewardRecipient, uint amount, address recipient, uint slashedCollateralAmount, uint slashTime, bool isForCCBurn ); event LockerLiquidated( address indexed lockerTargetAddress, address liquidatorAddress, uint collateralAmount, uint teleBTCAmount, uint liquidateTime ); event LockerSlashedCollateralSold( address indexed lockerTargetAddress, address buyerAddress, uint slashingAmount, uint teleBTCAmount, uint slashingTime ); event CollateralAdded( address indexed lockerTargetAddress, uint addedCollateral, uint totalCollateral, uint addingTime ); event CollateralRemoved( address indexed lockerTargetAddress, uint removedCollateral, uint totalCollateral, uint removingTime ); event MintByLocker( address indexed lockerTargetAddress, address receiver, uint mintedAmount, uint lockerFee, uint mintingTime ); event BurnByLocker( address indexed lockerTargetAddress, uint burntAmount, uint lockerFee, uint burningTime ); // Read-only functions function TeleportDAOToken() external view returns(address); function teleBTC() external view returns(address); function ccBurnRouter() external view returns(address); function exchangeConnector() external view returns(address); function priceOracle() external view returns(address); function minRequiredTDTLockedAmount() external view returns(uint); function minRequiredTNTLockedAmount() external view returns(uint); function lockerPercentageFee() external view returns(uint); function collateralRatio() external view returns(uint); function liquidationRatio() external view returns(uint); function priceWithDiscountRatio() external view returns(uint); function totalNumberOfCandidates() external view returns(uint); function totalNumberOfLockers() external view returns(uint); function getLockerTargetAddress(bytes calldata _lockerLockingScript) external view returns (address); function isLocker(bytes calldata _lockerLockingScript) external view returns (bool); function getNumberOfLockers() external view returns (uint); function getLockerLockingScript(address _lockerTargetAddress) external view returns (bytes memory); function isActive(address _lockerTargetAddress) external view returns (bool); function getLockerCapacity(address _lockerTargetAddress) external view returns (uint); function priceOfOneUnitOfCollateralInBTC() external view returns (uint); function isMinter(address account) external view returns (bool); function isBurner(address account) external view returns (bool); // State-changing functions function pauseLocker() external; function unPauseLocker() external; function addMinter(address _account) external; function removeMinter(address _account) external; function addBurner(address _account) external; function removeBurner(address _account) external; function mint(bytes calldata _lockerLockingScript, address _receiver, uint _amount) external returns(uint); function burn(bytes calldata _lockerLockingScript, uint256 _amount) external returns(uint); function setLockerPercentageFee(uint _lockerPercentageFee) external; function setMinRequiredTDTLockedAmount(uint _minRequiredTDTLockedAmount) external; function setMinRequiredTNTLockedAmount(uint _minRequiredTNTLockedAmount) external; function setPriceOracle(address _priceOracle) external; function setCCBurnRouter(address _ccBurnRouter) external; function setExchangeConnector(address _exchangeConnector) external; function setTeleBTC(address _teleBTC) external; function setCollateralRatio(uint _collateralRatio) external; function setLiquidationRatio(uint _liquidationRatio) external; function liquidateLocker( address _lockerTargetAddress, uint _btcAmount ) external returns (bool); function addCollateral( address _lockerTargetAddress, uint _addingNativeTokenAmount ) external payable returns (bool); function removeCollateral( uint _removingNativeTokenAmount ) external payable returns (bool); function requestToBecomeLocker( bytes calldata _lockerLockingScript, uint _lockedTDTAmount, uint _lockedNativeTokenAmount, ScriptTypes _lockerRescueType, bytes calldata _lockerRescueScript ) external payable returns (bool); function revokeRequest() external returns (bool); function addLocker(address _lockerTargetAddress) external returns (bool); function requestToRemoveLocker() external returns (bool); function ownerRemoveLocker(address _lockerTargetAddress) external returns(bool); function selfRemoveLocker() external returns (bool); function slashIdleLocker( address _lockerTargetAddress, uint _rewardAmount, address _rewardRecipient, uint _amount, address _recipient ) external returns(bool); function slashTheifLocker( address _lockerTargetAddress, uint _rewardAmount, address _rewardRecipient, uint _amount ) external returns(bool); function buySlashedCollateralOfLocker( address _lockerTargetAddress, uint _collateralAmount ) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./TypedMemView.sol"; import "../types/ScriptTypesEnum.sol"; import "hardhat/console.sol"; library BitcoinHelper { using TypedMemView for bytes; using TypedMemView for bytes29; // The target at minimum Difficulty. Also the target of the genesis block uint256 internal constant DIFF1_TARGET = 0xffff0000000000000000000000000000000000000000000000000000; uint256 internal constant RETARGET_PERIOD = 2 * 7 * 24 * 60 * 60; // 2 weeks in seconds uint256 internal constant RETARGET_PERIOD_BLOCKS = 2016; // 2 weeks in blocks enum BTCTypes { Unknown, // 0x0 CompactInt, // 0x1 ScriptSig, // 0x2 - with length prefix Outpoint, // 0x3 TxIn, // 0x4 IntermediateTxIns, // 0x5 - used in vin parsing Vin, // 0x6 ScriptPubkey, // 0x7 - with length prefix PKH, // 0x8 - the 20-byte payload digest WPKH, // 0x9 - the 20-byte payload digest WSH, // 0xa - the 32-byte payload digest SH, // 0xb - the 20-byte payload digest OpReturnPayload, // 0xc TxOut, // 0xd IntermediateTxOuts, // 0xe - used in vout parsing Vout, // 0xf Header, // 0x10 HeaderArray, // 0x11 MerkleNode, // 0x12 MerkleStep, // 0x13 MerkleArray // 0x14 } /// @notice requires `memView` to be of a specified type /// @dev passes if it is the correct type, errors if not /// @param memView a 29-byte view with a 5-byte type /// @param t the expected type (e.g. BTCTypes.Outpoint, BTCTypes.TxIn, etc) modifier typeAssert(bytes29 memView, BTCTypes t) { memView.assertType(uint40(t)); _; } // Revert with an error message re: non-minimal VarInts function revertNonMinimal(bytes29 ref) private pure returns (string memory) { (, uint256 g) = TypedMemView.encodeHex(ref.indexUint(0, uint8(ref.len()))); string memory err = string( abi.encodePacked( "Non-minimal var int. Got 0x", uint144(g) ) ); revert(err); } /// @notice reads a compact int from the view at the specified index /// @param memView a 29-byte view with a 5-byte type /// @param _index the index /// @return number returns the compact int at the specified index function indexCompactInt(bytes29 memView, uint256 _index) internal pure returns (uint64 number) { uint256 flag = memView.indexUint(_index, 1); if (flag <= 0xfc) { return uint64(flag); } else if (flag == 0xfd) { number = uint64(memView.indexLEUint(_index + 1, 2)); if (compactIntLength(number) != 3) {revertNonMinimal(memView.slice(_index, 3, 0));} } else if (flag == 0xfe) { number = uint64(memView.indexLEUint(_index + 1, 4)); if (compactIntLength(number) != 5) {revertNonMinimal(memView.slice(_index, 5, 0));} } else if (flag == 0xff) { number = uint64(memView.indexLEUint(_index + 1, 8)); if (compactIntLength(number) != 9) {revertNonMinimal(memView.slice(_index, 9, 0));} } } /// @notice gives the total length (in bytes) of a CompactInt-encoded number /// @param number the number as uint64 /// @return the compact integer as uint8 function compactIntLength(uint64 number) private pure returns (uint8) { if (number <= 0xfc) { return 1; } else if (number <= 0xffff) { return 3; } else if (number <= 0xffffffff) { return 5; } else { return 9; } } /// @notice extracts the LE txid from an outpoint /// @param _outpoint the outpoint /// @return the LE txid function txidLE(bytes29 _outpoint) internal pure typeAssert(_outpoint, BTCTypes.Outpoint) returns (bytes32) { return _outpoint.index(0, 32); } /// @notice Calculates the required transaction Id from the transaction details /// @dev Calculates the hash of transaction details two consecutive times /// @param _version Version of the transaction /// @param _vin Inputs of the transaction /// @param _vout Outputs of the transaction /// @param _locktime Lock time of the transaction /// @return Transaction Id of the required transaction function calculateTxId( bytes4 _version, bytes memory _vin, bytes memory _vout, bytes4 _locktime ) internal pure returns (bytes32) { bytes32 inputHash1 = sha256(abi.encodePacked(_version, _vin, _vout, _locktime)); bytes32 inputHash2 = sha256(abi.encodePacked(inputHash1)); return revertBytes32(inputHash2); } /// @notice Reverts a Bytes32 input /// @param _input Bytes32 input that we want to revert /// @return Reverted bytes32 function revertBytes32(bytes32 _input) private pure returns (bytes32) { bytes memory temp; bytes32 result; for (uint i = 0; i < 32; i++) { temp = abi.encodePacked(temp, _input[31-i]); } assembly { result := mload(add(temp, 32)) } return result; } /// @notice Parses outpoint info from an input /// @dev Reverts if vin is null /// @param _vin The vin of a Bitcoin transaction /// @param _index Index of the input that we are looking at /// @return _txId Output tx id /// @return _outputIndex Output tx index function extractOutpoint( bytes memory _vin, uint _index ) internal pure returns (bytes32 _txId, uint _outputIndex) { bytes29 vin = tryAsVin(_vin.ref(0)); require(!vin.isNull(), "BitcoinHelper: vin is null"); bytes29 input = indexVin(vin, _index); bytes29 _outpoint = outpoint(input); _txId = txidLE(_outpoint); _outputIndex = outpointIdx(_outpoint); } /// @notice extracts the index as an integer from the outpoint /// @param _outpoint the outpoint /// @return the index function outpointIdx(bytes29 _outpoint) internal pure typeAssert(_outpoint, BTCTypes.Outpoint) returns (uint32) { return uint32(_outpoint.indexLEUint(32, 4)); } /// @notice extracts the outpoint from an input /// @param _input the input /// @return the outpoint as a typed memory function outpoint(bytes29 _input) internal pure typeAssert(_input, BTCTypes.TxIn) returns (bytes29) { return _input.slice(0, 36, uint40(BTCTypes.Outpoint)); } /// @notice extracts the script sig from an input /// @param _input the input /// @return the script sig as a typed memory function scriptSig(bytes29 _input) internal pure typeAssert(_input, BTCTypes.TxIn) returns (bytes29) { uint64 scriptLength = indexCompactInt(_input, 36); return _input.slice(36, compactIntLength(scriptLength) + scriptLength, uint40(BTCTypes.ScriptSig)); } /// @notice determines the length of the first input in an array of inputs /// @param _inputs the vin without its length prefix /// @return the input length function inputLength(bytes29 _inputs) private pure typeAssert(_inputs, BTCTypes.IntermediateTxIns) returns (uint256) { uint64 scriptLength = indexCompactInt(_inputs, 36); return uint256(compactIntLength(scriptLength)) + uint256(scriptLength) + 36 + 4; } /// @notice extracts the input at a specified index /// @param _vin the vin /// @param _index the index of the desired input /// @return the desired input function indexVin(bytes29 _vin, uint256 _index) internal pure typeAssert(_vin, BTCTypes.Vin) returns (bytes29) { uint256 _nIns = uint256(indexCompactInt(_vin, 0)); uint256 _viewLen = _vin.len(); require(_index < _nIns, "Vin read overrun"); uint256 _offset = uint256(compactIntLength(uint64(_nIns))); bytes29 _remaining; for (uint256 _i = 0; _i < _index; _i += 1) { _remaining = _vin.postfix(_viewLen - _offset, uint40(BTCTypes.IntermediateTxIns)); _offset += inputLength(_remaining); } _remaining = _vin.postfix(_viewLen - _offset, uint40(BTCTypes.IntermediateTxIns)); uint256 _len = inputLength(_remaining); return _vin.slice(_offset, _len, uint40(BTCTypes.TxIn)); } /// @notice extracts the value from an output /// @param _output the output /// @return the value function value(bytes29 _output) internal pure typeAssert(_output, BTCTypes.TxOut) returns (uint64) { return uint64(_output.indexLEUint(0, 8)); } /// @notice Finds total outputs value /// @dev Reverts if vout is null /// @param _vout The vout of a Bitcoin transaction /// @return _totalValue Total vout value function parseOutputsTotalValue(bytes memory _vout) internal pure returns (uint64 _totalValue) { bytes29 voutView = tryAsVout(_vout.ref(0)); require(!voutView.isNull(), "BitcoinHelper: vout is null"); bytes29 output; // Finds total number of outputs uint _numberOfOutputs = uint256(indexCompactInt(voutView, 0)); for (uint index = 0; index < _numberOfOutputs; index++) { output = indexVout(voutView, index); _totalValue = _totalValue + value(output); } } /// @notice Parses the BTC amount that has been sent to /// a specific script in a specific output /// @param _vout The vout of a Bitcoin transaction /// @param _voutIndex Index of the output that we are looking at /// @param _script Desired recipient script /// @param _scriptType Type of the script (e.g. P2PK) /// @return bitcoinAmount Amount of BTC have been sent to the _script function parseValueFromSpecificOutputHavingScript( bytes memory _vout, uint _voutIndex, bytes memory _script, ScriptTypes _scriptType ) internal pure returns (uint64 bitcoinAmount) { bytes29 voutView = tryAsVout(_vout.ref(0)); require(!voutView.isNull(), "BitcoinHelper: vout is null"); bytes29 output = indexVout(voutView, _voutIndex); bytes29 _scriptPubkey = scriptPubkey(output); if (_scriptType == ScriptTypes.P2PK) { // note: first byte is Pushdata Bytelength. // note: public key length is 32. bitcoinAmount = keccak256(_script) == keccak256(abi.encodePacked(_scriptPubkey.index(1, 32))) ? value(output) : 0; } else if (_scriptType == ScriptTypes.P2PKH) { // note: first three bytes are OP_DUP, OP_HASH160, Pushdata Bytelength. // note: public key hash length is 20. bitcoinAmount = keccak256(_script) == keccak256(abi.encodePacked(_scriptPubkey.indexAddress(3))) ? value(output) : 0; } else if (_scriptType == ScriptTypes.P2SH) { // note: first two bytes are OP_HASH160, Pushdata Bytelength // note: script hash length is 20. bitcoinAmount = keccak256(_script) == keccak256(abi.encodePacked(_scriptPubkey.indexAddress(2))) ? value(output) : 0; } else if (_scriptType == ScriptTypes.P2WPKH) { // note: first two bytes are OP_0, Pushdata Bytelength // note: segwit public key hash length is 20. bitcoinAmount = keccak256(_script) == keccak256(abi.encodePacked(_scriptPubkey.indexAddress(2))) ? value(output) : 0; } else if (_scriptType == ScriptTypes.P2WSH) { // note: first two bytes are OP_0, Pushdata Bytelength // note: segwit script hash length is 32. bitcoinAmount = keccak256(_script) == keccak256(abi.encodePacked(_scriptPubkey.index(2, 32))) ? value(output) : 0; } } /// @notice Parses the BTC amount of a transaction /// @dev Finds the BTC amount that has been sent to the locking script /// Returns zero if no matching locking scrip is found /// @param _vout The vout of a Bitcoin transaction /// @param _lockingScript Desired locking script /// @return bitcoinAmount Amount of BTC have been sent to the _lockingScript function parseValueHavingLockingScript( bytes memory _vout, bytes memory _lockingScript ) internal view returns (uint64 bitcoinAmount) { // Checks that vout is not null bytes29 voutView = tryAsVout(_vout.ref(0)); require(!voutView.isNull(), "BitcoinHelper: vout is null"); bytes29 output; bytes29 _scriptPubkey; // Finds total number of outputs uint _numberOfOutputs = uint256(indexCompactInt(voutView, 0)); for (uint index = 0; index < _numberOfOutputs; index++) { output = indexVout(voutView, index); _scriptPubkey = scriptPubkey(output); if ( keccak256(abi.encodePacked(_scriptPubkey.clone())) == keccak256(abi.encodePacked(_lockingScript)) ) { bitcoinAmount = value(output); // Stops searching after finding the desired locking script break; } } } /// @notice Parses the BTC amount and the op_return of a transaction /// @dev Finds the BTC amount that has been sent to the locking script /// Assumes that payload size is less than 76 bytes /// @param _vout The vout of a Bitcoin transaction /// @param _lockingScript Desired locking script /// @return bitcoinAmount Amount of BTC have been sent to the _lockingScript /// @return arbitraryData Opreturn data of the transaction function parseValueAndDataHavingLockingScriptSmallPayload( bytes memory _vout, bytes memory _lockingScript ) internal view returns (uint64 bitcoinAmount, bytes memory arbitraryData) { // Checks that vout is not null bytes29 voutView = tryAsVout(_vout.ref(0)); require(!voutView.isNull(), "BitcoinHelper: vout is null"); bytes29 output; bytes29 _scriptPubkey; bytes29 _scriptPubkeyWithLength; bytes29 _arbitraryData; // Finds total number of outputs uint _numberOfOutputs = uint256(indexCompactInt(voutView, 0)); for (uint index = 0; index < _numberOfOutputs; index++) { output = indexVout(voutView, index); _scriptPubkey = scriptPubkey(output); _scriptPubkeyWithLength = scriptPubkeyWithLength(output); _arbitraryData = opReturnPayloadSmall(_scriptPubkeyWithLength); // Checks whether the output is an arbitarary data or not if(_arbitraryData == 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) { // Output is not an arbitrary data if ( keccak256(abi.encodePacked(_scriptPubkey.clone())) == keccak256(abi.encodePacked(_lockingScript)) ) { bitcoinAmount = value(output); } } else { // Returns the whole bytes array arbitraryData = _arbitraryData.clone(); } } } /// @notice Parses the BTC amount and the op_return of a transaction /// @dev Finds the BTC amount that has been sent to the locking script /// Assumes that payload size is greater than 75 bytes /// @param _vout The vout of a Bitcoin transaction /// @param _lockingScript Desired locking script /// @return bitcoinAmount Amount of BTC have been sent to the _lockingScript /// @return arbitraryData Opreturn data of the transaction function parseValueAndDataHavingLockingScriptBigPayload( bytes memory _vout, bytes memory _lockingScript ) internal view returns (uint64 bitcoinAmount, bytes memory arbitraryData) { // Checks that vout is not null bytes29 voutView = tryAsVout(_vout.ref(0)); require(!voutView.isNull(), "BitcoinHelper: vout is null"); bytes29 output; bytes29 _scriptPubkey; bytes29 _scriptPubkeyWithLength; bytes29 _arbitraryData; // Finds total number of outputs uint _numberOfOutputs = uint256(indexCompactInt(voutView, 0)); for (uint index = 0; index < _numberOfOutputs; index++) { output = indexVout(voutView, index); _scriptPubkey = scriptPubkey(output); _scriptPubkeyWithLength = scriptPubkeyWithLength(output); _arbitraryData = opReturnPayloadBig(_scriptPubkeyWithLength); // Checks whether the output is an arbitarary data or not if(_arbitraryData == 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) { // Output is not an arbitrary data if ( keccak256(abi.encodePacked(_scriptPubkey.clone())) == keccak256(abi.encodePacked(_lockingScript)) ) { bitcoinAmount = value(output); } } else { // Returns the whole bytes array arbitraryData = _arbitraryData.clone(); } } } /// @notice extracts the scriptPubkey from an output /// @param _output the output /// @return the scriptPubkey function scriptPubkey(bytes29 _output) internal pure typeAssert(_output, BTCTypes.TxOut) returns (bytes29) { uint64 scriptLength = indexCompactInt(_output, 8); return _output.slice(8 + compactIntLength(scriptLength), scriptLength, uint40(BTCTypes.ScriptPubkey)); } /// @notice extracts the scriptPubkey from an output /// @param _output the output /// @return the scriptPubkey function scriptPubkeyWithLength(bytes29 _output) internal pure typeAssert(_output, BTCTypes.TxOut) returns (bytes29) { uint64 scriptLength = indexCompactInt(_output, 8); return _output.slice(8, compactIntLength(scriptLength) + scriptLength, uint40(BTCTypes.ScriptPubkey)); } /// @notice Parses locking script from an output /// @dev Reverts if vout is null /// @param _vout The vout of a Bitcoin transaction /// @param _index Index of the output that we are looking at /// @return _lockingScript Parsed locking script function getLockingScript( bytes memory _vout, uint _index ) internal view returns (bytes memory _lockingScript) { bytes29 vout = tryAsVout(_vout.ref(0)); require(!vout.isNull(), "BitcoinHelper: vout is null"); bytes29 output = indexVout(vout, _index); bytes29 _lockingScriptBytes29 = scriptPubkey(output); _lockingScript = _lockingScriptBytes29.clone(); } /// @notice Returns number of outputs in a vout /// @param _vout The vout of a Bitcoin transaction function numberOfOutputs(bytes memory _vout) internal pure returns (uint _numberOfOutputs) { bytes29 voutView = tryAsVout(_vout.ref(0)); _numberOfOutputs = uint256(indexCompactInt(voutView, 0)); } /// @notice determines the length of the first output in an array of outputs /// @param _outputs the vout without its length prefix /// @return the output length function outputLength(bytes29 _outputs) private pure typeAssert(_outputs, BTCTypes.IntermediateTxOuts) returns (uint256) { uint64 scriptLength = indexCompactInt(_outputs, 8); return uint256(compactIntLength(scriptLength)) + uint256(scriptLength) + 8; } /// @notice extracts the output at a specified index /// @param _vout the vout /// @param _index the index of the desired output /// @return the desired output function indexVout(bytes29 _vout, uint256 _index) internal pure typeAssert(_vout, BTCTypes.Vout) returns (bytes29) { uint256 _nOuts = uint256(indexCompactInt(_vout, 0)); uint256 _viewLen = _vout.len(); require(_index < _nOuts, "Vout read overrun"); uint256 _offset = uint256(compactIntLength(uint64(_nOuts))); bytes29 _remaining; for (uint256 _i = 0; _i < _index; _i += 1) { _remaining = _vout.postfix(_viewLen - _offset, uint40(BTCTypes.IntermediateTxOuts)); _offset += outputLength(_remaining); } _remaining = _vout.postfix(_viewLen - _offset, uint40(BTCTypes.IntermediateTxOuts)); uint256 _len = outputLength(_remaining); return _vout.slice(_offset, _len, uint40(BTCTypes.TxOut)); } /// @notice extracts the Op Return Payload /// @dev structure of the input is: 1 byte op return + 2 bytes indicating the length of payload + max length for op return payload is 80 bytes /// @param _spk the scriptPubkey /// @return the Op Return Payload (or null if not a valid Op Return output) function opReturnPayloadBig(bytes29 _spk) internal pure typeAssert(_spk, BTCTypes.ScriptPubkey) returns (bytes29) { uint64 _bodyLength = indexCompactInt(_spk, 0); uint64 _payloadLen = uint64(_spk.indexUint(3, 1)); if (_bodyLength > 83 || _bodyLength < 4 || _spk.indexUint(1, 1) != 0x6a || _spk.indexUint(3, 1) != _bodyLength - 3) { return TypedMemView.nullView(); } return _spk.slice(4, _payloadLen, uint40(BTCTypes.OpReturnPayload)); } /// @notice extracts the Op Return Payload /// @dev structure of the input is: 1 byte op return + 1 bytes indicating the length of payload + max length for op return payload is 75 bytes /// @param _spk the scriptPubkey /// @return the Op Return Payload (or null if not a valid Op Return output) function opReturnPayloadSmall(bytes29 _spk) internal pure typeAssert(_spk, BTCTypes.ScriptPubkey) returns (bytes29) { uint64 _bodyLength = indexCompactInt(_spk, 0); uint64 _payloadLen = uint64(_spk.indexUint(2, 1)); if (_bodyLength > 77 || _bodyLength < 4 || _spk.indexUint(1, 1) != 0x6a || _spk.indexUint(2, 1) != _bodyLength - 2) { return TypedMemView.nullView(); } return _spk.slice(3, _payloadLen, uint40(BTCTypes.OpReturnPayload)); } /// @notice verifies the vin and converts to a typed memory /// @dev will return null in error cases /// @param _vin the vin /// @return the typed vin (or null if error) function tryAsVin(bytes29 _vin) internal pure typeAssert(_vin, BTCTypes.Unknown) returns (bytes29) { if (_vin.len() == 0) { return TypedMemView.nullView(); } uint64 _nIns = indexCompactInt(_vin, 0); uint256 _viewLen = _vin.len(); if (_nIns == 0) { return TypedMemView.nullView(); } uint256 _offset = uint256(compactIntLength(_nIns)); for (uint256 i = 0; i < _nIns; i++) { if (_offset >= _viewLen) { // We've reached the end, but are still trying to read more return TypedMemView.nullView(); } bytes29 _remaining = _vin.postfix(_viewLen - _offset, uint40(BTCTypes.IntermediateTxIns)); _offset += inputLength(_remaining); } if (_offset != _viewLen) { return TypedMemView.nullView(); } return _vin.castTo(uint40(BTCTypes.Vin)); } /// @notice verifies the vout and converts to a typed memory /// @dev will return null in error cases /// @param _vout the vout /// @return the typed vout (or null if error) function tryAsVout(bytes29 _vout) internal pure typeAssert(_vout, BTCTypes.Unknown) returns (bytes29) { if (_vout.len() == 0) { return TypedMemView.nullView(); } uint64 _nOuts = indexCompactInt(_vout, 0); uint256 _viewLen = _vout.len(); if (_nOuts == 0) { return TypedMemView.nullView(); } uint256 _offset = uint256(compactIntLength(_nOuts)); for (uint256 i = 0; i < _nOuts; i++) { if (_offset >= _viewLen) { // We've reached the end, but are still trying to read more return TypedMemView.nullView(); } bytes29 _remaining = _vout.postfix(_viewLen - _offset, uint40(BTCTypes.IntermediateTxOuts)); _offset += outputLength(_remaining); } if (_offset != _viewLen) { return TypedMemView.nullView(); } return _vout.castTo(uint40(BTCTypes.Vout)); } /// @notice verifies the header and converts to a typed memory /// @dev will return null in error cases /// @param _header the header /// @return the typed header (or null if error) function tryAsHeader(bytes29 _header) internal pure typeAssert(_header, BTCTypes.Unknown) returns (bytes29) { if (_header.len() != 80) { return TypedMemView.nullView(); } return _header.castTo(uint40(BTCTypes.Header)); } /// @notice Index a header array. /// @dev Errors on overruns /// @param _arr The header array /// @param index The 0-indexed location of the header to get /// @return the typed header at `index` function indexHeaderArray(bytes29 _arr, uint256 index) internal pure typeAssert(_arr, BTCTypes.HeaderArray) returns (bytes29) { uint256 _start = index * 80; return _arr.slice(_start, 80, uint40(BTCTypes.Header)); } /// @notice verifies the header array and converts to a typed memory /// @dev will return null in error cases /// @param _arr the header array /// @return the typed header array (or null if error) function tryAsHeaderArray(bytes29 _arr) internal pure typeAssert(_arr, BTCTypes.Unknown) returns (bytes29) { if (_arr.len() % 80 != 0) { return TypedMemView.nullView(); } return _arr.castTo(uint40(BTCTypes.HeaderArray)); } /// @notice verifies the merkle array and converts to a typed memory /// @dev will return null in error cases /// @param _arr the merkle array /// @return the typed merkle array (or null if error) function tryAsMerkleArray(bytes29 _arr) internal pure typeAssert(_arr, BTCTypes.Unknown) returns (bytes29) { if (_arr.len() % 32 != 0) { return TypedMemView.nullView(); } return _arr.castTo(uint40(BTCTypes.MerkleArray)); } /// @notice extracts the merkle root from the header /// @param _header the header /// @return the merkle root function merkleRoot(bytes29 _header) internal pure typeAssert(_header, BTCTypes.Header) returns (bytes32) { return _header.index(36, 32); } /// @notice extracts the target from the header /// @param _header the header /// @return the target function target(bytes29 _header) internal pure typeAssert(_header, BTCTypes.Header) returns (uint256) { uint256 _mantissa = _header.indexLEUint(72, 3); require(_header.indexUint(75, 1) > 2, "ViewBTC: invalid target difficulty"); uint256 _exponent = _header.indexUint(75, 1) - 3; return _mantissa * (256 ** _exponent); } /// @notice calculates the difficulty from a target /// @param _target the target /// @return the difficulty function toDiff(uint256 _target) private pure returns (uint256) { return DIFF1_TARGET / (_target); } /// @notice extracts the difficulty from the header /// @param _header the header /// @return the difficulty function diff(bytes29 _header) internal pure typeAssert(_header, BTCTypes.Header) returns (uint256) { return toDiff(target(_header)); } /// @notice extracts the timestamp from the header /// @param _header the header /// @return the timestamp function time(bytes29 _header) internal pure typeAssert(_header, BTCTypes.Header) returns (uint32) { return uint32(_header.indexLEUint(68, 4)); } /// @notice extracts the parent hash from the header /// @param _header the header /// @return the parent hash function parent(bytes29 _header) internal pure typeAssert(_header, BTCTypes.Header) returns (bytes32) { return _header.index(4, 32); } /// @notice Checks validity of header chain /// @dev Compares current header parent to previous header's digest /// @param _header The raw bytes header /// @param _prevHeaderDigest The previous header's digest /// @return true if the connect is valid, false otherwise function checkParent(bytes29 _header, bytes32 _prevHeaderDigest) internal pure typeAssert(_header, BTCTypes.Header) returns (bool) { return parent(_header) == _prevHeaderDigest; } /// @notice Validates a tx inclusion in the block /// @dev `index` is not a reliable indicator of location within a block /// @param _txid The txid (LE) /// @param _merkleRoot The merkle root /// @param _intermediateNodes The proof's intermediate nodes (digests between leaf and root) /// @param _index The leaf's index in the tree (0-indexed) /// @return true if fully valid, false otherwise function prove( bytes32 _txid, bytes32 _merkleRoot, bytes29 _intermediateNodes, uint _index ) internal view typeAssert(_intermediateNodes, BTCTypes.MerkleArray) returns (bool) { // Shortcut the empty-block case if ( _txid == _merkleRoot && _index == 0 && _intermediateNodes.len() == 0 ) { return true; } return checkMerkle(_txid, _intermediateNodes, _merkleRoot, _index); } /// @notice verifies a merkle proof /// @dev leaf, proof, and root are in LE format /// @param _leaf the leaf /// @param _proof the proof nodes /// @param _root the merkle root /// @param _index the index /// @return true if valid, false if otherwise function checkMerkle( bytes32 _leaf, bytes29 _proof, bytes32 _root, uint256 _index ) private view typeAssert(_proof, BTCTypes.MerkleArray) returns (bool) { uint256 nodes = _proof.len() / 32; if (nodes == 0) { return _leaf == _root; } uint256 _idx = _index; bytes32 _current = _leaf; for (uint i = 0; i < nodes; i++) { bytes32 _next = _proof.index(i * 32, 32); if (_idx % 2 == 1) { _current = merkleStep(_next, _current); } else { _current = merkleStep(_current, _next); } _idx >>= 1; } return _current == _root; } /// @notice Concatenates and hashes two inputs for merkle proving /// @dev Not recommended to call directly. /// @param _a The first hash /// @param _b The second hash /// @return digest The double-sha256 of the concatenated hashes function merkleStep(bytes32 _a, bytes32 _b) private view returns (bytes32 digest) { assembly { // solium-disable-previous-line security/no-inline-assembly let ptr := mload(0x40) mstore(ptr, _a) mstore(add(ptr, 0x20), _b) pop(staticcall(gas(), 2, ptr, 0x40, ptr, 0x20)) // sha2 #1 pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2 digest := mload(ptr) } } /// @notice performs the bitcoin difficulty retarget /// @dev implements the Bitcoin algorithm precisely /// @param _previousTarget the target of the previous period /// @param _firstTimestamp the timestamp of the first block in the difficulty period /// @param _secondTimestamp the timestamp of the last block in the difficulty period /// @return the new period's target threshold function retargetAlgorithm( uint256 _previousTarget, uint256 _firstTimestamp, uint256 _secondTimestamp ) internal pure returns (uint256) { uint256 _elapsedTime = _secondTimestamp - _firstTimestamp; // Normalize ratio to factor of 4 if very long or very short if (_elapsedTime < RETARGET_PERIOD / 4) { _elapsedTime = RETARGET_PERIOD / 4; } if (_elapsedTime > RETARGET_PERIOD * 4) { _elapsedTime = RETARGET_PERIOD * 4; } /* NB: high targets e.g. ffff0020 can cause overflows here so we divide it by 256**2, then multiply by 256**2 later we know the target is evenly divisible by 256**2, so this isn't an issue */ uint256 _adjusted = _previousTarget / 65536 * _elapsedTime; return _adjusted / RETARGET_PERIOD * 65536; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _setOwner(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _setOwner(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT 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; 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.0; enum ScriptTypes { P2PK, // 32 bytes P2PKH, // 20 bytes P2SH, // 20 bytes P2WPKH, // 20 bytes P2WSH // 32 bytes }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IERC20 { // events event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); // read-only functions function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); // state-changing functions function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** @author Summa (https://summa.one) */ /* Original version: https://github.com/summa-tx/memview-sol/blob/main/contracts/TypedMemView.sol We made few changes to the original version: 1. Use solidity version 8 compiler 2. Remove SafeMath library 3. Add unchecked in line 522 */ library TypedMemView { // Why does this exist? // the solidity `bytes memory` type has a few weaknesses. // 1. You can't index ranges effectively // 2. You can't slice without copying // 3. The underlying data may represent any type // 4. Solidity never deallocates memory, and memory costs grow // superlinearly // By using a memory view instead of a `bytes memory` we get the following // advantages: // 1. Slices are done on the stack, by manipulating the pointer // 2. We can index arbitrary ranges and quickly convert them to stack types // 3. We can insert type info into the pointer, and typecheck at runtime // This makes `TypedMemView` a useful tool for efficient zero-copy // algorithms. // Why bytes29? // We want to avoid confusion between views, digests, and other common // types so we chose a large and uncommonly used odd number of bytes // // Note that while bytes are left-aligned in a word, integers and addresses // are right-aligned. This means when working in assembly we have to // account for the 3 unused bytes on the righthand side // // First 5 bytes are a type flag. // - ff_ffff_fffe is reserved for unknown type. // - ff_ffff_ffff is reserved for invalid types/errors. // next 12 are memory address // next 12 are len // bottom 3 bytes are empty // Assumptions: // - non-modification of memory. // - No Solidity updates // - - wrt free mem point // - - wrt bytes representation in memory // - - wrt memory addressing in general // Usage: // - create type constants // - use `assertType` for runtime type assertions // - - unfortunately we can't do this at compile time yet :( // - recommended: implement modifiers that perform type checking // - - e.g. // - - `uint40 constant MY_TYPE = 3;` // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }` // - instantiate a typed view from a bytearray using `ref` // - use `index` to inspect the contents of the view // - use `slice` to create smaller views into the same memory // - - `slice` can increase the offset // - - `slice can decrease the length` // - - must specify the output type of `slice` // - - `slice` will return a null view if you try to overrun // - - make sure to explicitly check for this with `notNull` or `assertType` // - use `equal` for typed comparisons. // The null view bytes29 internal constant NULL = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff; uint8 constant TWELVE_BYTES = 96; /** * @notice Returns the encoded hex character that represents the lower 4 bits of the argument. * @param _b The byte * @return char - The encoded hex character */ function nibbleHex(uint8 _b) internal pure returns (uint8 char) { // This can probably be done more efficiently, but it's only in error // paths, so we don't really care :) uint8 _nibble = _b | 0xf0; // set top 4, keep bottom 4 if (_nibble == 0xf0) {return 0x30;} // 0 if (_nibble == 0xf1) {return 0x31;} // 1 if (_nibble == 0xf2) {return 0x32;} // 2 if (_nibble == 0xf3) {return 0x33;} // 3 if (_nibble == 0xf4) {return 0x34;} // 4 if (_nibble == 0xf5) {return 0x35;} // 5 if (_nibble == 0xf6) {return 0x36;} // 6 if (_nibble == 0xf7) {return 0x37;} // 7 if (_nibble == 0xf8) {return 0x38;} // 8 if (_nibble == 0xf9) {return 0x39;} // 9 if (_nibble == 0xfa) {return 0x61;} // a if (_nibble == 0xfb) {return 0x62;} // b if (_nibble == 0xfc) {return 0x63;} // c if (_nibble == 0xfd) {return 0x64;} // d if (_nibble == 0xfe) {return 0x65;} // e if (_nibble == 0xff) {return 0x66;} // f } /** * @notice Returns a uint16 containing the hex-encoded byte. * `the first 8 bits of encoded is the nibbleHex of top 4 bits of _b` * `the second 8 bits of encoded is the nibbleHex of lower 4 bits of _b` * @param _b The byte * @return encoded - The hex-encoded byte */ function byteHex(uint8 _b) internal pure returns (uint16 encoded) { encoded |= nibbleHex(_b >> 4); // top 4 bits encoded <<= 8; encoded |= nibbleHex(_b); // lower 4 bits } /** * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes. * `second` contains the encoded lower 16 bytes. * * @param _b The 32 bytes as uint256 * @return first - The top 16 bytes * @return second - The bottom 16 bytes */ function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) { for (uint8 i = 31; i > 15; i -= 1) { uint8 _byte = uint8(_b >> (i * 8)); first |= byteHex(_byte); if (i != 16) { first <<= 16; } } // abusing underflow here =_= for (uint8 i = 15; i < 255 ; i -= 1) { uint8 _byte = uint8(_b >> (i * 8)); second |= byteHex(_byte); if (i != 0) { second <<= 16; } } } /** * @notice Changes the endianness of a uint256. * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel * @param _b The unsigned integer to reverse * @return v - The reversed value */ function reverseUint256(uint256 _b) internal pure returns (uint256 v) { v = _b; // swap bytes v = ((v >> 8) & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) | ((v & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) << 8); // swap 2-byte long pairs v = ((v >> 16) & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) | ((v & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) << 16); // swap 4-byte long pairs v = ((v >> 32) & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) | ((v & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) << 32); // swap 8-byte long pairs v = ((v >> 64) & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) | ((v & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) << 64); // swap 16-byte long pairs v = (v >> 128) | (v << 128); } /** * @notice Create a mask with the highest `_len` bits set. * @param _len The length * @return mask - The mask */ function leftMask(uint8 _len) private pure returns (uint256 mask) { // ugly. redo without assembly? assembly { // solium-disable-previous-line security/no-inline-assembly mask := sar( sub(_len, 1), 0x8000000000000000000000000000000000000000000000000000000000000000 ) } } /** * @notice Return the null view. * @return bytes29 - The null view */ function nullView() internal pure returns (bytes29) { return NULL; } /** * @notice Check if the view is null. * @return bool - True if the view is null */ function isNull(bytes29 memView) internal pure returns (bool) { return memView == NULL; } /** * @notice Check if the view is not null. * @return bool - True if the view is not null */ function notNull(bytes29 memView) internal pure returns (bool) { return !isNull(memView); } /** * @notice Check if the view is of a valid type and points to a valid location * in memory. * @dev We perform this check by examining solidity's unallocated memory * pointer and ensuring that the view's upper bound is less than that. * @param memView The view * @return ret - True if the view is valid */ function isValid(bytes29 memView) internal pure returns (bool ret) { if (typeOf(memView) == 0xffffffffff) {return false;} uint256 _end = end(memView); assembly { // solium-disable-previous-line security/no-inline-assembly ret := not(gt(_end, mload(0x40))) } } /** * @notice Require that a typed memory view be valid. * @dev Returns the view for easy chaining. * @param memView The view * @return bytes29 - The validated view */ function assertValid(bytes29 memView) internal pure returns (bytes29) { require(isValid(memView), "Validity assertion failed"); return memView; } /** * @notice Return true if the memview is of the expected type. Otherwise false. * @param memView The view * @param _expected The expected type * @return bool - True if the memview is of the expected type */ function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) { return typeOf(memView) == _expected; } /** * @notice Require that a typed memory view has a specific type. * @dev Returns the view for easy chaining. * @param memView The view * @param _expected The expected type * @return bytes29 - The view with validated type */ function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) { if (!isType(memView, _expected)) { (, uint256 g) = encodeHex(uint256(typeOf(memView))); (, uint256 e) = encodeHex(uint256(_expected)); string memory err = string( abi.encodePacked( "Type assertion failed. Got 0x", uint80(g), ". Expected 0x", uint80(e) ) ); revert(err); } return memView; } /** * @notice Return an identical view with a different type. * @param memView The view * @param _newType The new type * @return newView - The new view with the specified type */ function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) { // then | in the new type assembly { // solium-disable-previous-line security/no-inline-assembly // shift off the top 5 bytes newView := or(newView, shr(40, shl(40, memView))) newView := or(newView, shl(216, _newType)) } } /** * @notice Unsafe raw pointer construction. This should generally not be called * directly. Prefer `ref` wherever possible. * @dev Unsafe raw pointer construction. This should generally not be called * directly. Prefer `ref` wherever possible. * @param _type The type * @param _loc The memory address * @param _len The length * @return newView - The new view with the specified type, location and length */ function unsafeBuildUnchecked(uint256 _type, uint256 _loc, uint256 _len) private pure returns (bytes29 newView) { assembly { // solium-disable-previous-line security/no-inline-assembly newView := shl(96, or(newView, _type)) // insert type newView := shl(96, or(newView, _loc)) // insert loc newView := shl(24, or(newView, _len)) // empty bottom 3 bytes } } /** * @notice Instantiate a new memory view. This should generally not be called * directly. Prefer `ref` wherever possible. * @dev Instantiate a new memory view. This should generally not be called * directly. Prefer `ref` wherever possible. * @param _type The type * @param _loc The memory address * @param _len The length * @return newView - The new view with the specified type, location and length */ function build(uint256 _type, uint256 _loc, uint256 _len) internal pure returns (bytes29 newView) { uint256 _end = _loc + _len; assembly { // solium-disable-previous-line security/no-inline-assembly if gt(_end, mload(0x40)) { _end := 0 } } if (_end == 0) { return NULL; } newView = unsafeBuildUnchecked(_type, _loc, _len); } /** * @notice Instantiate a memory view from a byte array. * @dev Note that due to Solidity memory representation, it is not possible to * implement a deref, as the `bytes` type stores its len in memory. * @param arr The byte array * @param newType The type * @return bytes29 - The memory view */ function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) { uint256 _len = arr.length; uint256 _loc; assembly { // solium-disable-previous-line security/no-inline-assembly _loc := add(arr, 0x20) // our view is of the data, not the struct } return build(newType, _loc, _len); } /** * @notice Return the associated type information. * @param memView The memory view * @return _type - The type associated with the view */ function typeOf(bytes29 memView) internal pure returns (uint40 _type) { assembly { // solium-disable-previous-line security/no-inline-assembly // 216 == 256 - 40 _type := shr(216, memView) // shift out lower 24 bytes } } /** * @notice Optimized type comparison. Checks that the 5-byte type flag is equal. * @param left The first view * @param right The second view * @return bool - True if the 5-byte type flag is equal */ function sameType(bytes29 left, bytes29 right) internal pure returns (bool) { // XOR the inputs to check their difference return (left ^ right) >> (2 * TWELVE_BYTES) == 0; } /** * @notice Return the memory address of the underlying bytes. * @param memView The view * @return _loc - The memory address */ function loc(bytes29 memView) internal pure returns (uint96 _loc) { uint256 _mask = LOW_12_MASK; // assembly can't use globals assembly { // solium-disable-previous-line security/no-inline-assembly // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space) _loc := and(shr(120, memView), _mask) } } /** * @notice The number of memory words this memory view occupies, rounded up. * @param memView The view * @return uint256 - The number of memory words */ function words(bytes29 memView) internal pure returns (uint256) { return (uint256(len(memView)) + 32) / 32; } /** * @notice The in-memory footprint of a fresh copy of the view. * @param memView The view * @return uint256 - The in-memory footprint of a fresh copy of the view. */ function footprint(bytes29 memView) internal pure returns (uint256) { return words(memView) * 32; } /** * @notice The number of bytes of the view. * @param memView The view * @return _len - The length of the view */ function len(bytes29 memView) internal pure returns (uint96 _len) { uint256 _mask = LOW_12_MASK; // assembly can't use globals assembly { // solium-disable-previous-line security/no-inline-assembly _len := and(shr(24, memView), _mask) } } /** * @notice Returns the endpoint of `memView`. * @param memView The view * @return uint256 - The endpoint of `memView` */ function end(bytes29 memView) internal pure returns (uint256) { return loc(memView) + len(memView); } /** * @notice Safe slicing without memory modification. * @param memView The view * @param _index The start index * @param _len The length * @param newType The new type * @return bytes29 - The new view */ function slice(bytes29 memView, uint256 _index, uint256 _len, uint40 newType) internal pure returns (bytes29) { uint256 _loc = loc(memView); // Ensure it doesn't overrun the view if (_loc + _index + _len > end(memView)) { return NULL; } _loc = _loc + _index; return build(newType, _loc, _len); } /** * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes. * @param memView The view * @param _len The length * @param newType The new type * @return bytes29 - The new view */ function prefix(bytes29 memView, uint256 _len, uint40 newType) internal pure returns (bytes29) { return slice(memView, 0, _len, newType); } /** * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte. * @param memView The view * @param _len The length * @param newType The new type * @return bytes29 - The new view */ function postfix(bytes29 memView, uint256 _len, uint40 newType) internal pure returns (bytes29) { return slice(memView, uint256(len(memView)) - _len, _len, newType); } /** * @notice Construct an error message for an indexing overrun. * @param _loc The memory address * @param _len The length * @param _index The index * @param _slice The slice where the overrun occurred * @return err - The err */ function indexErrOverrun( uint256 _loc, uint256 _len, uint256 _index, uint256 _slice ) internal pure returns (string memory err) { (, uint256 a) = encodeHex(_loc); (, uint256 b) = encodeHex(_len); (, uint256 c) = encodeHex(_index); (, uint256 d) = encodeHex(_slice); err = string( abi.encodePacked( "TypedMemView/index - Overran the view. Slice is at 0x", uint48(a), " with length 0x", uint48(b), ". Attempted to index at offset 0x", uint48(c), " with length 0x", uint48(d), "." ) ); } /** * @notice Load up to 32 bytes from the view onto the stack. * @dev Returns a bytes32 with only the `_bytes` highest bytes set. * This can be immediately cast to a smaller fixed-length byte array. * To automatically cast to an integer, use `indexUint`. * @param memView The view * @param _index The index * @param _bytes The bytes * @return result - The 32 byte result */ function index(bytes29 memView, uint256 _index, uint8 _bytes) internal pure returns (bytes32 result) { if (_bytes == 0) {return bytes32(0);} if (_index + _bytes > len(memView)) { revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes))); } require(_bytes <= 32, "TypedMemView/index - Attempted to index more than 32 bytes"); // FIXME: why the following lines need `unchecked` unchecked { uint8 bitLength = _bytes * 8; uint256 _loc = loc(memView); uint256 _mask = leftMask(bitLength); assembly { // solium-disable-previous-line security/no-inline-assembly result := and(mload(add(_loc, _index)), _mask) } } } /** * @notice Parse an unsigned integer from the view at `_index`. * @dev Requires that the view have >= `_bytes` bytes following that index. * @param memView The view * @param _index The index * @param _bytes The bytes * @return result - The unsigned integer */ function indexUint(bytes29 memView, uint256 _index, uint8 _bytes) internal pure returns (uint256 result) { return uint256(index(memView, _index, _bytes)) >> ((32 - _bytes) * 8); } /** * @notice Parse an unsigned integer from LE bytes. * @param memView The view * @param _index The index * @param _bytes The bytes * @return result - The unsigned integer */ function indexLEUint(bytes29 memView, uint256 _index, uint8 _bytes) internal pure returns (uint256 result) { return reverseUint256(uint256(index(memView, _index, _bytes))); } /** * @notice Parse an address from the view at `_index`. Requires that the view have >= 20 bytes * following that index. * @param memView The view * @param _index The index * @return address - The address */ function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) { return address(uint160(indexUint(memView, _index, 20))); } /** * @notice Return the keccak256 hash of the underlying memory * @param memView The view * @return digest - The keccak256 hash of the underlying memory */ function keccak(bytes29 memView) internal pure returns (bytes32 digest) { uint256 _loc = loc(memView); uint256 _len = len(memView); assembly { // solium-disable-previous-line security/no-inline-assembly digest := keccak256(_loc, _len) } } /** * @notice Return the sha2 digest of the underlying memory. * @dev We explicitly deallocate memory afterwards. * @param memView The view * @return digest - The sha2 hash of the underlying memory */ function sha2(bytes29 memView) internal view returns (bytes32 digest) { uint256 _loc = loc(memView); uint256 _len = len(memView); assembly { // solium-disable-previous-line security/no-inline-assembly let ptr := mload(0x40) pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1 digest := mload(ptr) } } /** * @notice Implements bitcoin's hash160 (rmd160(sha2())) * @param memView The pre-image * @return digest - the Digest */ function hash160(bytes29 memView) internal view returns (bytes20 digest) { uint256 _loc = loc(memView); uint256 _len = len(memView); assembly { // solium-disable-previous-line security/no-inline-assembly let ptr := mload(0x40) pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 pop(staticcall(gas(), 3, ptr, 0x20, ptr, 0x20)) // rmd160 digest := mload(add(ptr, 0xc)) // return value is 0-prefixed. } } /** * @notice Implements bitcoin's hash256 (double sha2) * @param memView A view of the preimage * @return digest - the Digest */ function hash256(bytes29 memView) internal view returns (bytes32 digest) { uint256 _loc = loc(memView); uint256 _len = len(memView); assembly { // solium-disable-previous-line security/no-inline-assembly let ptr := mload(0x40) pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1 pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2 digest := mload(ptr) } } /** * @notice Return true if the underlying memory is equal. Else false. * @param left The first view * @param right The second view * @return bool - True if the underlying memory is equal */ function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) { return (loc(left) == loc(right) && len(left) == len(right)) || keccak(left) == keccak(right); } /** * @notice Return false if the underlying memory is equal. Else true. * @param left The first view * @param right The second view * @return bool - False if the underlying memory is equal */ function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) { return !untypedEqual(left, right); } /** * @notice Compares type equality. * @dev Shortcuts if the pointers are identical, otherwise compares type and digest. * @param left The first view * @param right The second view * @return bool - True if the types are the same */ function equal(bytes29 left, bytes29 right) internal pure returns (bool) { return left == right || (typeOf(left) == typeOf(right) && keccak(left) == keccak(right)); } /** * @notice Compares type inequality. * @dev Shortcuts if the pointers are identical, otherwise compares type and digest. * @param left The first view * @param right The second view * @return bool - True if the types are not the same */ function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) { return !equal(left, right); } /** * @notice Copy the view to a location, return an unsafe memory reference * @dev Super Dangerous direct memory access. * * This reference can be overwritten if anything else modifies memory (!!!). * As such it MUST be consumed IMMEDIATELY. * This function is private to prevent unsafe usage by callers. * @param memView The view * @param _newLoc The new location * @return written - the unsafe memory reference */ function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) { require(notNull(memView), "TypedMemView/copyTo - Null pointer deref"); require(isValid(memView), "TypedMemView/copyTo - Invalid pointer deref"); uint256 _len = len(memView); uint256 _oldLoc = loc(memView); uint256 ptr; assembly { // solium-disable-previous-line security/no-inline-assembly ptr := mload(0x40) // revert if we're writing in occupied memory if gt(ptr, _newLoc) { revert(0x60, 0x20) // empty revert message } // use the identity precompile to copy // guaranteed not to fail, so pop the success pop(staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len)) } written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len); } /** * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to * the new memory * @dev Shortcuts if the pointers are identical, otherwise compares type and digest. * @param memView The view * @return ret - The view pointing to the new memory */ function clone(bytes29 memView) internal view returns (bytes memory ret) { uint256 ptr; uint256 _len = len(memView); assembly { // solium-disable-previous-line security/no-inline-assembly ptr := mload(0x40) // load unused memory pointer ret := ptr } unsafeCopyTo(memView, ptr + 0x20); assembly { // solium-disable-previous-line security/no-inline-assembly mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer mstore(ptr, _len) // write len of new array (in bytes) } } /** * @notice Join the views in memory, return an unsafe reference to the memory. * @dev Super Dangerous direct memory access. * * This reference can be overwritten if anything else modifies memory (!!!). * As such it MUST be consumed IMMEDIATELY. * This function is private to prevent unsafe usage by callers. * @param memViews The views * @return unsafeView - The conjoined view pointing to the new memory */ function unsafeJoin(bytes29[] memory memViews, uint256 _location) private view returns (bytes29 unsafeView) { assembly { // solium-disable-previous-line security/no-inline-assembly let ptr := mload(0x40) // revert if we're writing in occupied memory if gt(ptr, _location) { revert(0x60, 0x20) // empty revert message } } uint256 _offset = 0; for (uint256 i = 0; i < memViews.length; i ++) { bytes29 memView = memViews[i]; unsafeCopyTo(memView, _location + _offset); _offset += len(memView); } unsafeView = unsafeBuildUnchecked(0, _location, _offset); } /** * @notice Produce the keccak256 digest of the concatenated contents of multiple views. * @param memViews The views * @return bytes32 - The keccak256 digest */ function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) { uint256 ptr; assembly { // solium-disable-previous-line security/no-inline-assembly ptr := mload(0x40) // load unused memory pointer } return keccak(unsafeJoin(memViews, ptr)); } /** * @notice Produce the sha256 digest of the concatenated contents of multiple views. * @param memViews The views * @return bytes32 - The sha256 digest */ function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) { uint256 ptr; assembly { // solium-disable-previous-line security/no-inline-assembly ptr := mload(0x40) // load unused memory pointer } return sha2(unsafeJoin(memViews, ptr)); } /** * @notice copies all views, joins them into a new bytearray. * @param memViews The views * @return ret - The new byte array */ function join(bytes29[] memory memViews) internal view returns (bytes memory ret) { uint256 ptr; assembly { // solium-disable-previous-line security/no-inline-assembly ptr := mload(0x40) // load unused memory pointer } bytes29 _newView = unsafeJoin(memViews, ptr + 0x20); uint256 _written = len(_newView); uint256 _footprint = footprint(_newView); assembly { // solium-disable-previous-line security/no-inline-assembly // store the legnth mstore(ptr, _written) // new pointer is old + 0x20 + the footprint of the body mstore(0x40, add(add(ptr, _footprint), 0x20)) ret := ptr } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
[{"inputs":[{"internalType":"address","name":"_relay","type":"address"},{"internalType":"address","name":"_lockers","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"uint256","name":"_transferDeadline","type":"uint256"},{"internalType":"uint256","name":"_protocolPercentageFee","type":"uint256"},{"internalType":"uint256","name":"_slasherPercentageReward","type":"uint256"},{"internalType":"uint256","name":"_bitcoinFee","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"userTargetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"_lockerTargetAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"lockerLockingScript","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"requestIdOfLocker","type":"uint256"}],"name":"BurnDispute","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"userTargetAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"userScript","type":"bytes"},{"indexed":false,"internalType":"enum ScriptTypes","name":"scriptType","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"burntAmount","type":"uint256"},{"indexed":true,"internalType":"address","name":"lockerTargetAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"lockerLockingScript","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"requestIdOfLocker","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"CCBurn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_lockerTargetAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"lockerLockingScript","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"_blockNumber","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"txId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LockerDispute","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":true,"internalType":"address","name":"lockerTargetAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"requestIdOfLocker","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"bitcoinTxId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"bitcoinTxOutputIndex","type":"uint256"}],"name":"PaidCCBurn","type":"event"},{"inputs":[],"name":"bitcoinFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"_version","type":"bytes4"},{"internalType":"bytes","name":"_vin","type":"bytes"},{"internalType":"bytes","name":"_vout","type":"bytes"},{"internalType":"bytes4","name":"_locktime","type":"bytes4"},{"internalType":"uint256","name":"_blockNumber","type":"uint256"},{"internalType":"bytes","name":"_intermediateNodes","type":"bytes"},{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"bytes","name":"_lockerLockingScript","type":"bytes"},{"internalType":"uint256[]","name":"_burnReqIndexes","type":"uint256[]"},{"internalType":"uint256[]","name":"_voutIndexes","type":"uint256[]"}],"name":"burnProof","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"burnRequestCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"burnRequests","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"burntAmount","type":"uint256"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"bytes","name":"userScript","type":"bytes"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"isTransferred","type":"bool"},{"internalType":"enum ScriptTypes","name":"scriptType","type":"uint8"},{"internalType":"uint256","name":"requestIdOfLocker","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_userScript","type":"bytes"},{"internalType":"enum ScriptTypes","name":"_scriptType","type":"uint8"},{"internalType":"bytes","name":"_lockerLockingScript","type":"bytes"}],"name":"ccBurn","outputs":[{"internalType":"uint256","name":"_burntAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_lockerLockingScript","type":"bytes"},{"internalType":"uint256[]","name":"_indices","type":"uint256[]"}],"name":"disputeBurn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_lockerLockingScript","type":"bytes"},{"internalType":"bytes4[]","name":"_versions","type":"bytes4[]"},{"internalType":"bytes","name":"_inputVin","type":"bytes"},{"internalType":"bytes","name":"_inputVout","type":"bytes"},{"internalType":"bytes","name":"_outputVin","type":"bytes"},{"internalType":"bytes","name":"_outputVout","type":"bytes"},{"internalType":"bytes4[]","name":"_locktimes","type":"bytes4[]"},{"internalType":"bytes","name":"_inputIntermediateNodes","type":"bytes"},{"internalType":"uint256[]","name":"_indexesAndBlockNumbers","type":"uint256[]"}],"name":"disputeLocker","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_lockerTargetAddress","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"isTransferred","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"isUsedAsBurnProof","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolPercentageFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"relay","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bitcoinFee","type":"uint256"}],"name":"setBitcoinFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_lockers","type":"address"}],"name":"setLockers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_protocolPercentageFee","type":"uint256"}],"name":"setProtocolPercentageFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_relay","type":"address"}],"name":"setRelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_slasherPercentageReward","type":"uint256"}],"name":"setSlasherPercentageReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_teleBTC","type":"address"}],"name":"setTeleBTC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_transferDeadline","type":"uint256"}],"name":"setTransferDeadline","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slasherPercentageReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"teleBTC","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transferDeadline","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040523480156200001157600080fd5b506040516200572338038062005723833981016040819052620000349162000106565b6200003f3362000099565b60018055600280546001600160a01b03199081166001600160a01b03998a16179091556003805482169789169790971790965560058054909616949096169390931790935560065560079190915560085560095562000176565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200010157600080fd5b919050565b600080600080600080600060e0888a03121562000121578283fd5b6200012c88620000e9565b96506200013c60208901620000e9565b95506200014c60408901620000e9565b9450606088015193506080880151925060a0880151915060c0880151905092959891949750929550565b61559d80620001866000396000f3fe6080604052600436106101a05760003560e01c80638d3d78cd116100ec578063c780c03f1161008a578063ea73263711610064578063ea732637146104a4578063f0f44260146104b7578063f2fde38b146104d7578063f47e2240146104f7576101a7565b8063c780c03f14610451578063c805f68b14610464578063cdbe374114610484576101a7565b8063b14d3532116100c6578063b14d3532146103e5578063b59589d114610405578063b74d0d3514610425578063bed6a6021461043b576101a7565b80638d3d78cd1461037a5780638da5cb5b1461039a578063930a60e8146103b8576101a7565b80635c4f5f3e1161015957806373532b2a1161013357806373532b2a146102fa5780637ed557481461031a5780637f0f18171461033a5780637ffe9a921461035a576101a7565b80635c4f5f3e146102a557806361d027b3146102c5578063715018a6146102e5576101a7565b80631812adb6146101ac5780631876dec4146101d55780631e2361681461020d578063419cba7f1461024d57806343149dba146102635780634782bc3614610283576101a7565b366101a757005b600080fd5b3480156101b857600080fd5b506101c260075481565b6040519081526020015b60405180910390f35b3480156101e157600080fd5b506003546101f5906001600160a01b031681565b6040516001600160a01b0390911681526020016101cc565b34801561021957600080fd5b5061023d610228366004614b2f565b600c6020526000908152604090205460ff1681565b60405190151581526020016101cc565b34801561025957600080fd5b506101c260085481565b34801561026f57600080fd5b506101c261027e366004614e43565b61052b565b34801561028f57600080fd5b506102a361029e366004614b2f565b610a77565b005b3480156102b157600080fd5b506102a36102c0366004614b2f565b610b1d565b3480156102d157600080fd5b506005546101f5906001600160a01b031681565b3480156102f157600080fd5b506102a3610c2e565b34801561030657600080fd5b5061023d610315366004614c84565b610c64565b34801561032657600080fd5b506102a3610335366004614b2f565b6113c6565b34801561034657600080fd5b506102a3610355366004614aac565b61145a565b34801561036657600080fd5b5061023d610375366004614ae4565b6114ce565b34801561038657600080fd5b506004546101f5906001600160a01b031681565b3480156103a657600080fd5b506000546001600160a01b03166101f5565b3480156103c457600080fd5b506101c26103d3366004614aac565b600b6020526000908152604090205481565b3480156103f157600080fd5b506102a3610400366004614aac565b611526565b34801561041157600080fd5b506002546101f5906001600160a01b031681565b34801561043157600080fd5b506101c260095481565b34801561044757600080fd5b506101c260065481565b61023d61045f366004614ce9565b61159a565b34801561047057600080fd5b506102a361047f366004614aac565b611aff565b34801561049057600080fd5b506102a361049f366004614b2f565b611b73565b61023d6104b2366004614b5f565b611ba2565b3480156104c357600080fd5b506102a36104d2366004614aac565b611e49565b3480156104e357600080fd5b506102a36104f2366004614aac565b611ebd565b34801561050357600080fd5b50610517610512366004614ae4565b611f58565b6040516101cc98979695949392919061529b565b6000600260015414156105595760405162461bcd60e51b815260040161055090615264565b60405180910390fd5b600260015585806105ac5760405162461bcd60e51b815260206004820152601b60248201527f43434275726e526f757465723a2076616c7565206973207a65726f00000000006044820152606401610550565b6105b68686612055565b60035460405163aff2faa360e01b81526001600160a01b039091169063aff2faa3906105e89087908790600401615011565b60206040518083038186803b15801561060057600080fd5b505afa158015610614573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106389190614b0f565b6106545760405162461bcd60e51b81526004016105509061514d565b60035460405163626885b560e11b81526000916001600160a01b03169063c4d10b6a906106879088908890600401615011565b60206040518083038186803b15801561069f57600080fd5b505afa1580156106b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d79190614ac8565b6004549091506001600160a01b03166323b872dd336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018b9052606401602060405180830381600087803b15801561073a57600080fd5b505af115801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190614b0f565b50600061077f89836120f2565b6004805460035460405163095ea7b360e01b81526001600160a01b039182169381019390935260248301849052929350919091169063095ea7b390604401602060405180830381600087803b1580156107d757600080fd5b505af11580156107eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080f9190614b0f565b506003546040516338463cff60e01b81526001600160a01b03909116906338463cff9061084490899089908690600401615025565b602060405180830381600087803b15801561085e57600080fd5b505af1158015610872573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108969190614b47565b935061092b89858a8a600260009054906101000a90046001600160a01b03166001600160a01b0316632f796d906040518163ffffffff1660e01b815260040160206040518083038186803b1580156108ed57600080fd5b505afa158015610901573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109259190614b47565b876122ae565b6001600160a01b0382166000908152600a60205260409020805461095190600190615443565b8154811061096f57634e487b7160e01b600052603260045260246000fd5b906000526020600020906007020160040154826001600160a01b03166109923390565b6001600160a01b03167fe33c3da07e34f08c660e672e065c0fa53300573c646a21eadd6eef116a70e51e8b8b8e8a8d8d600a60008d6001600160a01b03166001600160a01b031681526020019081526020016000206001600a60008f6001600160a01b03166001600160a01b0316815260200190815260200160002080549050610a1c9190615443565b81548110610a3a57634e487b7160e01b600052603260045260246000fd5b906000526020600020906007020160060154604051610a5f979695949392919061505c565b60405180910390a45050600180555095945050505050565b6000546001600160a01b03163314610aa15760405162461bcd60e51b81526004016105509061522f565b8060641015610b185760405162461bcd60e51b815260206004820152603760248201527f43434275726e526f757465723a20736c61736865722070657263656e7461676560448201527f20726577617264206973206f7574206f662072616e67650000000000000000006064820152608401610550565b600855565b6000546001600160a01b03163314610b475760405162461bcd60e51b81526004016105509061522f565b60025460408051630a072bc560e41b815290516000926001600160a01b03169163a072bc50916004808301926020929190829003018186803b158015610b8c57600080fd5b505afa158015610ba0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc49190614b47565b9050808211610c285760405162461bcd60e51b815260206004820152602a60248201527f43434275726e526f757465723a207472616e7366657220646561646c696e6520604482015269697320746f6f206c6f7760b01b6064820152608401610550565b50600655565b6000546001600160a01b03163314610c585760405162461bcd60e51b81526004016105509061522f565b610c626000612476565b565b600060026001541415610c895760405162461bcd60e51b815260040161055090615264565b600260015560035460405163aff2faa360e01b81526001600160a01b039091169063aff2faa390610cc09087908790600401615011565b60206040518083038186803b158015610cd857600080fd5b505afa158015610cec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d109190614b0f565b610d2c5760405162461bcd60e51b81526004016105509061514d565b60035460405163626885b560e11b81526000916001600160a01b03169063c4d10b6a90610d5f9088908890600401615011565b60206040518083038186803b158015610d7757600080fd5b505afa158015610d8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610daf9190614ac8565b90506000600260009054906101000a90046001600160a01b03166001600160a01b0316632f796d906040518163ffffffff1660e01b815260040160206040518083038186803b158015610e0157600080fd5b505afa158015610e15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e399190614b47565b905060005b84518110156113b6576001600160a01b0383166000908152600a602052604090208551869083908110610e8157634e487b7160e01b600052603260045260246000fd5b602002602001015181548110610ea757634e487b7160e01b600052603260045260246000fd5b600091825260209091206005600790920201015460ff1615610f1e5760405162461bcd60e51b815260206004820152602a60248201527f43434275726e526f757465723a207265717565737420686173206265656e2070604482015269616964206265666f726560b01b6064820152608401610550565b6001600160a01b0383166000908152600a602052604090208551839190879084908110610f5b57634e487b7160e01b600052603260045260246000fd5b602002602001015181548110610f8157634e487b7160e01b600052603260045260246000fd5b90600052602060002090600702016004015410610fb05760405162461bcd60e51b81526004016105509061519d565b6001600160a01b0383166000908152600a60205260409020855160019190879084908110610fee57634e487b7160e01b600052603260045260246000fd5b60200260200101518154811061101457634e487b7160e01b600052603260045260246000fd5b60009182526020808320600792909202909101600501805460ff1916931515939093179092556003546008546001600160a01b038781168452600a909452604090922088519390911692631697565b9287926064928b908890811061108957634e487b7160e01b600052603260045260246000fd5b6020026020010151815481106110af57634e487b7160e01b600052603260045260246000fd5b9060005260206000209060070201600001546110cb91906153fb565b6110d591906153db565b336001600160a01b0388166000908152600a602052604090208a518b908890811061111057634e487b7160e01b600052603260045260246000fd5b60200260200101518154811061113657634e487b7160e01b600052603260045260246000fd5b906000526020600020906007020160000154600a60008a6001600160a01b03166001600160a01b031681526020019081526020016000208b888151811061118d57634e487b7160e01b600052603260045260246000fd5b6020026020010151815481106111b357634e487b7160e01b600052603260045260246000fd5b600091825260209091206007909102016002015460405160e087901b6001600160e01b03191681526001600160a01b03958616600482015260248101949094529184166044840152606483015291909116608482015260a401602060405180830381600087803b15801561122657600080fd5b505af115801561123a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125e9190614b0f565b506001600160a01b0383166000818152600a60205260409020865187908490811061129957634e487b7160e01b600052603260045260246000fd5b6020026020010151815481106112bf57634e487b7160e01b600052603260045260246000fd5b906000526020600020906007020160020160009054906101000a90046001600160a01b03166001600160a01b03167f58c23b4ae0617be275628875bcfd65759a441263099a256eeb27899fb5dd846d8989600a6000896001600160a01b03166001600160a01b031681526020019081526020016000208a878151811061135557634e487b7160e01b600052603260045260246000fd5b60200260200101518154811061137b57634e487b7160e01b600052603260045260246000fd5b90600052602060002090600702016006015460405161139c93929190615025565b60405180910390a3806113ae816154e2565b915050610e3e565b5050600180805595945050505050565b6000546001600160a01b031633146113f05760405162461bcd60e51b81526004016105509061522f565b8061271010156114555760405162461bcd60e51b815260206004820152602a60248201527f43434275726e526f757465723a2070726f746f636f6c20666565206973206f7560448201526974206f662072616e676560b01b6064820152608401610550565b600755565b806001600160a01b0381166114815760405162461bcd60e51b815260040161055090615116565b6000546001600160a01b031633146114ab5760405162461bcd60e51b81526004016105509061522f565b50600480546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0382166000908152600a6020526040812080548390811061150657634e487b7160e01b600052603260045260246000fd5b600091825260209091206005600790920201015460ff1690505b92915050565b806001600160a01b03811661154d5760405162461bcd60e51b815260040161055090615116565b6000546001600160a01b031633146115775760405162461bcd60e51b81526004016105509061522f565b50600380546001600160a01b0319166001600160a01b0392909216919091179055565b6000600260015414156115bf5760405162461bcd60e51b815260040161055090615264565b6002600181905589511480156115d6575083516002145b80156115e3575081516003145b61162f5760405162461bcd60e51b815260206004820152601a60248201527f43434275726e526f757465723a2077726f6e6720696e707574730000000000006044820152606401610550565b60035460405163aff2faa360e01b81526001600160a01b039091169063aff2faa39061165f908d90600401615049565b60206040518083038186803b15801561167757600080fd5b505afa15801561168b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116af9190614b0f565b6116cb5760405162461bcd60e51b81526004016105509061514d565b60006117298a6000815181106116f157634e487b7160e01b600052603260045260246000fd5b60200260200101518a8a8860008151811061171c57634e487b7160e01b600052603260045260246000fd5b60200260200101516124c6565b9050611787818460028151811061175057634e487b7160e01b600052603260045260246000fd5b6020026020010151868660018151811061177a57634e487b7160e01b600052603260045260246000fd5b60200260200101516125c7565b6117ec5760405162461bcd60e51b815260206004820152603060248201527f43434275726e526f757465723a20696e707574207472616e73616374696f6e2060448201526f1a5cc81b9bdd08199a5b985b1a5e995960821b6064820152608401610550565b6000818152600c602052604090205460ff16156118695760405162461bcd60e51b815260206004820152603560248201527f43434275726e526f757465723a207472616e73616374696f6e2068617320626560448201527432b7103ab9b2b21030b990313ab93710383937b7b360591b6064820152608401610550565b60008061189e8b8660008151811061189157634e487b7160e01b600052603260045260246000fd5b6020026020010151612739565b915091506118f18c6001815181106118c657634e487b7160e01b600052603260045260246000fd5b60200260200101518a8a8a60018151811061171c57634e487b7160e01b600052603260045260246000fd5b821461195e5760405162461bcd60e51b815260206004820152603660248201527f43434275726e526f757465723a206f7574706f696e7420747820646f65736e276044820152750e840dac2e8c6d040eed2e8d040deeae8e0eae840e8f60531b6064820152608401610550565b8c5160208e012061196f89836127e8565b80519060200120146119dc5760405162461bcd60e51b815260206004820152603060248201527f43434275726e526f757465723a206f757470757420747820646f65736e27742060448201526f3132b637b733903a37903637b1b5b2b960811b6064820152608401610550565b846002815181106119fd57634e487b7160e01b600052603260045260246000fd5b6020026020010151600654611a129190615351565b600260009054906101000a90046001600160a01b03166001600160a01b0316632f796d906040518163ffffffff1660e01b815260040160206040518083038186803b158015611a6057600080fd5b505afa158015611a74573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a989190614b47565b11611ab55760405162461bcd60e51b81526004016105509061519d565b611ae98a8e8588600281518110611adc57634e487b7160e01b600052603260045260246000fd5b602002602001015161285a565b505060018080559b9a5050505050505050505050565b806001600160a01b038116611b265760405162461bcd60e51b815260040161055090615116565b6000546001600160a01b03163314611b505760405162461bcd60e51b81526004016105509061522f565b50600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314611b9d5760405162461bcd60e51b81526004016105509061522f565b600955565b600060026001541415611bc75760405162461bcd60e51b815260040161055090615264565b60026001556001600160e01b0319881615611c245760405162461bcd60e51b815260206004820181905260248201527f43434275726e526f757465723a206e6f6e2d7a65726f206c6f636b2074696d656044820152606401610550565b60035460405163aff2faa360e01b81526001600160a01b039091169063aff2faa390611c54908790600401615049565b60206040518083038186803b158015611c6c57600080fd5b505afa158015611c80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca49190614b0f565b611cc05760405162461bcd60e51b81526004016105509061514d565b60035460405163626885b560e11b81526000916001600160a01b03169063c4d10b6a90611cf1908890600401615049565b60206040518083038186803b158015611d0957600080fd5b505afa158015611d1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d419190614ac8565b90508251845114611d945760405162461bcd60e51b815260206004820152601b60248201527f43434275726e526f757465723a2077726f6e6720696e646578657300000000006044820152606401610550565b6000611da28d8d8d8d6124c6565b9050611db0818a8a8a6125c7565b611e145760405162461bcd60e51b815260206004820152602f60248201527f43434275726e526f757465723a207472616e73616374696f6e20686173206e6f60448201526e1d08199a5b985b1a5e9959081e595d608a1b6064820152608401610550565b6000611e24828b858f8a8a612a2c565b9050611e32818d8985612e78565b505060018080559c9b505050505050505050505050565b806001600160a01b038116611e705760405162461bcd60e51b815260040161055090615116565b6000546001600160a01b03163314611e9a5760405162461bcd60e51b81526004016105509061522f565b50600580546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314611ee75760405162461bcd60e51b81526004016105509061522f565b6001600160a01b038116611f4c5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610550565b611f5581612476565b50565b600a6020528160005260406000208181548110611f7457600080fd5b600091825260209091206007909102018054600182015460028301546003840180549396509194506001600160a01b03169291611fb0906154ad565b80601f0160208091040260200160405190810160405280929190818152602001828054611fdc906154ad565b80156120295780601f10611ffe57610100808354040283529160200191612029565b820191906000526020600020905b81548152906001019060200180831161200c57829003601f168201915b505050600484015460058501546006909501549394909360ff8083169450610100909204909116915088565b600081600481111561207757634e487b7160e01b600052602160045260246000fd5b14806120a2575060048160048111156120a057634e487b7160e01b600052602160045260246000fd5b145b156120cd5781516020146120c85760405162461bcd60e51b8152600401610550906151ee565b6120ee565b81516014146120ee5760405162461bcd60e51b8152600401610550906151ee565b5050565b6000806127106007548561210691906153fb565b61211091906153db565b9050600954816121209190615351565b841161216e5760405162461bcd60e51b815260206004820152601f60248201527f43434275726e526f757465723a20616d6f756e7420697320746f6f206c6f77006044820152606401610550565b60095460009061217e8387615443565b6121889190615443565b6004805460055460405163a9059cbb60e01b81526001600160a01b039182169381019390935260248301869052929350919091169063a9059cbb90604401602060405180830381600087803b1580156121e057600080fd5b505af11580156121f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122189190614b0f565b506004805460095460405163a9059cbb60e01b81526001600160a01b0388811694820194909452602481019190915291169063a9059cbb90604401602060405180830381600087803b15801561226d57600080fd5b505af1158015612281573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a59190614b0f565b50949350505050565b604080516101008101825260006080820181905260a0820181905260c0820181815260e0830191909152888252602082018890523392820192909252606081018690529084600481111561231257634e487b7160e01b600052602160045260246000fd5b9081600481111561233357634e487b7160e01b600052602160045260246000fd5b9052506006546123439084615351565b6080820152600060a082018190526001600160a01b038316808252600b6020818152604084205460e0860181905292909352909152612383906001615351565b6001600160a01b038381166000908152600b6020908152604080832094909455600a81528382208054600180820183559184529282902086516007909402019283558582015190830155928401516002820180546001600160a01b031916919093161790915560608301518051849361240392600385019291019061487e565b50608082015160048281019190915560a083015160058301805460ff19169115159190911780825560c08501519261ff00199091169061010090849081111561245c57634e487b7160e01b600052602160045260246000fd5b021790555060e08201518160060155505050505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000806002868686866040516020016124e29493929190614f43565b60408051601f19818403018152908290526124fc91614f96565b602060405180830381855afa158015612519573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061253c9190614b47565b9050600060028260405160200161255591815260200190565b60408051601f198184030181529082905261256f91614f96565b602060405180830381855afa15801561258c573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906125af9190614b47565b90506125ba81612f01565b925050505b949350505050565b60025460405163d0a8973960e01b8152600481018590526000602482018190529182916001600160a01b039091169063d0a897399060440160206040518083038186803b15801561261757600080fd5b505afa15801561262b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264f9190614b47565b9050803410156126b35760405162461bcd60e51b815260206004820152602960248201527f43434275726e526f757465723a2072656c617920666565206973206e6f7420736044820152681d59999a58da595b9d60ba1b6064820152608401610550565b600254604051600091612710916001600160a01b03909116906126e0908a908a908a908a90602401614fe1565b60408051601f198184030181529190526020810180516001600160e01b0316634354da2560e01b17905284612f83565b9050612725336127208434615443565b612fb3565b808060200190518101906125ba9190614b0f565b6000808061274f61274a86836130d1565b6130f5565b905062ffffff1980821614156127a75760405162461bcd60e51b815260206004820152601a60248201527f426974636f696e48656c7065723a2076696e206973206e756c6c0000000000006044820152606401610550565b60006127b3828661322b565b905060006127c082613349565b90506127cb8161336d565b94506127d68161338f565b63ffffffff1693505050509250929050565b606060006127fe6127f985836130d1565b6133b1565b905062ffffff1980821614156128265760405162461bcd60e51b8152600401610550906150df565b600061283282856134a2565b9050600061283f8261359c565b905061285062ffffff1982166135ed565b9695505050505050565b60006128658561363d565b60035460405163626885b560e11b81526001600160401b039290921692506000916001600160a01b039091169063c4d10b6a906128a6908890600401615049565b60206040518083038186803b1580156128be57600080fd5b505afa1580156128d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f69190614ac8565b6003546008549192506001600160a01b0316906333c99e1d90839060649061291e90876153fb565b61292891906153db565b3360405160e085901b6001600160e01b03191681526001600160a01b0393841660048201526024810192909252909116604482015260648101859052608401602060405180830381600087803b15801561298157600080fd5b505af1158015612995573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b99190614b0f565b50806001600160a01b03167f7ff138134e34ccab071315c38e38eec079f54726b890304ab46e2c5ab6f722bb8685876064600854886129f891906153fb565b612a0291906153db565b612a0c9088615351565b604051612a1c94939291906150b0565b60405180910390a2505050505050565b600080805b8451811015612e6c576000858281518110612a5c57634e487b7160e01b600052603260045260246000fd5b60200260200101519050600a6000896001600160a01b03166001600160a01b031681526020019081526020016000208181548110612aaa57634e487b7160e01b600052603260045260246000fd5b600091825260209091206005600790920201015460ff16158015612b1957506001600160a01b0388166000908152600a6020526040902080548a919083908110612b0457634e487b7160e01b600052603260045260246000fd5b90600052602060002090600702016004015410155b15612e5957612cc487868481518110612b4257634e487b7160e01b600052603260045260246000fd5b6020026020010151600a60008c6001600160a01b03166001600160a01b031681526020019081526020016000208481548110612b8e57634e487b7160e01b600052603260045260246000fd5b90600052602060002090600702016003018054612baa906154ad565b80601f0160208091040260200160405190810160405280929190818152602001828054612bd6906154ad565b8015612c235780601f10612bf857610100808354040283529160200191612c23565b820191906000526020600020905b815481529060010190602001808311612c0657829003601f168201915b5050506001600160a01b038e166000908152600a6020526040902080549092508791508110612c6257634e487b7160e01b600052603260045260246000fd5b906000526020600020906007020160050160019054906101000a900460ff166004811115612ca057634e487b7160e01b600052602160045260246000fd5b6004811115612cbf57634e487b7160e01b600052602160045260246000fd5b6136d5565b6001600160401b0316925082600a60008a6001600160a01b03166001600160a01b031681526020019081526020016000208281548110612d1457634e487b7160e01b600052603260045260246000fd5b9060005260206000209060070201600101541415612e59576001600160a01b0388166000908152600a6020526040902080546001919083908110612d6857634e487b7160e01b600052603260045260246000fd5b60009182526020909120600790910201600501805460ff1916911515919091179055612d95846001615351565b6001600160a01b0389166000818152600a60205260409020805492965090917f1b46655c2f394f2191cb246d5982dbe00ad671f0b590e75e97c90ee97f1f782a919084908110612df557634e487b7160e01b600052603260045260246000fd5b9060005260206000209060070201600601548c888681518110612e2857634e487b7160e01b600052603260045260246000fd5b6020026020010151604051612e50939291909283526020830191909152604082015260600190565b60405180910390a25b5080612e64816154e2565b915050612a31565b50509695505050505050565b6000612e848484613910565b6001600160401b031690506000612e9a85613a14565b90508115801590612eb4575080612eb2876001615351565b145b15612ed7576000838152600c60205260409020805460ff19166001179055612ef9565b80861415612ef9576000838152600c60205260409020805460ff191660011790555b505050505050565b6000606081805b6020811015612f75578285612f1e83601f615443565b60208110612f3c57634e487b7160e01b600052603260045260246000fd5b1a60f81b604051602001612f51929190614fb2565b60405160208183030381529060405292508080612f6d906154e2565b915050612f08565b50506020015190505b919050565b6060612fa984848460405180606001604052806029815260200161553f60299139613a41565b90505b9392505050565b804710156130035760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610550565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613050576040519150601f19603f3d011682016040523d82523d6000602084013e613055565b606091505b50509050806130cc5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610550565b505050565b8151600090602084016130ec64ffffffffff85168284613b5e565b95945050505050565b6000818161310b815b62ffffff19841690613ba2565b50601884901c6001600160601b031661312b5762ffffff195b9250613224565b6000613138856000613c7c565b9050601885901c6001600160601b03166001600160401b0382166131655762ffffff195b94505050613224565b600061317083613dab565b60ff16905060005b836001600160401b03168110156131ec578282106131a15762ffffff195b965050505050613224565b60006131c16131b08486615443565b60055b62ffffff198c169190613e04565b90506131cc81613e38565b6131d69084615351565b92505080806131e4906154e2565b915050613178565b508181146132045762ffffff195b9550505050613224565b61321e60065b60d81b6301000000600160d81b0389161790565b95505050505b5050919050565b6000826006613239816130fe565b506000613247866000613c7c565b6001600160401b03169050601886901c6001600160601b03168186106132a25760405162461bcd60e51b815260206004820152601060248201526f2b34b7103932b0b21037bb32b9393ab760811b6044820152606401610550565b60006132ad83613dab565b60ff1690506000805b88811015613305576132dc6132cb8486615443565b60055b62ffffff198d169190613e04565b91506132e782613e38565b6132f19084615351565b92506132fe600182615351565b90506132b6565b506133136131b08385615443565b9050600061332082613e38565b9050613339838260045b62ffffff198e16929190613e8c565b975050505050505b505092915050565b6000816004613357816130fe565b506125bf62ffffff198516600060246003613e8c565b600081600361337b816130fe565b506125bf62ffffff19851660006020613efc565b600081600361339d816130fe565b506125bf62ffffff19851660206004614055565b600081816133be816130fe565b50601884901c6001600160601b03166133db5762ffffff19613124565b60006133e8856000613c7c565b9050601885901c6001600160601b03166001600160401b0382166134105762ffffff1961315c565b600061341b83613dab565b60ff16905060005b836001600160401b0316811015613486578282106134455762ffffff19613196565b600061345b6134548486615443565b600e6131b3565b90506134668161419f565b6134709084615351565b925050808061347e906154e2565b915050613423565b508181146134985762ffffff196131fa565b61321e600f61320a565b600082600f6134b0816130fe565b5060006134be866000613c7c565b6001600160401b03169050601886901c6001600160601b031681861061351a5760405162461bcd60e51b81526020600482015260116024820152702b37baba103932b0b21037bb32b9393ab760791b6044820152606401610550565b600061352583613dab565b60ff1690506000805b888110156135735761354a6135438486615443565b600e6132ce565b91506135558261419f565b61355f9084615351565b925061356c600182615351565b905061352e565b506135816134548385615443565b9050600061358e8261419f565b90506133398382600d61332a565b600081600d6135aa816130fe565b5060006135b8856008613c7c565b90506130ec6135c682613dab565b6135d1906008615394565b62ffffff1987169060ff166001600160401b0384166007613e8c565b60606000806136058460181c6001600160601b031690565b60405193508392506001600160601b0316905061362c84613627846020615351565b6141e8565b508181016020016040529052919050565b60008061364d6127f984836130d1565b905062ffffff1980821614156136755760405162461bcd60e51b8152600401610550906150df565b600080613683836000613c7c565b6001600160401b0316905060005b818110156136cc576136a384826134a2565b92506136ae83614340565b6136b89086615369565b9450806136c4816154e2565b915050613691565b50505050919050565b6000806136e56127f987836130d1565b905062ffffff19808216141561370d5760405162461bcd60e51b8152600401610550906150df565b600061371982876134a2565b905060006137268261359c565b9050600085600481111561374a57634e487b7160e01b600052602160045260246000fd5b14156137af5761376362ffffff19821660016020613efc565b60405160200161377591815260200190565b6040516020818303038152906040528051906020012086805190602001201461379f5760006137a8565b6137a882614340565b9350613905565b60018560048111156137d157634e487b7160e01b600052602160045260246000fd5b1415613810576137e862ffffff1982166003614362565b604051602001613775919060609190911b6bffffffffffffffffffffffff1916815260140190565b600285600481111561383257634e487b7160e01b600052602160045260246000fd5b1415613849576137e862ffffff1982166002614362565b600385600481111561386b57634e487b7160e01b600052602160045260246000fd5b1415613882576137e862ffffff1982166002614362565b60048560048111156138a457634e487b7160e01b600052602160045260246000fd5b1415613905576138bd62ffffff19821660026020613efc565b6040516020016138cf91815260200190565b604051602081830303815290604052805190602001208680519060200120146138f9576000613902565b61390282614340565b93505b505050949350505050565b6000806139206127f985836130d1565b905062ffffff1980821614156139485760405162461bcd60e51b8152600401610550906150df565b6000806000613958846000613c7c565b6001600160401b0316905060005b81811015613a095761397885826134a2565b93506139838461359c565b9250866040516020016139969190614f96565b604051602081830303815290604052805190602001206139bb8462ffffff19166135ed565b6040516020016139cb9190614f96565b6040516020818303038152906040528051906020012014156139f7576139f084614340565b9550613a09565b80613a01816154e2565b915050613966565b505050505092915050565b600080613a246127f984836130d1565b9050613a31816000613c7c565b6001600160401b03169392505050565b606082471015613aa25760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610550565b843b613af05760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610550565b600080866001600160a01b03168587604051613b0c9190614f96565b60006040518083038185875af1925050503d8060008114613b49576040519150601f19603f3d011682016040523d82523d6000602084013e613b4e565b606091505b50915091506125ba828286614370565b600080613b6b8385615351565b9050604051811115613b7b575060005b80613b8d5762ffffff19915050612fac565b5050606092831b9190911790911b1760181b90565b6000613bae83836143a9565b613c75576000613bcd613bc18560d81c90565b64ffffffffff166143cc565b9150506000613be28464ffffffffff166143cc565b6040517f5479706520617373657274696f6e206661696c65642e20476f7420307800000060208201526001600160b01b031960b086811b8216603d8401526c05c408af0e0cac6e8cac84060f609b1b604784015283901b16605482015290925060009150605e015b60405160208183030381529060405290508060405162461bcd60e51b81526004016105509190615049565b5090919050565b600080613c9162ffffff19851684600161448c565b905060fc8111613ca2579050611520565b8060fd1415613d0057613cc8613cb9846001615351565b62ffffff198616906002614055565b9150613cd382613dab565b60ff16600314613cfb57613cf9613cf462ffffff1986168560036000613e8c565b6144bc565b505b613da4565b8060fe1415613d5257613d26613d17846001615351565b62ffffff198616906004614055565b9150613d3182613dab565b60ff16600514613cfb57613cf9613cf462ffffff1986168560056000613e8c565b8060ff1415613da457613d78613d69846001615351565b62ffffff198616906008614055565b9150613d8382613dab565b60ff16600914613da457613341613cf462ffffff1986168560096000613e8c565b5092915050565b600060fc826001600160401b031611613dc657506001612f7e565b61ffff826001600160401b031611613de057506003612f7e565b63ffffffff826001600160401b031611613dfc57506005612f7e565b506009612f7e565b6000612fa98484613e1e8760181c6001600160601b031690565b6001600160601b0316613e319190615443565b8585613e8c565b6000816005613e46816130fe565b506000613e54856024613c7c565b9050806001600160401b0316613e6982613dab565b60ff16613e769190615351565b613e81906024615351565b6130ec906004615351565b600080613ea28660781c6001600160601b031690565b6001600160601b03169050613eb686614539565b84613ec18784615351565b613ecb9190615351565b1115613ede5762ffffff199150506125bf565b613ee88582615351565b90506128508364ffffffffff168286613b5e565b600060ff8216613f0e57506000612fac565b613f218460181c6001600160601b031690565b6001600160601b0316613f3760ff841685615351565b1115613f9b57613f82613f538560781c6001600160601b031690565b6001600160601b0316613f6f8660181c6001600160601b031690565b6001600160601b0316858560ff1661457a565b60405162461bcd60e51b81526004016105509190615049565b60208260ff1611156140155760405162461bcd60e51b815260206004820152603a60248201527f54797065644d656d566965772f696e646578202d20417474656d70746564207460448201527f6f20696e646578206d6f7265207468616e2033322062797465730000000000006064820152608401610550565b60088202600061402e8660781c6001600160601b031690565b6001600160601b031690506000600160ff1b60001984011d91909501511695945050505050565b6000612fa9614065858585613efc565b600881811c7eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff167fff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff009290911b9190911617601081811c7dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff167fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff00009290911b9190911617602081811c7bffffffff00000000ffffffff00000000ffffffff00000000ffffffff167fffffffff00000000ffffffff00000000ffffffff00000000ffffffff000000009290911b9190911617604081811c77ffffffffffffffff0000000000000000ffffffffffffffff1677ffffffffffffffff0000000000000000ffffffffffffffff199290911b9190911617608081811c91901b1790565b600081600e6141ad816130fe565b5060006141bb856008613c7c565b9050806001600160401b03166141d082613dab565b60ff166141dd9190615351565b6130ec906008615351565b600062ffffff1980841614156142515760405162461bcd60e51b815260206004820152602860248201527f54797065644d656d566965772f636f7079546f202d204e756c6c20706f696e7460448201526732b9103232b932b360c11b6064820152608401610550565b61425a836146a4565b6142ba5760405162461bcd60e51b815260206004820152602b60248201527f54797065644d656d566965772f636f7079546f202d20496e76616c696420706f60448201526a34b73a32b9103232b932b360a91b6064820152608401610550565b60006142cf8460181c6001600160601b031690565b6001600160601b0316905060006142ef8560781c6001600160601b031690565b6001600160601b03169050600060405190508481111561430f5760206060fd5b8285848460045afa506128506143258760d81c90565b64ffffffffff60601b606091821b168717901b841760181b90565b600081600d61434e816130fe565b506125bf62ffffff19851660006008614055565b6000612fac8383601461448c565b6060831561437f575081612fac565b82511561438f5782518084602001fd5b8160405162461bcd60e51b81526004016105509190615049565b60008164ffffffffff166143bd8460d81c90565b64ffffffffff16149392505050565b600080601f5b600f8160ff16111561442a5760006143eb82600861541a565b60ff1685901c90506143fc816146e2565b61ffff16841793508160ff1660101461441757601084901b93505b5061442360018261545a565b90506143d2565b50600f5b60ff8160ff16101561448657600061444782600861541a565b60ff1685901c9050614458816146e2565b61ffff16831792508160ff1660001461447357601083901b92505b5061447f60018261545a565b905061442e565b50915091565b600061449982602061545a565b6144a490600861541a565b60ff166144b2858585613efc565b901c949350505050565b606060006144e66144e162ffffff19851683601887901c6001600160601b031661448c565b6143cc565b6040517f4e6f6e2d6d696e696d616c2076617220696e742e20476f74203078000000000060208201526dffffffffffffffffffffffffffff19607083901b16603b82015290925060009150604d01613c4a565b600061454e8260181c6001600160601b031690565b6145618360781c6001600160601b031690565b61456b91906153b9565b6001600160601b031692915050565b60606000614587866143cc565b9150506000614595866143cc565b91505060006145a3866143cc565b91505060006145b1866143cc565b604080517f54797065644d656d566965772f696e646578202d204f76657272616e20746865602082015274040ecd2caee5c40a6d8d2c6ca40d2e640c2e84060f605b1b818301526001600160d01b031960d098891b811660558301526e040eed2e8d040d8cadccee8d04060f608b1b605b830181905297891b8116606a8301527f2e20417474656d7074656420746f20696e646578206174206f666673657420306070830152600f60fb1b609083015295881b861660918201526097810196909652951b90921660a68401525050601760f91b60ac8201528151808203608d01815260ad90910190915295945050505050565b60006146b08260d81c90565b64ffffffffff1664ffffffffff14156146cb57506000612f7e565b60006146d683614539565b60405110199392505050565b60006146f460048360ff16901c614712565b60ff161760081b62ffff001661470982614712565b60ff1617919050565b600060f08083179060ff8216141561472e576030915050612f7e565b8060ff1660f11415614744576031915050612f7e565b8060ff1660f2141561475a576032915050612f7e565b8060ff1660f31415614770576033915050612f7e565b8060ff1660f41415614786576034915050612f7e565b8060ff1660f5141561479c576035915050612f7e565b8060ff1660f614156147b2576036915050612f7e565b8060ff1660f714156147c8576037915050612f7e565b8060ff1660f814156147de576038915050612f7e565b8060ff1660f914156147f4576039915050612f7e565b8060ff1660fa141561480a576061915050612f7e565b8060ff1660fb1415614820576062915050612f7e565b8060ff1660fc1415614836576063915050612f7e565b8060ff1660fd141561484c576064915050612f7e565b8060ff1660fe1415614862576065915050612f7e565b8060ff1660ff1415614878576066915050612f7e565b50919050565b82805461488a906154ad565b90600052602060002090601f0160209004810192826148ac57600085556148f2565b82601f106148c557805160ff19168380011785556148f2565b828001600101855582156148f2579182015b828111156148f25782518255916020019190600101906148d7565b506148fe929150614902565b5090565b5b808211156148fe5760008155600101614903565b600082601f830112614927578081fd5b8135602061493c6149378361532e565b6152fe565b8281528181019085830183850287018401881015614958578586fd5b855b8581101561497d5761496b826149e4565b8452928401929084019060010161495a565b5090979650505050505050565b600082601f83011261499a578081fd5b813560206149aa6149378361532e565b82815281810190858301838502870184018810156149c6578586fd5b855b8581101561497d578135845292840192908401906001016149c8565b80356001600160e01b031981168114612f7e57600080fd5b60008083601f840112614a0d578182fd5b5081356001600160401b03811115614a23578182fd5b602083019150836020828501011115614a3b57600080fd5b9250929050565b600082601f830112614a52578081fd5b81356001600160401b03811115614a6b57614a6b615513565b614a7e601f8201601f19166020016152fe565b818152846020838601011115614a92578283fd5b816020850160208301379081016020019190915292915050565b600060208284031215614abd578081fd5b8135612fac81615529565b600060208284031215614ad9578081fd5b8151612fac81615529565b60008060408385031215614af6578081fd5b8235614b0181615529565b946020939093013593505050565b600060208284031215614b20578081fd5b81518015158114612fac578182fd5b600060208284031215614b40578081fd5b5035919050565b600060208284031215614b58578081fd5b5051919050565b6000806000806000806000806000806101408b8d031215614b7e578586fd5b614b878b6149e4565b995060208b01356001600160401b0380821115614ba2578788fd5b614bae8e838f01614a42565b9a5060408d0135915080821115614bc3578788fd5b614bcf8e838f01614a42565b9950614bdd60608e016149e4565b985060808d0135975060a08d0135915080821115614bf9578687fd5b614c058e838f01614a42565b965060c08d0135955060e08d0135915080821115614c21578485fd5b614c2d8e838f01614a42565b94506101008d0135915080821115614c43578384fd5b614c4f8e838f0161498a565b93506101208d0135915080821115614c65578283fd5b50614c728d828e0161498a565b9150509295989b9194979a5092959850565b600080600060408486031215614c98578283fd5b83356001600160401b0380821115614cae578485fd5b614cba878388016149fc565b90955093506020860135915080821115614cd2578283fd5b50614cdf8682870161498a565b9150509250925092565b60008060008060008060008060006101208a8c031215614d07578283fd5b89356001600160401b0380821115614d1d578485fd5b614d298d838e01614a42565b9a5060208c0135915080821115614d3e578485fd5b614d4a8d838e01614917565b995060408c0135915080821115614d5f578485fd5b614d6b8d838e01614a42565b985060608c0135915080821115614d80578485fd5b614d8c8d838e01614a42565b975060808c0135915080821115614da1578485fd5b614dad8d838e01614a42565b965060a08c0135915080821115614dc2578485fd5b614dce8d838e01614a42565b955060c08c0135915080821115614de3578485fd5b614def8d838e01614917565b945060e08c0135915080821115614e04578384fd5b614e108d838e01614a42565b93506101008c0135915080821115614e26578283fd5b50614e338c828d0161498a565b9150509295985092959850929598565b600080600080600060808688031215614e5a578283fd5b8535945060208601356001600160401b0380821115614e77578485fd5b614e8389838a01614a42565b95506040880135915060058210614e98578485fd5b90935060608701359080821115614ead578283fd5b50614eba888289016149fc565b969995985093965092949392505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b60008151808452614f0d81602086016020860161547d565b601f01601f19169290920160200192915050565b60058110614f3f57634e487b7160e01b600052602160045260246000fd5b9052565b600063ffffffff60e01b80871683528551614f65816004860160208a0161547d565b855190840190614f7c816004840160208a0161547d565b919094169301600481019390935250506008019392505050565b60008251614fa881846020870161547d565b9190910192915050565b60008351614fc481846020880161547d565b6001600160f81b0319939093169190920190815260010192915050565b6000858252846020830152608060408301526150006080830185614ef5565b905082606083015295945050505050565b600060208252612fa9602083018486614ecb565b600060408252615039604083018587614ecb565b9050826020830152949350505050565b600060208252612fac6020830184614ef5565b600060c0825261506f60c083018a614ef5565b61507c602084018a614f21565b876040840152866060840152828103608084015261509b818688614ecb565b9150508260a083015298975050505050505050565b6000608082526150c36080830187614ef5565b6020830195909552506040810192909252606090910152919050565b6020808252601b908201527f426974636f696e48656c7065723a20766f7574206973206e756c6c0000000000604082015260600190565b6020808252601d908201527f43434275726e526f757465723a2061646472657373206973207a65726f000000604082015260600190565b60208082526030908201527f43434275726e526f757465723a20676976656e206c6f636b696e67207363726960408201526f383a1034b9903737ba103637b1b5b2b960811b606082015260800190565b60208082526031908201527f43434275726e526f757465723a207061796261636b20646561646c696e652068604082015270185cc81b9bdd081c185cdcd959081e595d607a1b606082015260800190565b60208082526021908201527f43434275726e526f757465723a20696e76616c696420757365722073637269706040820152601d60fa1b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b888152602081018890526001600160a01b0387166040820152610100606082018190526000906152cd83820189614ef5565b91505085608083015284151560a08301526152eb60c0830185614f21565b8260e08301529998505050505050505050565b604051601f8201601f191681016001600160401b038111828210171561532657615326615513565b604052919050565b60006001600160401b0382111561534757615347615513565b5060209081020190565b60008219821115615364576153646154fd565b500190565b60006001600160401b0380831681851680830382111561538b5761538b6154fd565b01949350505050565b600060ff821660ff84168060ff038211156153b1576153b16154fd565b019392505050565b60006001600160601b0380831681851680830382111561538b5761538b6154fd565b6000826153f657634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615615415576154156154fd565b500290565b600060ff821660ff84168160ff048111821515161561543b5761543b6154fd565b029392505050565b600082821015615455576154556154fd565b500390565b600060ff821660ff841680821015615474576154746154fd565b90039392505050565b60005b83811015615498578181015183820152602001615480565b838111156154a7576000848401525b50505050565b6002810460018216806154c157607f821691505b6020821081141561487857634e487b7160e01b600052602260045260246000fd5b60006000198214156154f6576154f66154fd565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114611f5557600080fdfe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220ae6c1105e8965ae97e8bc35586d69add5181e1915339b31578307b974009e7de64736f6c634300080200330000000000000000000000005519fa2b1a4069556bc11470cdea61ba4920f7e8000000000000000000000000c0aec12ed73144cb4697b0ea2341cea5a345028c0000000000000000000000005364e3557572bd5d5903c0e9c21be359f2eac1da000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|