Overview
APE Balance
0 APE
APE Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 16 from a total of 16 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Public Set Peer | 2051215 | 32 days ago | IN | 0 APE | 0.00123498 | ||||
Public Set Peer | 2051214 | 32 days ago | IN | 0 APE | 0.00123498 | ||||
Public Set Peer | 2051214 | 32 days ago | IN | 0 APE | 0.00123498 | ||||
Public Set Peer | 2051214 | 32 days ago | IN | 0 APE | 0.00123498 | ||||
Public Set Peer | 2051214 | 32 days ago | IN | 0 APE | 0.00123498 | ||||
Public Set Peer | 2051214 | 32 days ago | IN | 0 APE | 0.00123468 | ||||
Public Set Peer | 2051214 | 32 days ago | IN | 0 APE | 0.00123468 | ||||
Public Set Peer | 2051213 | 32 days ago | IN | 0 APE | 0.00123498 | ||||
Public Set Peer | 2051212 | 32 days ago | IN | 0 APE | 0.00123498 | ||||
Public Set Peer | 2051212 | 32 days ago | IN | 0 APE | 0.00123498 | ||||
Public Set Peer | 2051212 | 32 days ago | IN | 0 APE | 0.00123498 | ||||
Public Set Peer | 2051212 | 32 days ago | IN | 0 APE | 0.00123498 | ||||
Public Set Peer | 2051212 | 32 days ago | IN | 0 APE | 0.00123468 | ||||
Public Set Peer | 2051212 | 32 days ago | IN | 0 APE | 0.00123468 | ||||
Public Set Peer | 2051211 | 32 days ago | IN | 0 APE | 0.00123498 | ||||
0x60a03462 | 2048571 | 32 days ago | IN | 0 APE | 0.11614453 |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Bridges
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "./bridgedToken.sol"; import "./ierc20metadata.sol"; import {OApp, Origin, MessagingFee} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/OApp.sol"; import "../lib/LayerZero-v2/packages/layerzero-v2/evm/oapp/contracts/oapp/OApp.sol"; import "../lib/LayerZero-v2/packages/layerzero-v2/evm/protocol/contracts/interfaces/ILayerZeroEndpointV2.sol"; import {OptionsBuilder} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/libs/OptionsBuilder.sol"; import "../lib/LayerZero-v2/packages/layerzero-v2/evm/oapp/contracts/oapp/libs/OptionsBuilder.sol"; import "../lib/openzeppelin-contracts/contracts/utils/Strings.sol"; import "../lib/solidity-stringutils/strings.sol"; import './IOmnify.sol'; import './ownable.sol'; interface IBridgedOmniToken { function mint(address _recipient, uint256 _amount) external; function burnSenderTokens(address _sender, uint256 _amount) external; function decimals() external view returns (uint8); function balanceOf(address account) external view returns (uint256); function changeOmnifyAddress(address newAddress) external; } contract Bridges is OApp, Ownable { using OptionsBuilder for bytes; using strings for *; event NewBridgedTokenCreated( uint32 _sourceChainId, uint32 _thisChainId, address _creator, address _bridgedAssetAddress, string _bridgedAssetName, string _bridgedAssetSymbol, address _sourceAssetAddress, string _sourceAssetName, string _sourceAssetSymbol); event AssetsMigrated( uint256 _id, address _asset, uint256 _amount, uint32 _sourceChain, address _sourceAddress, uint32 _destinationChain, address _destinationAddress, uint256 _blockNumber, uint256 _date ); event AssetsReceived( uint256 _id, address _asset, uint256 _amount, uint32 _sourceChain, address _sourceAddress, uint32 _destinationChain, address _destinationAddress, uint256 _blockNumber, uint256 _date ); struct BridgeProfile { address person; uint256 transactionCount; mapping(uint256 => uint256) transactions; uint256 migratedAssetCount; mapping(uint256 => ProfileMigratedAsset) assetAmountMigrated; mapping(address => uint256) migratedAssetToCount; uint256 receivedAssetCount; mapping(uint256 => ProfileReceivedAsset) assetAmountReceived; mapping(address => uint256) receivedAssetToCount; } struct ProfileMigratedAsset { address asset; uint256 amountMigrated; } struct ProfileReceivedAsset { address asset; uint256 amountReceived; } struct BridgeTransaction { address asset; uint256 amount; uint32 sourceChain; uint32 destinationChain; address sourceAddress; address destinationAddress; uint256 date; } constructor( address _endpoint, uint256 _paramBridgeFee, uint32 _paramChainId, address _paramOmnifyAddress )OApp(_endpoint, msg.sender) Ownable(msg.sender){ bridgeFee = _paramBridgeFee; thisChainEid = _paramChainId; GAS_LIMIT = 2000000; omnifyAddress = _paramOmnifyAddress; } mapping(address => mapping(uint32 => address)) public bridgedTokenForeignEquivalent; mapping(uint32 => mapping(address => address)) public foreignTokenBridgedEquivalent; uint256 internal MAXUINT = 2 ** 256 - 1; uint256 public bridgeFee; uint256 public numberReceivedTransactions; uint256 public numberMigrationTransactions; uint256 public amountReceivedAssets; uint256 public amountMigratedAssets; uint256 public transactionCount; uint32 public thisChainEid; uint128 public GAS_LIMIT; address public feeKeeperAddress; address public omnifyAddress; mapping(address => BridgeProfile) public bridgeProfiles; mapping(uint256 => BridgeTransaction) public bridgeTransactions; function getMinAmount(uint8 _decimals) public pure returns (uint256) { if (_decimals == 0) { return 1; } if (_decimals == 1) { return 0.1 * (10 ** 1); } if (_decimals == 2) { return 0.01 * (10 ** 2); } if (_decimals >= 3) { uint8 powa = _decimals - 3; //0.001 return 1 * (10 ** powa); } return 1; } modifier onlyFeeKeeper(address _sender){ require(_sender == feeKeeperAddress); _; } function setOmnifyAddress(address _newaddress) external onlyOwner { omnifyAddress = _newaddress; } function setBridgeFee(uint256 _fee) external onlyOwner { bridgeFee = _fee; } function setFeeKeeperAddress(address _feeKeeper) external onlyOwner { feeKeeperAddress = _feeKeeper; } function setBridgeFeeByFeeKeeper(uint256 _fee) external onlyFeeKeeper(msg.sender) { bridgeFee = _fee; } function setGasLimit(uint128 _limit) external onlyOwner { GAS_LIMIT = _limit; } function setGasLimitByFeeKeeper(uint128 _limit) external onlyFeeKeeper(msg.sender) { GAS_LIMIT = _limit; } function createLzReceiveOption(uint128 _gas, uint128 _value) public pure returns (bytes memory) { return OptionsBuilder.newOptions().addExecutorLzReceiveOption(_gas, _value); } function lookupBridgeTransaction(uint256 _id) public view returns (BridgeTransaction memory) { return bridgeTransactions[_id]; } function publicSetPeer(uint32 _eid, address _peer) public onlyOwner { bytes32 _addressBytes = bytes32(uint256(uint160(_peer))); setPeer(_eid, _addressBytes); } function publicSetDelegate(address _delegate) public onlyOwner { setDelegate(_delegate); } function lookupBridgeProfileTransactions(address _profile) public view returns (uint256[] memory) { uint256 count = bridgeProfiles[_profile].transactionCount; uint256[] memory trans = new uint256[](count); if (count > 0) { for (uint256 i = 0; i < count; i++) { trans[i] = bridgeProfiles[_profile].transactions[i + 1]; } } return trans; } function lookupBridgeProfileMigratedAssets(address _profile) public view returns (ProfileMigratedAsset[] memory) { uint256 count = bridgeProfiles[_profile].migratedAssetCount; ProfileMigratedAsset[] memory migs = new ProfileMigratedAsset[](count); if (count > 0) { for (uint256 i = 0; i < count; i++) { migs[i] = bridgeProfiles[_profile].assetAmountMigrated[i + 1]; } } return migs; } function lookupBridgeProfileReceivedAssets(address _profile) public view returns (ProfileReceivedAsset[] memory) { uint256 count = bridgeProfiles[_profile].receivedAssetCount; ProfileReceivedAsset[] memory recs = new ProfileReceivedAsset[](count); if (count > 0) { for (uint256 i = 0; i < count; i++) { recs[i] = bridgeProfiles[_profile].assetAmountReceived[i + 1]; } } return recs; } function compare(string memory str1, string memory str2) public pure returns (bool) { if (bytes(str1).length != bytes(str2).length) { return false; } return keccak256(abi.encodePacked(str1)) == keccak256(abi.encodePacked(str2)); } function quote( uint32 _dstEid, // Destination chain's endpoint ID. string memory _message, // The message to send. bytes memory _options, // Message execution options bool _payInLzToken // boolean for which token to return fee in ) public view returns (uint256 nativeFee, uint256 lzTokenFee) { bytes memory _payload = abi.encode(_message); MessagingFee memory fee = _quote(_dstEid, _payload, _options, _payInLzToken); return (fee.nativeFee, fee.lzTokenFee); } function dotter(string memory val) private pure returns (string memory){ return string.concat(val, "."); } function convertBoolToString(bool input) private pure returns (string memory) { if (input) { return "true"; } else { return "false"; } } function convertStringToBool(string memory input) private pure returns (bool){ if (compare("true", input)) { return true; } else { return false; } } // function lookupAllBridgedTokensFromChain(uint32 _chain) public view returns (mapping(address => address) memory){ // return foreignTokenBridgedEquivalent[_chain]; // } function migrateAssets(address _sourceAsset, uint256 _amount, uint32 _destinationChain, address _recipient) external payable { require(_destinationChain != thisChainEid); MYIERC20Metadata _theCoin = MYIERC20Metadata(_sourceAsset); require(_sourceAsset != address(0)); address _foreignEquivalent = lookupBridgedTokenForeignEquivalent(_sourceAsset, _destinationChain); address _bridgedEquivalent = lookupForeignTokenBridgedEquivalent(_foreignEquivalent, _destinationChain); bool isReturningBridgedAsset = (_bridgedEquivalent != address(0)) && (_bridgedEquivalent == _sourceAsset); string memory sourceAssetString = Strings.toHexString(uint256(uint160(_sourceAsset)), 20); string memory dottedSourceAssetString = dotter(sourceAssetString); string memory thisChainEidString = Strings.toString(uint256(thisChainEid)); string memory dottedThisChainIdString = dotter(thisChainEidString); string memory senderAddressString = Strings.toHexString(uint256(uint160(msg.sender)), 20); string memory dottedSenderAddressString = dotter(senderAddressString); string memory recipientAddressString = Strings.toHexString(uint256(uint160(_recipient)), 20); string memory dottedRecipientAddressString = dotter(recipientAddressString); string memory amountString = Strings.toString(_amount); string memory dottedAmountString = dotter(amountString); string memory assetName = _theCoin.name(); string memory dottedAssetName = dotter(assetName); string memory assetSymbol = _theCoin.symbol(); string memory dottedAssetSymbol = dotter(assetSymbol); uint8 decimals = _theCoin.decimals(); string memory decimalsString = Strings.toString(uint256(decimals)); string memory dottedDecimalsString = dotter(decimalsString); string memory isReturningBridgedAssetString = convertBoolToString(isReturningBridgedAsset); string memory dottedIsReturningBridgedAsset = dotter(isReturningBridgedAssetString); string memory foreignEquivalentAddressString = Strings.toHexString(uint256(uint160(_foreignEquivalent)), 20); string memory _message = string.concat(dottedSourceAssetString, dottedThisChainIdString, dottedSenderAddressString, dottedRecipientAddressString, dottedAmountString, dottedAssetName, dottedAssetSymbol, dottedDecimalsString, dottedIsReturningBridgedAsset, foreignEquivalentAddressString); // message: sourceAssetAddress.thisChainEid.msgsenderaddress.recipientAddress.amount.assetName.assetSymbol.decimals.isReturningBridgedAsset.foreignEquivalentAddress bytes memory _payload = abi.encode(_message); bytes memory _options = createLzReceiveOption(GAS_LIMIT, 0); (uint256 nativeGas,) = quote(_destinationChain, _message, _options, false); require(msg.value == bridgeFee + nativeGas); if (isReturningBridgedAsset) { IBridgedOmniToken _theToken = IBridgedOmniToken(_sourceAsset); uint8 _decimals = _theToken.decimals(); uint256 _minAmount = getMinAmount(_decimals); require(_amount >= _minAmount); uint256 balanceOfCaller = _theToken.balanceOf(msg.sender); require(balanceOfCaller >= _amount); _theToken.burnSenderTokens(msg.sender, _amount); } else { uint8 _decimals = _theCoin.decimals(); uint256 _minAmount = getMinAmount(_decimals); require(_amount >= _minAmount); bool success = _theCoin.transferFrom(msg.sender, address(this), _amount); require(success); } IOmnify mainContract = IOmnify(omnifyAddress); mainContract.addProfitsFromExternalContract{value: bridgeFee}(); numberMigrationTransactions++; amountMigratedAssets = safeAdd(amountMigratedAssets, _amount); transactionCount++; bridgeTransactions[transactionCount].asset = _sourceAsset; bridgeTransactions[transactionCount].amount = _amount; bridgeTransactions[transactionCount].sourceChain = thisChainEid; bridgeTransactions[transactionCount].destinationChain = _destinationChain; bridgeTransactions[transactionCount].sourceAddress = msg.sender; bridgeTransactions[transactionCount].destinationAddress = _recipient; bridgeTransactions[transactionCount].date = block.timestamp; uint256 thisAssetProfileCount = bridgeProfiles[msg.sender].migratedAssetToCount[_sourceAsset]; bridgeProfiles[msg.sender].transactionCount++; bridgeProfiles[msg.sender].transactions[bridgeProfiles[msg.sender].transactionCount] = transactionCount; if (thisAssetProfileCount > 0) { bridgeProfiles[msg.sender].assetAmountMigrated[thisAssetProfileCount].amountMigrated = safeAdd(bridgeProfiles[msg.sender].assetAmountMigrated[thisAssetProfileCount].amountMigrated, _amount); } else { bridgeProfiles[msg.sender].migratedAssetCount++; bridgeProfiles[msg.sender].migratedAssetToCount[_sourceAsset] = bridgeProfiles[msg.sender].migratedAssetCount; bridgeProfiles[msg.sender].assetAmountMigrated[bridgeProfiles[msg.sender].migratedAssetCount].asset = _sourceAsset; bridgeProfiles[msg.sender].assetAmountMigrated[bridgeProfiles[msg.sender].migratedAssetCount].amountMigrated = safeAdd(bridgeProfiles[msg.sender].assetAmountMigrated[bridgeProfiles[msg.sender].migratedAssetCount].amountMigrated, _amount); } _lzSend(_destinationChain, _payload, _options, MessagingFee(nativeGas, 0), payable(msg.sender)); emit AssetsMigrated( transactionCount, _sourceAsset, _amount, thisChainEid, msg.sender, _destinationChain, _recipient, block.number, block.timestamp ); } function decodeMessage(bytes calldata data) private pure returns (string memory){ return abi.decode(data, (string)); } function stringToUint(string memory s) private pure returns (uint result) { bytes memory b = bytes(s); uint i; result = 0; for (i = 0; i < b.length; i++) { uint c = uint256(uint8(b[i])); if (c >= 48 && c <= 57) { result = result * 10 + (c - 48); } } } function stringToAddress(string memory _address) public pure returns (address) { string memory cleanAddress = remove0xPrefix(_address); bytes20 _addressBytes = parseHexStringToBytes20(cleanAddress); return address(_addressBytes); } function remove0xPrefix(string memory _hexString) internal pure returns (string memory) { if (bytes(_hexString).length >= 2 && bytes(_hexString)[0] == '0' && (bytes(_hexString)[1] == 'x' || bytes(_hexString)[1] == 'X')) { return substring(_hexString, 2, bytes(_hexString).length); } return _hexString; } function substring(string memory _str, uint256 _start, uint256 _end) internal pure returns (string memory) { bytes memory _strBytes = bytes(_str); bytes memory _result = new bytes(_end - _start); for (uint256 i = _start; i < _end; i++) { _result[i - _start] = _strBytes[i]; } return string(_result); } function parseHexStringToBytes20(string memory _hexString) internal pure returns (bytes20) { bytes memory _bytesString = bytes(_hexString); uint160 _parsedBytes = 0; for (uint256 i = 0; i < _bytesString.length; i += 2) { _parsedBytes *= 256; uint8 _byteValue = parseByteToUint8(_bytesString[i]); _byteValue *= 16; _byteValue += parseByteToUint8(_bytesString[i + 1]); _parsedBytes += _byteValue; } return bytes20(_parsedBytes); } function parseByteToUint8(bytes1 _byte) internal pure returns (uint8) { if (uint8(_byte) >= 48 && uint8(_byte) <= 57) { return uint8(_byte) - 48; } else if (uint8(_byte) >= 65 && uint8(_byte) <= 70) { return uint8(_byte) - 55; } else if (uint8(_byte) >= 97 && uint8(_byte) <= 102) { return uint8(_byte) - 87; } else { revert(string(abi.encodePacked("Invalid byte value: ", _byte))); } } function _lzReceive(Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData) internal override { //message: sourceAssetAddress.thisChainEid.msgsenderaddress.recipientAddress.amount.assetName.assetSymbol.decimals.isReturningBridgedAsset.foreignEquivalentAddress string memory _decodedMessage = decodeMessage(_message); strings.slice memory s = _decodedMessage.toSlice(); strings.slice memory delim = ".".toSlice(); string memory sourceAssetAddressString = s.split(delim).toString(); address sourceAssetAddress = stringToAddress(sourceAssetAddressString); string memory chainEidString = s.split(delim).toString(); uint chainEid = stringToUint(chainEidString); string memory senderAddressString = s.split(delim).toString(); address senderAddress = stringToAddress(senderAddressString); string memory recipientAddressString = s.split(delim).toString(); address recipientAddress = stringToAddress(recipientAddressString); string memory amountString = s.split(delim).toString(); uint amount = stringToUint(amountString); string memory assetName = s.split(delim).toString(); string memory assetSymbol = s.split(delim).toString(); string memory decimalsString = s.split(delim).toString(); uint decimals = stringToUint(decimalsString); string memory isReturningString = s.split(delim).toString(); bool isReturning = convertStringToBool(isReturningString); string memory foreignEquivAddressString = s.toString(); address foreingEquivAddress = stringToAddress(foreignEquivAddressString); receiveAssets( sourceAssetAddress, uint32(chainEid), senderAddress, recipientAddress, amount, assetName, assetSymbol, uint8(decimals), isReturning, foreingEquivAddress ); } function receiveAssets( address _foreignAsset, uint32 _sourceChain, address _sourceAddress, address _recipientAddress, uint256 _amount, string memory _foreignAssetName, string memory _foreignAssetSymbol, uint8 _foreignAssetDecimals, bool _isReturningBridgedAsset, address _bridgedAssetAddressOnSource ) private { require(_sourceChain != thisChainEid); require(msg.sender != address(0)); address _theAssetWeAreWorkingOn; address _localEquivalent = lookupForeignTokenBridgedEquivalent(_foreignAsset, _sourceChain); if (_localEquivalent == address(0)) { if (_isReturningBridgedAsset) { MYIERC20Metadata _theCoin = MYIERC20Metadata(_bridgedAssetAddressOnSource); uint8 _decimals = _theCoin.decimals(); uint256 _minAmount = getMinAmount(_decimals); require(_amount >= _minAmount); bool success = _theCoin.transfer(_recipientAddress, _amount); require(success); transactionCount++; bridgeTransactions[transactionCount].asset = _bridgedAssetAddressOnSource; _theAssetWeAreWorkingOn = _bridgedAssetAddressOnSource; } else { address _newBridgedToken = _createNewLocalAssetForForeignAsset( _foreignAsset, _sourceChain, _foreignAssetName, _foreignAssetSymbol, _sourceAddress, _foreignAssetDecimals ); require(_newBridgedToken != address(0)); IBridgedOmniToken _theToken = IBridgedOmniToken(_newBridgedToken); _theToken.mint(_recipientAddress, _amount); transactionCount++; bridgeTransactions[transactionCount].asset = _newBridgedToken; _theAssetWeAreWorkingOn = _newBridgedToken; } amountReceivedAssets = safeAdd(amountReceivedAssets, _amount); numberReceivedTransactions++; } else { IBridgedOmniToken _theToken = IBridgedOmniToken(_localEquivalent); _theToken.mint(_recipientAddress, _amount); amountReceivedAssets = safeAdd(amountReceivedAssets, _amount); numberReceivedTransactions++; transactionCount++; bridgeTransactions[transactionCount].asset = _localEquivalent; _theAssetWeAreWorkingOn = _localEquivalent; } bridgeTransactions[transactionCount].amount = _amount; bridgeTransactions[transactionCount].sourceChain = _sourceChain; bridgeTransactions[transactionCount].destinationChain = thisChainEid; bridgeTransactions[transactionCount].sourceAddress = _sourceAddress; bridgeTransactions[transactionCount].destinationAddress = _recipientAddress; bridgeTransactions[transactionCount].date = block.timestamp; bridgeProfiles[_recipientAddress].transactionCount++; bridgeProfiles[_recipientAddress].transactions[bridgeProfiles[_recipientAddress].transactionCount] = transactionCount; uint256 thisAssetProfileCount = bridgeProfiles[_recipientAddress].receivedAssetToCount[_theAssetWeAreWorkingOn]; if (thisAssetProfileCount > 0) { bridgeProfiles[_recipientAddress].assetAmountReceived[thisAssetProfileCount].amountReceived = safeAdd(bridgeProfiles[_recipientAddress].assetAmountReceived[thisAssetProfileCount].amountReceived, _amount); } else { bridgeProfiles[_recipientAddress].receivedAssetCount++; uint256 receivedCount = bridgeProfiles[_recipientAddress].receivedAssetCount; bridgeProfiles[_recipientAddress].receivedAssetToCount[_theAssetWeAreWorkingOn] = receivedCount; bridgeProfiles[_recipientAddress].assetAmountReceived[receivedCount].asset = _theAssetWeAreWorkingOn; bridgeProfiles[_recipientAddress].assetAmountReceived[receivedCount].amountReceived = safeAdd(bridgeProfiles[_recipientAddress].assetAmountReceived[receivedCount].amountReceived, _amount); } emit AssetsReceived( transactionCount, _theAssetWeAreWorkingOn, _amount, _sourceChain, _sourceAddress, thisChainEid, _recipientAddress, block.number, block.timestamp ); } function lookupForeignTokenBridgedEquivalent(address _asset, uint32 _sourceChain) public view returns (address) { return foreignTokenBridgedEquivalent[_sourceChain][_asset]; } function lookupBridgedTokenForeignEquivalent(address _asset, uint32 _sourceChain) public view returns (address) { return bridgedTokenForeignEquivalent[_asset][_sourceChain]; } function _createNewLocalAssetForForeignAsset( address _foreignAsset, uint32 _sourceChain, string memory _foreignAssetName, string memory _foreignAssetSymbol, address _sourceAddress, uint8 _foreignAssetDecimals ) internal returns (address) { require(foreignTokenBridgedEquivalent[_sourceChain][_foreignAsset] == address(0)); address _omnifyAddress = address(this); string memory concatenatedName = string.concat("Omnify ", _foreignAssetName); string memory concatenatedSymbol = string.concat("OFY", _foreignAssetSymbol); address _newBridgedToken = address(new BridgedOmniToken(_omnifyAddress, concatenatedName, concatenatedSymbol, _foreignAssetDecimals)); foreignTokenBridgedEquivalent[_sourceChain][_foreignAsset] = _newBridgedToken; bridgedTokenForeignEquivalent[_newBridgedToken][_sourceChain] = _foreignAsset; emit NewBridgedTokenCreated(_sourceChain, thisChainEid, _sourceAddress, _newBridgedToken, concatenatedName, concatenatedSymbol, _foreignAsset, _foreignAssetName, _foreignAssetSymbol); return _newBridgedToken; } function changeOmnifyAddressOnBridgedCoin(address _bridgedCoinAddress, address _newAddress) external onlyOwner { IBridgedOmniToken _theBridgedToken = IBridgedOmniToken(_bridgedCoinAddress); _theBridgedToken.changeOmnifyAddress(_newAddress); } function safeAdd(uint256 _currentAmount, uint256 _amountToBeAdded) internal view returns (uint256){ uint256 _allowedAmount = MAXUINT - _currentAmount; if (_amountToBeAdded <= _allowedAmount) { return _currentAmount + _amountToBeAdded; } return _currentAmount; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; //import "../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; contract BridgedOmniToken is ERC20 { uint8 public tokenDecimals; address public omnifyAddress; constructor( address _omnifyAddress, string memory _tokenName, string memory _tokenSymbol, uint8 _tokenDecimals ) ERC20(_tokenName, _tokenSymbol) { omnifyAddress = _omnifyAddress; tokenDecimals = _tokenDecimals; } function changeOmnifyAddress(address newAddress) external{ require(msg.sender == omnifyAddress); require(omnifyAddress != newAddress); omnifyAddress = newAddress; } function decimals() public view override returns (uint8) { return tokenDecimals; } function burnSenderTokens(address _sender, uint _amount) external { require(msg.sender == omnifyAddress); _burn(_sender, _amount); } function mint(address _recipient, uint _amount) external { require(msg.sender == omnifyAddress); _mint(_recipient, _amount); } // function balanceOf(address account) public view override returns (uint256) { // return _balances[account]; // } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "./ierc20.sol"; interface MYIERC20Metadata is MYIERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; // @dev Import the 'MessagingFee' and 'MessagingReceipt' so it's exposed to OApp implementers // solhint-disable-next-line no-unused-import import { OAppSender, MessagingFee, MessagingReceipt } from "./OAppSender.sol"; // @dev Import the 'Origin' so it's exposed to OApp implementers // solhint-disable-next-line no-unused-import import { OAppReceiver, Origin } from "./OAppReceiver.sol"; import { OAppCore } from "./OAppCore.sol"; /** * @title OApp * @dev Abstract contract serving as the base for OApp implementation, combining OAppSender and OAppReceiver functionality. */ abstract contract OApp is OAppSender, OAppReceiver { /** * @dev Constructor to initialize the OApp with the provided endpoint and owner. * @param _endpoint The address of the LOCAL LayerZero endpoint. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. */ constructor(address _endpoint, address _delegate) OAppCore(_endpoint, _delegate) {} /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol implementation. * @return receiverVersion The version of the OAppReceiver.sol implementation. */ function oAppVersion() public pure virtual override(OAppSender, OAppReceiver) returns (uint64 senderVersion, uint64 receiverVersion) { return (SENDER_VERSION, RECEIVER_VERSION); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { IMessageLibManager } from "./IMessageLibManager.sol"; import { IMessagingComposer } from "./IMessagingComposer.sol"; import { IMessagingChannel } from "./IMessagingChannel.sol"; import { IMessagingContext } from "./IMessagingContext.sol"; struct MessagingParams { uint32 dstEid; bytes32 receiver; bytes message; bytes options; bool payInLzToken; } struct MessagingReceipt { bytes32 guid; uint64 nonce; MessagingFee fee; } struct MessagingFee { uint256 nativeFee; uint256 lzTokenFee; } struct Origin { uint32 srcEid; bytes32 sender; uint64 nonce; } interface ILayerZeroEndpointV2 is IMessageLibManager, IMessagingComposer, IMessagingChannel, IMessagingContext { event PacketSent(bytes encodedPayload, bytes options, address sendLibrary); event PacketVerified(Origin origin, address receiver, bytes32 payloadHash); event PacketDelivered(Origin origin, address receiver); event LzReceiveAlert( address indexed receiver, address indexed executor, Origin origin, bytes32 guid, uint256 gas, uint256 value, bytes message, bytes extraData, bytes reason ); event LzTokenSet(address token); event DelegateSet(address sender, address delegate); function quote(MessagingParams calldata _params, address _sender) external view returns (MessagingFee memory); function send( MessagingParams calldata _params, address _refundAddress ) external payable returns (MessagingReceipt memory); function verify(Origin calldata _origin, address _receiver, bytes32 _payloadHash) external; function verifiable(Origin calldata _origin, address _receiver) external view returns (bool); function initializable(Origin calldata _origin, address _receiver) external view returns (bool); function lzReceive( Origin calldata _origin, address _receiver, bytes32 _guid, bytes calldata _message, bytes calldata _extraData ) external payable; // oapp can burn messages partially by calling this function with its own business logic if messages are verified in order function clear(address _oapp, Origin calldata _origin, bytes32 _guid, bytes calldata _message) external; function setLzToken(address _lzToken) external; function lzToken() external view returns (address); function nativeToken() external view returns (address); function setDelegate(address _delegate) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { BytesLib } from "solidity-bytes-utils/contracts/BytesLib.sol"; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import { ExecutorOptions } from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/ExecutorOptions.sol"; import { DVNOptions } from "@layerzerolabs/lz-evm-messagelib-v2/contracts/uln/libs/DVNOptions.sol"; import "../../../../messagelib/contracts/uln/libs/DVNOptions.sol"; import "../../../../protocol/contracts/messagelib/libs/ExecutorOptions.sol"; import "../../../../../../../../openzeppelin-contracts/contracts/utils/math/SafeCast.sol"; import "../../../../../../../../solidity-bytes-utils/contracts/BytesLib.sol"; /** * @title OptionsBuilder * @dev Library for building and encoding various message options. */ library OptionsBuilder { using SafeCast for uint256; using BytesLib for bytes; // Constants for options types uint16 internal constant TYPE_1 = 1; // legacy options type 1 uint16 internal constant TYPE_2 = 2; // legacy options type 2 uint16 internal constant TYPE_3 = 3; // Custom error message error InvalidSize(uint256 max, uint256 actual); error InvalidOptionType(uint16 optionType); // Modifier to ensure only options of type 3 are used modifier onlyType3(bytes memory _options) { if (_options.toUint16(0) != TYPE_3) revert InvalidOptionType(_options.toUint16(0)); _; } /** * @dev Creates a new options container with type 3. * @return options The newly created options container. */ function newOptions() internal pure returns (bytes memory) { return abi.encodePacked(TYPE_3); } /** * @dev Adds an executor LZ receive option to the existing options. * @param _options The existing options container. * @param _gas The gasLimit used on the lzReceive() function in the OApp. * @param _value The msg.value passed to the lzReceive() function in the OApp. * @return options The updated options container. * * @dev When multiples of this option are added, they are summed by the executor * eg. if (_gas: 200k, and _value: 1 ether) AND (_gas: 100k, _value: 0.5 ether) are sent in an option to the LayerZeroEndpoint, * that becomes (300k, 1.5 ether) when the message is executed on the remote lzReceive() function. */ function addExecutorLzReceiveOption( bytes memory _options, uint128 _gas, uint128 _value ) internal pure onlyType3(_options) returns (bytes memory) { bytes memory option = ExecutorOptions.encodeLzReceiveOption(_gas, _value); return addExecutorOption(_options, ExecutorOptions.OPTION_TYPE_LZRECEIVE, option); } /** * @dev Adds an executor native drop option to the existing options. * @param _options The existing options container. * @param _amount The amount for the native value that is airdropped to the 'receiver'. * @param _receiver The receiver address for the native drop option. * @return options The updated options container. * * @dev When multiples of this option are added, they are summed by the executor on the remote chain. */ function addExecutorNativeDropOption( bytes memory _options, uint128 _amount, bytes32 _receiver ) internal pure onlyType3(_options) returns (bytes memory) { bytes memory option = ExecutorOptions.encodeNativeDropOption(_amount, _receiver); return addExecutorOption(_options, ExecutorOptions.OPTION_TYPE_NATIVE_DROP, option); } /** * @dev Adds an executor LZ compose option to the existing options. * @param _options The existing options container. * @param _index The index for the lzCompose() function call. * @param _gas The gasLimit for the lzCompose() function call. * @param _value The msg.value for the lzCompose() function call. * @return options The updated options container. * * @dev When multiples of this option are added, they are summed PER index by the executor on the remote chain. * @dev If the OApp sends N lzCompose calls on the remote, you must provide N incremented indexes starting with 0. * ie. When your remote OApp composes (N = 3) messages, you must set this option for index 0,1,2 */ function addExecutorLzComposeOption( bytes memory _options, uint16 _index, uint128 _gas, uint128 _value ) internal pure onlyType3(_options) returns (bytes memory) { bytes memory option = ExecutorOptions.encodeLzComposeOption(_index, _gas, _value); return addExecutorOption(_options, ExecutorOptions.OPTION_TYPE_LZCOMPOSE, option); } /** * @dev Adds an executor ordered execution option to the existing options. * @param _options The existing options container. * @return options The updated options container. */ function addExecutorOrderedExecutionOption( bytes memory _options ) internal pure onlyType3(_options) returns (bytes memory) { return addExecutorOption(_options, ExecutorOptions.OPTION_TYPE_ORDERED_EXECUTION, bytes("")); } /** * @dev Adds a DVN pre-crime option to the existing options. * @param _options The existing options container. * @param _dvnIdx The DVN index for the pre-crime option. * @return options The updated options container. */ function addDVNPreCrimeOption( bytes memory _options, uint8 _dvnIdx ) internal pure onlyType3(_options) returns (bytes memory) { return addDVNOption(_options, _dvnIdx, DVNOptions.OPTION_TYPE_PRECRIME, bytes("")); } /** * @dev Adds an executor option to the existing options. * @param _options The existing options container. * @param _optionType The type of the executor option. * @param _option The encoded data for the executor option. * @return options The updated options container. */ function addExecutorOption( bytes memory _options, uint8 _optionType, bytes memory _option ) internal pure onlyType3(_options) returns (bytes memory) { return abi.encodePacked( _options, ExecutorOptions.WORKER_ID, _option.length.toUint16() + 1, // +1 for optionType _optionType, _option ); } /** * @dev Adds a DVN option to the existing options. * @param _options The existing options container. * @param _dvnIdx The DVN index for the DVN option. * @param _optionType The type of the DVN option. * @param _option The encoded data for the DVN option. * @return options The updated options container. */ function addDVNOption( bytes memory _options, uint8 _dvnIdx, uint8 _optionType, bytes memory _option ) internal pure onlyType3(_options) returns (bytes memory) { return abi.encodePacked( _options, DVNOptions.WORKER_ID, _option.length.toUint16() + 2, // +2 for optionType and dvnIdx _dvnIdx, _optionType, _option ); } /** * @dev Encodes legacy options of type 1. * @param _executionGas The gasLimit value passed to lzReceive(). * @return legacyOptions The encoded legacy options. */ function encodeLegacyOptionsType1(uint256 _executionGas) internal pure returns (bytes memory) { if (_executionGas > type(uint128).max) revert InvalidSize(type(uint128).max, _executionGas); return abi.encodePacked(TYPE_1, _executionGas); } /** * @dev Encodes legacy options of type 2. * @param _executionGas The gasLimit value passed to lzReceive(). * @param _nativeForDst The amount of native air dropped to the receiver. * @param _receiver The _nativeForDst receiver address. * @return legacyOptions The encoded legacy options of type 2. */ function encodeLegacyOptionsType2( uint256 _executionGas, uint256 _nativeForDst, bytes memory _receiver // @dev Use bytes instead of bytes32 in legacy type 2 for _receiver. ) internal pure returns (bytes memory) { if (_executionGas > type(uint128).max) revert InvalidSize(type(uint128).max, _executionGas); if (_nativeForDst > type(uint128).max) revert InvalidSize(type(uint128).max, _nativeForDst); if (_receiver.length > 32) revert InvalidSize(32, _receiver.length); return abi.encodePacked(TYPE_2, _executionGas, _nativeForDst, _receiver); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
/* * @title String & slice utility library for Solidity contracts. * @author Nick Johnson <[email protected]> * * @dev Functionality in this library is largely implemented using an * abstraction called a 'slice'. A slice represents a part of a string - * anything from the entire string to a single character, or even no * characters at all (a 0-length slice). Since a slice only has to specify * an offset and a length, copying and manipulating slices is a lot less * expensive than copying and manipulating the strings they reference. * * To further reduce gas costs, most functions on slice that need to return * a slice modify the original one instead of allocating a new one; for * instance, `s.split(".")` will return the text up to the first '.', * modifying s to only contain the remainder of the string after the '.'. * In situations where you do not want to modify the original slice, you * can make a copy first with `.copy()`, for example: * `s.copy().split(".")`. Try and avoid using this idiom in loops; since * Solidity has no memory management, it will result in allocating many * short-lived slices that are later discarded. * * Functions that return two slices come in two versions: a non-allocating * version that takes the second slice as an argument, modifying it in * place, and an allocating version that allocates and returns the second * slice; see `nextRune` for example. * * Functions that have to copy string data will return strings rather than * slices; these can be cast back to slices for further processing if * required. * * For convenience, some functions are provided with non-modifying * variants that create a new slice and return both; for instance, * `s.splitNew('.')` leaves s unmodified, and returns two values * corresponding to the left and right parts of the string. */ pragma solidity ^0.8.0; library strings { struct slice { uint _len; uint _ptr; } function memcpy(uint dest, uint src, uint length) private pure { // Copy word-length chunks while possible for(; length >= 32; length -= 32) { assembly { mstore(dest, mload(src)) } dest += 32; src += 32; } // Copy remaining bytes uint mask = type(uint).max; if (length > 0) { mask = 256 ** (32 - length) - 1; } assembly { let srcpart := and(mload(src), not(mask)) let destpart := and(mload(dest), mask) mstore(dest, or(destpart, srcpart)) } } /* * @dev Returns a slice containing the entire string. * @param self The string to make a slice from. * @return A newly allocated slice containing the entire string. */ function toSlice(string memory self) internal pure returns (slice memory) { uint ptr; assembly { ptr := add(self, 0x20) } return slice(bytes(self).length, ptr); } /* * @dev Returns the length of a null-terminated bytes32 string. * @param self The value to find the length of. * @return The length of the string, from 0 to 32. */ function len(bytes32 self) internal pure returns (uint) { uint ret; if (self == 0) return 0; if (uint(self) & type(uint128).max == 0) { ret += 16; self = bytes32(uint(self) / 0x100000000000000000000000000000000); } if (uint(self) & type(uint64).max == 0) { ret += 8; self = bytes32(uint(self) / 0x10000000000000000); } if (uint(self) & type(uint32).max == 0) { ret += 4; self = bytes32(uint(self) / 0x100000000); } if (uint(self) & type(uint16).max == 0) { ret += 2; self = bytes32(uint(self) / 0x10000); } if (uint(self) & type(uint8).max == 0) { ret += 1; } return 32 - ret; } /* * @dev Returns a slice containing the entire bytes32, interpreted as a * null-terminated utf-8 string. * @param self The bytes32 value to convert to a slice. * @return A new slice containing the value of the input argument up to the * first null. */ function toSliceB32(bytes32 self) internal pure returns (slice memory ret) { // Allocate space for `self` in memory, copy it there, and point ret at it assembly { let ptr := mload(0x40) mstore(0x40, add(ptr, 0x20)) mstore(ptr, self) mstore(add(ret, 0x20), ptr) } ret._len = len(self); } /* * @dev Returns a new slice containing the same data as the current slice. * @param self The slice to copy. * @return A new slice containing the same data as `self`. */ function copy(slice memory self) internal pure returns (slice memory) { return slice(self._len, self._ptr); } /* * @dev Copies a slice to a new string. * @param self The slice to copy. * @return A newly allocated string containing the slice's text. */ function toString(slice memory self) internal pure returns (string memory) { string memory ret = new string(self._len); uint retptr; assembly { retptr := add(ret, 32) } memcpy(retptr, self._ptr, self._len); return ret; } /* * @dev Returns the length in runes of the slice. Note that this operation * takes time proportional to the length of the slice; avoid using it * in loops, and call `slice.empty()` if you only need to know whether * the slice is empty or not. * @param self The slice to operate on. * @return The length of the slice in runes. */ function len(slice memory self) internal pure returns (uint l) { // Starting at ptr-31 means the LSB will be the byte we care about uint ptr = self._ptr - 31; uint end = ptr + self._len; for (l = 0; ptr < end; l++) { uint8 b; assembly { b := and(mload(ptr), 0xFF) } if (b < 0x80) { ptr += 1; } else if(b < 0xE0) { ptr += 2; } else if(b < 0xF0) { ptr += 3; } else if(b < 0xF8) { ptr += 4; } else if(b < 0xFC) { ptr += 5; } else { ptr += 6; } } } /* * @dev Returns true if the slice is empty (has a length of 0). * @param self The slice to operate on. * @return True if the slice is empty, False otherwise. */ function empty(slice memory self) internal pure returns (bool) { return self._len == 0; } /* * @dev Returns a positive number if `other` comes lexicographically after * `self`, a negative number if it comes before, or zero if the * contents of the two slices are equal. Comparison is done per-rune, * on unicode codepoints. * @param self The first slice to compare. * @param other The second slice to compare. * @return The result of the comparison. */ function compare(slice memory self, slice memory other) internal pure returns (int) { uint shortest = self._len; if (other._len < self._len) shortest = other._len; uint selfptr = self._ptr; uint otherptr = other._ptr; for (uint idx = 0; idx < shortest; idx += 32) { uint a; uint b; assembly { a := mload(selfptr) b := mload(otherptr) } if (a != b) { // Mask out irrelevant bytes and check again uint mask = type(uint).max; // 0xffff... if(shortest < 32) { mask = ~(2 ** (8 * (32 - shortest + idx)) - 1); } unchecked { uint diff = (a & mask) - (b & mask); if (diff != 0) return int(diff); } } selfptr += 32; otherptr += 32; } return int(self._len) - int(other._len); } /* * @dev Returns true if the two slices contain the same text. * @param self The first slice to compare. * @param self The second slice to compare. * @return True if the slices are equal, false otherwise. */ function equals(slice memory self, slice memory other) internal pure returns (bool) { return compare(self, other) == 0; } /* * @dev Extracts the first rune in the slice into `rune`, advancing the * slice to point to the next rune and returning `self`. * @param self The slice to operate on. * @param rune The slice that will contain the first rune. * @return `rune`. */ function nextRune(slice memory self, slice memory rune) internal pure returns (slice memory) { rune._ptr = self._ptr; if (self._len == 0) { rune._len = 0; return rune; } uint l; uint b; // Load the first byte of the rune into the LSBs of b assembly { b := and(mload(sub(mload(add(self, 32)), 31)), 0xFF) } if (b < 0x80) { l = 1; } else if(b < 0xE0) { l = 2; } else if(b < 0xF0) { l = 3; } else { l = 4; } // Check for truncated codepoints if (l > self._len) { rune._len = self._len; self._ptr += self._len; self._len = 0; return rune; } self._ptr += l; self._len -= l; rune._len = l; return rune; } /* * @dev Returns the first rune in the slice, advancing the slice to point * to the next rune. * @param self The slice to operate on. * @return A slice containing only the first rune from `self`. */ function nextRune(slice memory self) internal pure returns (slice memory ret) { nextRune(self, ret); } /* * @dev Returns the number of the first codepoint in the slice. * @param self The slice to operate on. * @return The number of the first codepoint in the slice. */ function ord(slice memory self) internal pure returns (uint ret) { if (self._len == 0) { return 0; } uint word; uint length; uint divisor = 2 ** 248; // Load the rune into the MSBs of b assembly { word:= mload(mload(add(self, 32))) } uint b = word / divisor; if (b < 0x80) { ret = b; length = 1; } else if(b < 0xE0) { ret = b & 0x1F; length = 2; } else if(b < 0xF0) { ret = b & 0x0F; length = 3; } else { ret = b & 0x07; length = 4; } // Check for truncated codepoints if (length > self._len) { return 0; } for (uint i = 1; i < length; i++) { divisor = divisor / 256; b = (word / divisor) & 0xFF; if (b & 0xC0 != 0x80) { // Invalid UTF-8 sequence return 0; } ret = (ret * 64) | (b & 0x3F); } return ret; } /* * @dev Returns the keccak-256 hash of the slice. * @param self The slice to hash. * @return The hash of the slice. */ function keccak(slice memory self) internal pure returns (bytes32 ret) { assembly { ret := keccak256(mload(add(self, 32)), mload(self)) } } /* * @dev Returns true if `self` starts with `needle`. * @param self The slice to operate on. * @param needle The slice to search for. * @return True if the slice starts with the provided text, false otherwise. */ function startsWith(slice memory self, slice memory needle) internal pure returns (bool) { if (self._len < needle._len) { return false; } if (self._ptr == needle._ptr) { return true; } bool equal; assembly { let length := mload(needle) let selfptr := mload(add(self, 0x20)) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } return equal; } /* * @dev If `self` starts with `needle`, `needle` is removed from the * beginning of `self`. Otherwise, `self` is unmodified. * @param self The slice to operate on. * @param needle The slice to search for. * @return `self` */ function beyond(slice memory self, slice memory needle) internal pure returns (slice memory) { if (self._len < needle._len) { return self; } bool equal = true; if (self._ptr != needle._ptr) { assembly { let length := mload(needle) let selfptr := mload(add(self, 0x20)) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } } if (equal) { self._len -= needle._len; self._ptr += needle._len; } return self; } /* * @dev Returns true if the slice ends with `needle`. * @param self The slice to operate on. * @param needle The slice to search for. * @return True if the slice starts with the provided text, false otherwise. */ function endsWith(slice memory self, slice memory needle) internal pure returns (bool) { if (self._len < needle._len) { return false; } uint selfptr = self._ptr + self._len - needle._len; if (selfptr == needle._ptr) { return true; } bool equal; assembly { let length := mload(needle) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } return equal; } /* * @dev If `self` ends with `needle`, `needle` is removed from the * end of `self`. Otherwise, `self` is unmodified. * @param self The slice to operate on. * @param needle The slice to search for. * @return `self` */ function until(slice memory self, slice memory needle) internal pure returns (slice memory) { if (self._len < needle._len) { return self; } uint selfptr = self._ptr + self._len - needle._len; bool equal = true; if (selfptr != needle._ptr) { assembly { let length := mload(needle) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } } if (equal) { self._len -= needle._len; } return self; } // Returns the memory address of the first byte of the first occurrence of // `needle` in `self`, or the first byte after `self` if not found. function findPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) { uint ptr = selfptr; uint idx; if (needlelen <= selflen) { if (needlelen <= 32) { bytes32 mask; if (needlelen > 0) { mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1)); } bytes32 needledata; assembly { needledata := and(mload(needleptr), mask) } uint end = selfptr + selflen - needlelen; bytes32 ptrdata; assembly { ptrdata := and(mload(ptr), mask) } while (ptrdata != needledata) { if (ptr >= end) return selfptr + selflen; ptr++; assembly { ptrdata := and(mload(ptr), mask) } } return ptr; } else { // For long needles, use hashing bytes32 hash; assembly { hash := keccak256(needleptr, needlelen) } for (idx = 0; idx <= selflen - needlelen; idx++) { bytes32 testHash; assembly { testHash := keccak256(ptr, needlelen) } if (hash == testHash) return ptr; ptr += 1; } } } return selfptr + selflen; } // Returns the memory address of the first byte after the last occurrence of // `needle` in `self`, or the address of `self` if not found. function rfindPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) { uint ptr; if (needlelen <= selflen) { if (needlelen <= 32) { bytes32 mask; if (needlelen > 0) { mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1)); } bytes32 needledata; assembly { needledata := and(mload(needleptr), mask) } ptr = selfptr + selflen - needlelen; bytes32 ptrdata; assembly { ptrdata := and(mload(ptr), mask) } while (ptrdata != needledata) { if (ptr <= selfptr) return selfptr; ptr--; assembly { ptrdata := and(mload(ptr), mask) } } return ptr + needlelen; } else { // For long needles, use hashing bytes32 hash; assembly { hash := keccak256(needleptr, needlelen) } ptr = selfptr + (selflen - needlelen); while (ptr >= selfptr) { bytes32 testHash; assembly { testHash := keccak256(ptr, needlelen) } if (hash == testHash) return ptr + needlelen; ptr -= 1; } } } return selfptr; } /* * @dev Modifies `self` to contain everything from the first occurrence of * `needle` to the end of the slice. `self` is set to the empty slice * if `needle` is not found. * @param self The slice to search and modify. * @param needle The text to search for. * @return `self`. */ function find(slice memory self, slice memory needle) internal pure returns (slice memory) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); self._len -= ptr - self._ptr; self._ptr = ptr; return self; } /* * @dev Modifies `self` to contain the part of the string from the start of * `self` to the end of the first occurrence of `needle`. If `needle` * is not found, `self` is set to the empty slice. * @param self The slice to search and modify. * @param needle The text to search for. * @return `self`. */ function rfind(slice memory self, slice memory needle) internal pure returns (slice memory) { uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); self._len = ptr - self._ptr; return self; } /* * @dev Splits the slice, setting `self` to everything after the first * occurrence of `needle`, and `token` to everything before it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and `token` is set to the entirety of `self`. * @param self The slice to split. * @param needle The text to search for in `self`. * @param token An output parameter to which the first token is written. * @return `token`. */ function split(slice memory self, slice memory needle, slice memory token) internal pure returns (slice memory) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); token._ptr = self._ptr; token._len = ptr - self._ptr; if (ptr == self._ptr + self._len) { // Not found self._len = 0; } else { self._len -= token._len + needle._len; self._ptr = ptr + needle._len; } return token; } /* * @dev Splits the slice, setting `self` to everything after the first * occurrence of `needle`, and returning everything before it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and the entirety of `self` is returned. * @param self The slice to split. * @param needle The text to search for in `self`. * @return The part of `self` up to the first occurrence of `delim`. */ function split(slice memory self, slice memory needle) internal pure returns (slice memory token) { split(self, needle, token); } /* * @dev Splits the slice, setting `self` to everything before the last * occurrence of `needle`, and `token` to everything after it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and `token` is set to the entirety of `self`. * @param self The slice to split. * @param needle The text to search for in `self`. * @param token An output parameter to which the first token is written. * @return `token`. */ function rsplit(slice memory self, slice memory needle, slice memory token) internal pure returns (slice memory) { uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); token._ptr = ptr; token._len = self._len - (ptr - self._ptr); if (ptr == self._ptr) { // Not found self._len = 0; } else { self._len -= token._len + needle._len; } return token; } /* * @dev Splits the slice, setting `self` to everything before the last * occurrence of `needle`, and returning everything after it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and the entirety of `self` is returned. * @param self The slice to split. * @param needle The text to search for in `self`. * @return The part of `self` after the last occurrence of `delim`. */ function rsplit(slice memory self, slice memory needle) internal pure returns (slice memory token) { rsplit(self, needle, token); } /* * @dev Counts the number of nonoverlapping occurrences of `needle` in `self`. * @param self The slice to search. * @param needle The text to search for in `self`. * @return The number of occurrences of `needle` found in `self`. */ function count(slice memory self, slice memory needle) internal pure returns (uint cnt) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr) + needle._len; while (ptr <= self._ptr + self._len) { cnt++; ptr = findPtr(self._len - (ptr - self._ptr), ptr, needle._len, needle._ptr) + needle._len; } } /* * @dev Returns True if `self` contains `needle`. * @param self The slice to search. * @param needle The text to search for in `self`. * @return True if `needle` is found in `self`, false otherwise. */ function contains(slice memory self, slice memory needle) internal pure returns (bool) { return rfindPtr(self._len, self._ptr, needle._len, needle._ptr) != self._ptr; } /* * @dev Returns a newly allocated string containing the concatenation of * `self` and `other`. * @param self The first slice to concatenate. * @param other The second slice to concatenate. * @return The concatenation of the two strings. */ function concat(slice memory self, slice memory other) internal pure returns (string memory) { string memory ret = new string(self._len + other._len); uint retptr; assembly { retptr := add(ret, 32) } memcpy(retptr, self._ptr, self._len); memcpy(retptr + self._len, other._ptr, other._len); return ret; } /* * @dev Joins an array of slices, using `self` as a delimiter, returning a * newly allocated string. * @param self The delimiter to use. * @param parts A list of slices to join. * @return A newly allocated string containing all the slices in `parts`, * joined with `self`. */ function join(slice memory self, slice[] memory parts) internal pure returns (string memory) { if (parts.length == 0) return ""; uint length = self._len * (parts.length - 1); for(uint i = 0; i < parts.length; i++) length += parts[i]._len; string memory ret = new string(length); uint retptr; assembly { retptr := add(ret, 32) } for(uint i = 0; i < parts.length; i++) { memcpy(retptr, parts[i]._ptr, parts[i]._len); retptr += parts[i]._len; if (i < parts.length - 1) { memcpy(retptr, self._ptr, self._len); retptr += self._len; } } return ret; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; interface IOmnify { function addProfitsFromExternalContract() external payable; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; abstract contract MyContext { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } } /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is MyContext { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC20Metadata} from "./extensions/IERC20Metadata.sol"; import {Context} from "../../utils/Context.sol"; import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. */ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply += value; } else { uint256 fromBalance = _balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. _totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. _balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * ``` * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner` s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ interface MYIERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; //import { MessagingParams, MessagingFee, MessagingReceipt } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; import {OAppCore} from "./OAppCore.sol"; import "../../../../../../../openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import "../../../protocol/contracts/interfaces/ILayerZeroEndpointV2.sol"; /** * @title OAppSender * @dev Abstract contract implementing the OAppSender functionality for sending messages to a LayerZero endpoint. */ abstract contract OAppSender is OAppCore { using SafeERC20 for IERC20; // Custom error messages error NotEnoughNative(uint256 msgValue); error LzTokenUnavailable(); // @dev The version of the OAppSender implementation. // @dev Version is bumped when changes are made to this contract. uint64 internal constant SENDER_VERSION = 1; /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol contract. * @return receiverVersion The version of the OAppReceiver.sol contract. * * @dev Providing 0 as the default for OAppReceiver version. Indicates that the OAppReceiver is not implemented. * ie. this is a SEND only OApp. * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions */ function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) { return (SENDER_VERSION, 0); } /** * @dev Internal function to interact with the LayerZero EndpointV2.quote() for fee calculation. * @param _dstEid The destination endpoint ID. * @param _message The message payload. * @param _options Additional options for the message. * @param _payInLzToken Flag indicating whether to pay the fee in LZ tokens. * @return fee The calculated MessagingFee for the message. * - nativeFee: The native fee for the message. * - lzTokenFee: The LZ token fee for the message. */ function _quote( uint32 _dstEid, bytes memory _message, bytes memory _options, bool _payInLzToken ) internal view virtual returns (MessagingFee memory fee) { return endpoint.quote( MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _payInLzToken), address(this) ); } /** * @dev Internal function to interact with the LayerZero EndpointV2.send() for sending a message. * @param _dstEid The destination endpoint ID. * @param _message The message payload. * @param _options Additional options for the message. * @param _fee The calculated LayerZero fee for the message. * - nativeFee: The native fee. * - lzTokenFee: The lzToken fee. * @param _refundAddress The address to receive any excess fee values sent to the endpoint. * @return receipt The receipt for the sent message. * - guid: The unique identifier for the sent message. * - nonce: The nonce of the sent message. * - fee: The LayerZero fee incurred for the message. */ function _lzSend( uint32 _dstEid, bytes memory _message, bytes memory _options, MessagingFee memory _fee, address _refundAddress ) internal virtual returns (MessagingReceipt memory receipt) { // @dev Push corresponding fees to the endpoint, any excess is sent back to the _refundAddress from the endpoint. uint256 messageValue = _payNative(_fee.nativeFee); if (_fee.lzTokenFee > 0) _payLzToken(_fee.lzTokenFee); return // solhint-disable-next-line check-send-result endpoint.send{value: messageValue}( MessagingParams(_dstEid, _getPeerOrRevert(_dstEid), _message, _options, _fee.lzTokenFee > 0), _refundAddress ); } /** * @dev Internal function to pay the native fee associated with the message. * @param _nativeFee The native fee to be paid. * @return nativeFee The amount of native currency paid. * * @dev If the OApp needs to initiate MULTIPLE LayerZero messages in a single transaction, * this will need to be overridden because msg.value would contain multiple lzFees. * @dev Should be overridden in the event the LayerZero endpoint requires a different native currency. * @dev Some EVMs use an ERC20 as a method for paying transactions/gasFees. * @dev The endpoint is EITHER/OR, ie. it will NOT support both types of native payment at a time. */ function _payNative(uint256 _nativeFee) internal virtual returns (uint256 nativeFee) { if (msg.value < _nativeFee) revert NotEnoughNative(msg.value); return _nativeFee; } /** * @dev Internal function to pay the LZ token fee associated with the message. * @param _lzTokenFee The LZ token fee to be paid. * * @dev If the caller is trying to pay in the specified lzToken, then the lzTokenFee is passed to the endpoint. * @dev Any excess sent, is passed back to the specified _refundAddress in the _lzSend(). */ function _payLzToken(uint256 _lzTokenFee) internal virtual { // @dev Cannot cache the token because it is not immutable in the endpoint. address lzToken = endpoint.lzToken(); if (lzToken == address(0)) revert LzTokenUnavailable(); // Pay LZ token fee by sending tokens to the endpoint. IERC20(lzToken).safeTransferFrom(msg.sender, address(endpoint), _lzTokenFee); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import { IOAppReceiver, Origin } from "./interfaces/IOAppReceiver.sol"; import { OAppCore } from "./OAppCore.sol"; /** * @title OAppReceiver * @dev Abstract contract implementing the ILayerZeroReceiver interface and extending OAppCore for OApp receivers. */ abstract contract OAppReceiver is IOAppReceiver, OAppCore { // Custom error message for when the caller is not the registered endpoint/ error OnlyEndpoint(address addr); // @dev The version of the OAppReceiver implementation. // @dev Version is bumped when changes are made to this contract. uint64 internal constant RECEIVER_VERSION = 1; /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol contract. * @return receiverVersion The version of the OAppReceiver.sol contract. * * @dev Providing 0 as the default for OAppSender version. Indicates that the OAppSender is not implemented. * ie. this is a RECEIVE only OApp. * @dev If the OApp uses both OAppSender and OAppReceiver, then this needs to be override returning the correct versions. */ function oAppVersion() public view virtual returns (uint64 senderVersion, uint64 receiverVersion) { return (0, RECEIVER_VERSION); } /** * @notice Retrieves the address responsible for 'sending' composeMsg's to the Endpoint. * @return sender The address responsible for 'sending' composeMsg's to the Endpoint. * * @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer. * @dev The default sender IS the OApp implementer. */ function composeMsgSender() public view virtual returns (address sender) { return address(this); } /** * @notice Checks if the path initialization is allowed based on the provided origin. * @param origin The origin information containing the source endpoint and sender address. * @return Whether the path has been initialized. * * @dev This indicates to the endpoint that the OApp has enabled msgs for this particular path to be received. * @dev This defaults to assuming if a peer has been set, its initialized. * Can be overridden by the OApp if there is other logic to determine this. */ function allowInitializePath(Origin calldata origin) public view virtual returns (bool) { return peers[origin.srcEid] == origin.sender; } /** * @notice Retrieves the next nonce for a given source endpoint and sender address. * @dev _srcEid The source endpoint ID. * @dev _sender The sender address. * @return nonce The next nonce. * * @dev The path nonce starts from 1. If 0 is returned it means that there is NO nonce ordered enforcement. * @dev Is required by the off-chain executor to determine the OApp expects msg execution is ordered. * @dev This is also enforced by the OApp. * @dev By default this is NOT enabled. ie. nextNonce is hardcoded to return 0. */ function nextNonce(uint32 /*_srcEid*/, bytes32 /*_sender*/) public view virtual returns (uint64 nonce) { return 0; } /** * @dev Entry point for receiving messages or packets from the endpoint. * @param _origin The origin information containing the source endpoint and sender address. * - srcEid: The source chain endpoint ID. * - sender: The sender address on the src chain. * - nonce: The nonce of the message. * @param _guid The unique identifier for the received LayerZero message. * @param _message The payload of the received message. * @param _executor The address of the executor for the received message. * @param _extraData Additional arbitrary data provided by the corresponding executor. * * @dev Entry point for receiving msg/packet from the LayerZero endpoint. */ function lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) public payable virtual { // Ensures that only the endpoint can attempt to lzReceive() messages to this OApp. if (address(endpoint) != msg.sender) revert OnlyEndpoint(msg.sender); // Ensure that the sender matches the expected peer for the source endpoint. if (_getPeerOrRevert(_origin.srcEid) != _origin.sender) revert OnlyPeer(_origin.srcEid, _origin.sender); // Call the internal OApp implementation of lzReceive. _lzReceive(_origin, _guid, _message, _executor, _extraData); } /** * @dev Internal function to implement lzReceive logic without needing to copy the basic parameter validation. */ function _lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) internal virtual; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; //import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import {IOAppCore, ILayerZeroEndpointV2} from "./interfaces/IOAppCore.sol"; /** * @title OAppCore * @dev Abstract contract implementing the IOAppCore interface with basic OApp configurations. */ abstract contract OAppCore is IOAppCore { // The LayerZero endpoint associated with the given OApp ILayerZeroEndpointV2 public immutable endpoint; // Mapping to store peers associated with corresponding endpoints mapping(uint32 eid => bytes32 peer) public peers; /** * @dev Constructor to initialize the OAppCore with the provided endpoint and delegate. * @param _endpoint The address of the LOCAL Layer Zero endpoint. * @param _delegate The delegate capable of making OApp configurations inside of the endpoint. * * @dev The delegate typically should be set as the owner of the contract. */ constructor(address _endpoint, address _delegate) { endpoint = ILayerZeroEndpointV2(_endpoint); if (_delegate == address(0)) revert InvalidDelegate(); endpoint.setDelegate(_delegate); } /** * @notice Sets the peer address (OApp instance) for a corresponding endpoint. * @param _eid The endpoint ID. * @param _peer The address of the peer to be associated with the corresponding endpoint. * * @dev Only the owner/admin of the OApp can call this function. * @dev Indicates that the peer is trusted to send LayerZero messages to this OApp. * @dev Set this to bytes32(0) to remove the peer address. * @dev Peer is a bytes32 to accommodate non-evm chains. */ function setPeer(uint32 _eid, bytes32 _peer) internal { peers[_eid] = _peer; emit PeerSet(_eid, _peer); } /** * @notice Internal function to get the peer address associated with a specific endpoint; reverts if NOT set. * ie. the peer is set to bytes32(0). * @param _eid The endpoint ID. * @return peer The address of the peer associated with the specified endpoint. */ function _getPeerOrRevert(uint32 _eid) internal view virtual returns (bytes32) { bytes32 peer = peers[_eid]; if (peer == bytes32(0)) revert NoPeer(_eid); return peer; } /** * @notice Sets the delegate address for the OApp. * @param _delegate The address of the delegate to be set. * * @dev Only the owner/admin of the OApp can call this function. * @dev Provides the ability for a delegate to set configs, on behalf of the OApp, directly on the Endpoint contract. */ function setDelegate(address _delegate) internal { endpoint.setDelegate(_delegate); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; struct SetConfigParam { uint32 eid; uint32 configType; bytes config; } interface IMessageLibManager { struct Timeout { address lib; uint256 expiry; } event LibraryRegistered(address newLib); event DefaultSendLibrarySet(uint32 eid, address newLib); event DefaultReceiveLibrarySet(uint32 eid, address newLib); event DefaultReceiveLibraryTimeoutSet(uint32 eid, address oldLib, uint256 expiry); event SendLibrarySet(address sender, uint32 eid, address newLib); event ReceiveLibrarySet(address receiver, uint32 eid, address newLib); event ReceiveLibraryTimeoutSet(address receiver, uint32 eid, address oldLib, uint256 timeout); function registerLibrary(address _lib) external; function isRegisteredLibrary(address _lib) external view returns (bool); function getRegisteredLibraries() external view returns (address[] memory); function setDefaultSendLibrary(uint32 _eid, address _newLib) external; function defaultSendLibrary(uint32 _eid) external view returns (address); function setDefaultReceiveLibrary(uint32 _eid, address _newLib, uint256 _timeout) external; function defaultReceiveLibrary(uint32 _eid) external view returns (address); function setDefaultReceiveLibraryTimeout(uint32 _eid, address _lib, uint256 _expiry) external; function defaultReceiveLibraryTimeout(uint32 _eid) external view returns (address lib, uint256 expiry); function isSupportedEid(uint32 _eid) external view returns (bool); function isValidReceiveLibrary(address _receiver, uint32 _eid, address _lib) external view returns (bool); /// ------------------- OApp interfaces ------------------- function setSendLibrary(address _oapp, uint32 _eid, address _newLib) external; function getSendLibrary(address _sender, uint32 _eid) external view returns (address lib); function isDefaultSendLibrary(address _sender, uint32 _eid) external view returns (bool); function setReceiveLibrary(address _oapp, uint32 _eid, address _newLib, uint256 _gracePeriod) external; function getReceiveLibrary(address _receiver, uint32 _eid) external view returns (address lib, bool isDefault); function setReceiveLibraryTimeout(address _oapp, uint32 _eid, address _lib, uint256 _gracePeriod) external; function receiveLibraryTimeout(address _receiver, uint32 _eid) external view returns (address lib, uint256 expiry); function setConfig(address _oapp, address _lib, SetConfigParam[] calldata _params) external; function getConfig( address _oapp, address _lib, uint32 _eid, uint32 _configType ) external view returns (bytes memory config); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IMessagingComposer { event ComposeSent(address from, address to, bytes32 guid, uint16 index, bytes message); event ComposeDelivered(address from, address to, bytes32 guid, uint16 index); event LzComposeAlert( address indexed from, address indexed to, address indexed executor, bytes32 guid, uint16 index, uint256 gas, uint256 value, bytes message, bytes extraData, bytes reason ); function composeQueue( address _from, address _to, bytes32 _guid, uint16 _index ) external view returns (bytes32 messageHash); function sendCompose(address _to, bytes32 _guid, uint16 _index, bytes calldata _message) external; function lzCompose( address _from, address _to, bytes32 _guid, uint16 _index, bytes calldata _message, bytes calldata _extraData ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IMessagingChannel { event InboundNonceSkipped(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce); event PacketNilified(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash); event PacketBurnt(uint32 srcEid, bytes32 sender, address receiver, uint64 nonce, bytes32 payloadHash); function eid() external view returns (uint32); // this is an emergency function if a message cannot be verified for some reasons // required to provide _nextNonce to avoid race condition function skip(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce) external; function nilify(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external; function burn(address _oapp, uint32 _srcEid, bytes32 _sender, uint64 _nonce, bytes32 _payloadHash) external; function nextGuid(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (bytes32); function inboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64); function outboundNonce(address _sender, uint32 _dstEid, bytes32 _receiver) external view returns (uint64); function inboundPayloadHash( address _receiver, uint32 _srcEid, bytes32 _sender, uint64 _nonce ) external view returns (bytes32); function lazyInboundNonce(address _receiver, uint32 _srcEid, bytes32 _sender) external view returns (uint64); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; interface IMessagingContext { function isSendingMessage() external view returns (bool); function getSendContext() external view returns (uint32 dstEid, address sender); }
// SPDX-License-Identifier: Unlicense /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.8.0 <0.9.0; library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore(0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. )) } return tempBytes; } function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes.slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { require(_bytes.length >= _start + 1 , "toUint8_outOfBounds"); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equal_nonAligned(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let endMinusWord := add(_preBytes, length) let mc := add(_preBytes, 0x20) let cc := add(_postBytes, 0x20) for { // the next line is the loop condition: // while(uint256(mc < endWord) + cb == 2) } eq(add(lt(mc, endMinusWord), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } // Only if still successful // For <1 word tail bytes if gt(success, 0) { // Get the remainder of length/32 // length % 32 = AND(length, 32 - 1) let numTailBytes := and(length, 0x1f) let mcRem := mload(mc) let ccRem := mload(cc) for { let i := 0 // the next line is the loop condition: // while(uint256(i < numTailBytes) + cb == 2) } eq(add(lt(i, numTailBytes), cb), 2) { i := add(i, 1) } { if iszero(eq(byte(i, mcRem), byte(i, ccRem))) { // unsuccess: success := 0 cb := 0 } } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } }
// SPDX-License-Identifier: LZBL-1.2 pragma solidity ^0.8.20; import { CalldataBytesLib } from "../../libs/CalldataBytesLib.sol"; library ExecutorOptions { using CalldataBytesLib for bytes; uint8 internal constant WORKER_ID = 1; uint8 internal constant OPTION_TYPE_LZRECEIVE = 1; uint8 internal constant OPTION_TYPE_NATIVE_DROP = 2; uint8 internal constant OPTION_TYPE_LZCOMPOSE = 3; uint8 internal constant OPTION_TYPE_ORDERED_EXECUTION = 4; error Executor_InvalidLzReceiveOption(); error Executor_InvalidNativeDropOption(); error Executor_InvalidLzComposeOption(); /// @dev decode the next executor option from the options starting from the specified cursor /// @param _options [executor_id][executor_option][executor_id][executor_option]... /// executor_option = [option_size][option_type][option] /// option_size = len(option_type) + len(option) /// executor_id: uint8, option_size: uint16, option_type: uint8, option: bytes /// @param _cursor the cursor to start decoding from /// @return optionType the type of the option /// @return option the option of the executor /// @return cursor the cursor to start decoding the next executor option function nextExecutorOption( bytes calldata _options, uint256 _cursor ) internal pure returns (uint8 optionType, bytes calldata option, uint256 cursor) { unchecked { // skip worker id cursor = _cursor + 1; // read option size uint16 size = _options.toU16(cursor); cursor += 2; // read option type optionType = _options.toU8(cursor); // startCursor and endCursor are used to slice the option from _options uint256 startCursor = cursor + 1; // skip option type uint256 endCursor = cursor + size; option = _options[startCursor:endCursor]; cursor += size; } } function decodeLzReceiveOption(bytes calldata _option) internal pure returns (uint128 gas, uint128 value) { if (_option.length != 16 && _option.length != 32) revert Executor_InvalidLzReceiveOption(); gas = _option.toU128(0); value = _option.length == 32 ? _option.toU128(16) : 0; } function decodeNativeDropOption(bytes calldata _option) internal pure returns (uint128 amount, bytes32 receiver) { if (_option.length != 48) revert Executor_InvalidNativeDropOption(); amount = _option.toU128(0); receiver = _option.toB32(16); } function decodeLzComposeOption( bytes calldata _option ) internal pure returns (uint16 index, uint128 gas, uint128 value) { if (_option.length != 18 && _option.length != 34) revert Executor_InvalidLzComposeOption(); index = _option.toU16(0); gas = _option.toU128(2); value = _option.length == 34 ? _option.toU128(18) : 0; } function encodeLzReceiveOption(uint128 _gas, uint128 _value) internal pure returns (bytes memory) { return _value == 0 ? abi.encodePacked(_gas) : abi.encodePacked(_gas, _value); } function encodeNativeDropOption(uint128 _amount, bytes32 _receiver) internal pure returns (bytes memory) { return abi.encodePacked(_amount, _receiver); } function encodeLzComposeOption(uint16 _index, uint128 _gas, uint128 _value) internal pure returns (bytes memory) { return _value == 0 ? abi.encodePacked(_index, _gas) : abi.encodePacked(_index, _gas, _value); } }
// SPDX-License-Identifier: LZBL-1.2 pragma solidity ^0.8.20; import { BytesLib } from "solidity-bytes-utils/contracts/BytesLib.sol"; import { BitMap256 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/messagelib/libs/BitMaps.sol"; import { CalldataBytesLib } from "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/CalldataBytesLib.sol"; import "../../../../protocol/contracts/messagelib/libs/BitMaps.sol"; import "../../../../protocol/contracts/libs/CalldataBytesLib.sol"; import "../../../../protocol/contracts/messagelib/libs/BitMaps.sol"; library DVNOptions { using CalldataBytesLib for bytes; using BytesLib for bytes; uint8 internal constant WORKER_ID = 2; uint8 internal constant OPTION_TYPE_PRECRIME = 1; error DVN_InvalidDVNIdx(); error DVN_InvalidDVNOptions(uint256 cursor); /// @dev group dvn options by its idx /// @param _options [dvn_id][dvn_option][dvn_id][dvn_option]... /// dvn_option = [option_size][dvn_idx][option_type][option] /// option_size = len(dvn_idx) + len(option_type) + len(option) /// dvn_id: uint8, dvn_idx: uint8, option_size: uint16, option_type: uint8, option: bytes /// @return dvnOptions the grouped options, still share the same format of _options /// @return dvnIndices the dvn indices function groupDVNOptionsByIdx( bytes memory _options ) internal pure returns (bytes[] memory dvnOptions, uint8[] memory dvnIndices) { if (_options.length == 0) return (dvnOptions, dvnIndices); uint8 numDVNs = getNumDVNs(_options); // if there is only 1 dvn, we can just return the whole options if (numDVNs == 1) { dvnOptions = new bytes[](1); dvnOptions[0] = _options; dvnIndices = new uint8[](1); dvnIndices[0] = _options.toUint8(3); // dvn idx return (dvnOptions, dvnIndices); } // otherwise, we need to group the options by dvn_idx dvnIndices = new uint8[](numDVNs); dvnOptions = new bytes[](numDVNs); unchecked { uint256 cursor = 0; uint256 start = 0; uint8 lastDVNIdx = 255; // 255 is an invalid dvn_idx while (cursor < _options.length) { ++cursor; // skip worker_id // optionLength asserted in getNumDVNs (skip check) uint16 optionLength = _options.toUint16(cursor); cursor += 2; // dvnIdx asserted in getNumDVNs (skip check) uint8 dvnIdx = _options.toUint8(cursor); // dvnIdx must equal to the lastDVNIdx for the first option // so it is always skipped in the first option // this operation slices out options whenever the scan finds a different lastDVNIdx if (lastDVNIdx == 255) { lastDVNIdx = dvnIdx; } else if (dvnIdx != lastDVNIdx) { uint256 len = cursor - start - 3; // 3 is for worker_id and option_length bytes memory opt = _options.slice(start, len); _insertDVNOptions(dvnOptions, dvnIndices, lastDVNIdx, opt); // reset the start and lastDVNIdx start += len; lastDVNIdx = dvnIdx; } cursor += optionLength; } // skip check the cursor here because the cursor is asserted in getNumDVNs // if we have reached the end of the options, we need to process the last dvn uint256 size = cursor - start; bytes memory op = _options.slice(start, size); _insertDVNOptions(dvnOptions, dvnIndices, lastDVNIdx, op); // revert dvnIndices to start from 0 for (uint8 i = 0; i < numDVNs; ++i) { --dvnIndices[i]; } } } function _insertDVNOptions( bytes[] memory _dvnOptions, uint8[] memory _dvnIndices, uint8 _dvnIdx, bytes memory _newOptions ) internal pure { // dvnIdx starts from 0 but default value of dvnIndices is 0, // so we tell if the slot is empty by adding 1 to dvnIdx if (_dvnIdx == 255) revert DVN_InvalidDVNIdx(); uint8 dvnIdxAdj = _dvnIdx + 1; for (uint256 j = 0; j < _dvnIndices.length; ++j) { uint8 index = _dvnIndices[j]; if (dvnIdxAdj == index) { _dvnOptions[j] = abi.encodePacked(_dvnOptions[j], _newOptions); break; } else if (index == 0) { // empty slot, that means it is the first time we see this dvn _dvnIndices[j] = dvnIdxAdj; _dvnOptions[j] = _newOptions; break; } } } /// @dev get the number of unique dvns /// @param _options the format is the same as groupDVNOptionsByIdx function getNumDVNs(bytes memory _options) internal pure returns (uint8 numDVNs) { uint256 cursor = 0; BitMap256 bitmap; // find number of unique dvn_idx unchecked { while (cursor < _options.length) { ++cursor; // skip worker_id uint16 optionLength = _options.toUint16(cursor); cursor += 2; if (optionLength < 2) revert DVN_InvalidDVNOptions(cursor); // at least 1 byte for dvn_idx and 1 byte for option_type uint8 dvnIdx = _options.toUint8(cursor); // if dvnIdx is not set, increment numDVNs // max num of dvns is 255, 255 is an invalid dvn_idx // The order of the dvnIdx is not required to be sequential, as enforcing the order may weaken // the composability of the options. e.g. if we refrain from enforcing the order, an OApp that has // already enforced certain options can append additional options to the end of the enforced // ones without restrictions. if (dvnIdx == 255) revert DVN_InvalidDVNIdx(); if (!bitmap.get(dvnIdx)) { ++numDVNs; bitmap = bitmap.set(dvnIdx); } cursor += optionLength; } } if (cursor != _options.length) revert DVN_InvalidDVNOptions(cursor); } /// @dev decode the next dvn option from _options starting from the specified cursor /// @param _options the format is the same as groupDVNOptionsByIdx /// @param _cursor the cursor to start decoding /// @return optionType the type of the option /// @return option the option /// @return cursor the cursor to start decoding the next option function nextDVNOption( bytes calldata _options, uint256 _cursor ) internal pure returns (uint8 optionType, bytes calldata option, uint256 cursor) { unchecked { // skip worker id cursor = _cursor + 1; // read option size uint16 size = _options.toU16(cursor); cursor += 2; // read option type optionType = _options.toU8(cursor + 1); // skip dvn_idx // startCursor and endCursor are used to slice the option from _options uint256 startCursor = cursor + 2; // skip option type and dvn_idx uint256 endCursor = cursor + size; option = _options[startCursor:endCursor]; cursor += size; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; //import { ILayerZeroReceiver, Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol"; import "../../../../protocol/contracts/interfaces/ILayerZeroReceiver.sol"; interface IOAppReceiver is ILayerZeroReceiver { /** * @notice Retrieves the address responsible for 'sending' composeMsg's to the Endpoint. * @return sender The address responsible for 'sending' composeMsg's to the Endpoint. * * @dev Applications can optionally choose to implement a separate composeMsg sender that is NOT the bridging layer. * @dev The default sender IS the OApp implementer. */ function composeMsgSender() external view returns (address sender); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "../../../../protocol/contracts/interfaces/ILayerZeroEndpointV2.sol"; //import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; /** * @title IOAppCore */ interface IOAppCore { // Custom error messages error OnlyPeer(uint32 eid, bytes32 sender); error NoPeer(uint32 eid); error InvalidEndpointCall(); error InvalidDelegate(); // Event emitted when a peer (OApp) is set for a corresponding endpoint event PeerSet(uint32 eid, bytes32 peer); /** * @notice Retrieves the OApp version information. * @return senderVersion The version of the OAppSender.sol contract. * @return receiverVersion The version of the OAppReceiver.sol contract. */ function oAppVersion() external view returns (uint64 senderVersion, uint64 receiverVersion); /** * @notice Retrieves the LayerZero endpoint associated with the OApp. * @return iEndpoint The LayerZero endpoint as an interface. */ function endpoint() external view returns (ILayerZeroEndpointV2 iEndpoint); /** * @notice Retrieves the peer (OApp) associated with a corresponding endpoint. * @param _eid The endpoint ID. * @return peer The peer address (OApp instance) associated with the corresponding endpoint. */ function peers(uint32 _eid) external view returns (bytes32 peer); /** * @notice Sets the peer address (OApp instance) for a corresponding endpoint. * @param _eid The endpoint ID. * @param _peer The address of the peer to be associated with the corresponding endpoint. */ // function setPeer(uint32 _eid, bytes32 _peer) external; /** * @notice Sets the delegate address for the OApp Core. * @param _delegate The address of the delegate to be set. */ // function setDelegate(address _delegate) external; }
// SPDX-License-Identifier: LZBL-1.2 pragma solidity ^0.8.20; library CalldataBytesLib { function toU8(bytes calldata _bytes, uint256 _start) internal pure returns (uint8) { return uint8(_bytes[_start]); } function toU16(bytes calldata _bytes, uint256 _start) internal pure returns (uint16) { unchecked { uint256 end = _start + 2; return uint16(bytes2(_bytes[_start:end])); } } function toU32(bytes calldata _bytes, uint256 _start) internal pure returns (uint32) { unchecked { uint256 end = _start + 4; return uint32(bytes4(_bytes[_start:end])); } } function toU64(bytes calldata _bytes, uint256 _start) internal pure returns (uint64) { unchecked { uint256 end = _start + 8; return uint64(bytes8(_bytes[_start:end])); } } function toU128(bytes calldata _bytes, uint256 _start) internal pure returns (uint128) { unchecked { uint256 end = _start + 16; return uint128(bytes16(_bytes[_start:end])); } } function toU256(bytes calldata _bytes, uint256 _start) internal pure returns (uint256) { unchecked { uint256 end = _start + 32; return uint256(bytes32(_bytes[_start:end])); } } function toAddr(bytes calldata _bytes, uint256 _start) internal pure returns (address) { unchecked { uint256 end = _start + 20; return address(bytes20(_bytes[_start:end])); } } function toB32(bytes calldata _bytes, uint256 _start) internal pure returns (bytes32) { unchecked { uint256 end = _start + 32; return bytes32(_bytes[_start:end]); } } }
// SPDX-License-Identifier: MIT // modified from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/structs/BitMaps.sol pragma solidity ^0.8.20; type BitMap256 is uint256; using BitMaps for BitMap256 global; library BitMaps { /** * @dev Returns whether the bit at `index` is set. */ function get(BitMap256 bitmap, uint8 index) internal pure returns (bool) { uint256 mask = 1 << index; return BitMap256.unwrap(bitmap) & mask != 0; } /** * @dev Sets the bit at `index`. */ function set(BitMap256 bitmap, uint8 index) internal pure returns (BitMap256) { uint256 mask = 1 << index; return BitMap256.wrap(BitMap256.unwrap(bitmap) | mask); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * 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. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @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`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import { Origin } from "./ILayerZeroEndpointV2.sol"; interface ILayerZeroReceiver { function allowInitializePath(Origin calldata _origin) external view returns (bool); function nextNonce(uint32 _eid, bytes32 _sender) external view returns (uint64); function lzReceive( Origin calldata _origin, bytes32 _guid, bytes calldata _message, address _executor, bytes calldata _extraData ) external payable; }
{ "remappings": [ "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@layerzerolabs/lz-evm-oapp-v2/contracts/=lib/LayerZero-v2/packages/layerzero-v2/evm/oapp/contracts/", "@layerzerolabs/lz-evm-protocol-v2/=lib/LayerZero-v2/packages/layerzero-v2/evm/protocol/", "@layerzerolabs/lz-evm-messagelib-v2/=lib/LayerZero-v2/packages/layerzero-v2/evm/messagelib/", "solidity-bytes-utils/contracts/=lib/solidity-bytes-utils/contracts/", "LayerZero-v2/=lib/LayerZero-v2/", "ds-test/=lib/solidity-stringutils/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solidity-stringutils/=lib/solidity-stringutils/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_endpoint","type":"address"},{"internalType":"uint256","name":"_paramBridgeFee","type":"uint256"},{"internalType":"uint32","name":"_paramChainId","type":"uint32"},{"internalType":"address","name":"_paramOmnifyAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidDelegate","type":"error"},{"inputs":[],"name":"InvalidEndpointCall","type":"error"},{"inputs":[{"internalType":"uint16","name":"optionType","type":"uint16"}],"name":"InvalidOptionType","type":"error"},{"inputs":[],"name":"LzTokenUnavailable","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"NoPeer","type":"error"},{"inputs":[{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"NotEnoughNative","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"OnlyEndpoint","type":"error"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"}],"name":"OnlyPeer","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"length","type":"uint256"}],"name":"StringsInsufficientHexLength","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_id","type":"uint256"},{"indexed":false,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"_sourceChain","type":"uint32"},{"indexed":false,"internalType":"address","name":"_sourceAddress","type":"address"},{"indexed":false,"internalType":"uint32","name":"_destinationChain","type":"uint32"},{"indexed":false,"internalType":"address","name":"_destinationAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"_blockNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_date","type":"uint256"}],"name":"AssetsMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_id","type":"uint256"},{"indexed":false,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"_sourceChain","type":"uint32"},{"indexed":false,"internalType":"address","name":"_sourceAddress","type":"address"},{"indexed":false,"internalType":"uint32","name":"_destinationChain","type":"uint32"},{"indexed":false,"internalType":"address","name":"_destinationAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"_blockNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_date","type":"uint256"}],"name":"AssetsReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"_sourceChainId","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"_thisChainId","type":"uint32"},{"indexed":false,"internalType":"address","name":"_creator","type":"address"},{"indexed":false,"internalType":"address","name":"_bridgedAssetAddress","type":"address"},{"indexed":false,"internalType":"string","name":"_bridgedAssetName","type":"string"},{"indexed":false,"internalType":"string","name":"_bridgedAssetSymbol","type":"string"},{"indexed":false,"internalType":"address","name":"_sourceAssetAddress","type":"address"},{"indexed":false,"internalType":"string","name":"_sourceAssetName","type":"string"},{"indexed":false,"internalType":"string","name":"_sourceAssetSymbol","type":"string"}],"name":"NewBridgedTokenCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"eid","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"peer","type":"bytes32"}],"name":"PeerSet","type":"event"},{"inputs":[],"name":"GAS_LIMIT","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"origin","type":"tuple"}],"name":"allowInitializePath","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"amountMigratedAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"amountReceivedAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgeFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"bridgeProfiles","outputs":[{"internalType":"address","name":"person","type":"address"},{"internalType":"uint256","name":"transactionCount","type":"uint256"},{"internalType":"uint256","name":"migratedAssetCount","type":"uint256"},{"internalType":"uint256","name":"receivedAssetCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"bridgeTransactions","outputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint32","name":"sourceChain","type":"uint32"},{"internalType":"uint32","name":"destinationChain","type":"uint32"},{"internalType":"address","name":"sourceAddress","type":"address"},{"internalType":"address","name":"destinationAddress","type":"address"},{"internalType":"uint256","name":"date","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"bridgedTokenForeignEquivalent","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_bridgedCoinAddress","type":"address"},{"internalType":"address","name":"_newAddress","type":"address"}],"name":"changeOmnifyAddressOnBridgedCoin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"str1","type":"string"},{"internalType":"string","name":"str2","type":"string"}],"name":"compare","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"composeMsgSender","outputs":[{"internalType":"address","name":"sender","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"_gas","type":"uint128"},{"internalType":"uint128","name":"_value","type":"uint128"}],"name":"createLzReceiveOption","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"contract ILayerZeroEndpointV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeKeeperAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"address","name":"","type":"address"}],"name":"foreignTokenBridgedEquivalent","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_decimals","type":"uint8"}],"name":"getMinAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_profile","type":"address"}],"name":"lookupBridgeProfileMigratedAssets","outputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amountMigrated","type":"uint256"}],"internalType":"struct Bridges.ProfileMigratedAsset[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_profile","type":"address"}],"name":"lookupBridgeProfileReceivedAssets","outputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amountReceived","type":"uint256"}],"internalType":"struct Bridges.ProfileReceivedAsset[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_profile","type":"address"}],"name":"lookupBridgeProfileTransactions","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"lookupBridgeTransaction","outputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint32","name":"sourceChain","type":"uint32"},{"internalType":"uint32","name":"destinationChain","type":"uint32"},{"internalType":"address","name":"sourceAddress","type":"address"},{"internalType":"address","name":"destinationAddress","type":"address"},{"internalType":"uint256","name":"date","type":"uint256"}],"internalType":"struct Bridges.BridgeTransaction","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint32","name":"_sourceChain","type":"uint32"}],"name":"lookupBridgedTokenForeignEquivalent","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint32","name":"_sourceChain","type":"uint32"}],"name":"lookupForeignTokenBridgedEquivalent","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"srcEid","type":"uint32"},{"internalType":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct Origin","name":"_origin","type":"tuple"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"_executor","type":"address"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_sourceAsset","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint32","name":"_destinationChain","type":"uint32"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"migrateAssets","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"nextNonce","outputs":[{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numberMigrationTransactions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numberReceivedTransactions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oAppVersion","outputs":[{"internalType":"uint64","name":"senderVersion","type":"uint64"},{"internalType":"uint64","name":"receiverVersion","type":"uint64"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"omnifyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"eid","type":"uint32"}],"name":"peers","outputs":[{"internalType":"bytes32","name":"peer","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_delegate","type":"address"}],"name":"publicSetDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_eid","type":"uint32"},{"internalType":"address","name":"_peer","type":"address"}],"name":"publicSetPeer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstEid","type":"uint32"},{"internalType":"string","name":"_message","type":"string"},{"internalType":"bytes","name":"_options","type":"bytes"},{"internalType":"bool","name":"_payInLzToken","type":"bool"}],"name":"quote","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"lzTokenFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setBridgeFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"setBridgeFeeByFeeKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeKeeper","type":"address"}],"name":"setFeeKeeperAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_limit","type":"uint128"}],"name":"setGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_limit","type":"uint128"}],"name":"setGasLimitByFeeKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newaddress","type":"address"}],"name":"setOmnifyAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_address","type":"string"}],"name":"stringToAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"thisChainEid","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transactionCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a034620001d657600090601f6200513438819003918201601f1916830192916001600160401b039182851184861017620001c2578160809285926040978852833981010312620001be576200005582620001db565b916020810151848201519163ffffffff8316809303620001ba5760606200007d9101620001db565b6001600160a01b03948516608052923315620001a95786908560805116803b15620001a5578290602489518095819363ca5eb5e160e01b83523360048401525af180156200019b576200016b575b505090661e8480000000009160015460018060a01b031996338883161760015551977f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0873393169180a360001960045560055584600b54161717600b551690600d541617600d55614f439081620001f182396080518181816104b1015281816108fd01528181610b2c0152818161273a015281816130ad0152613b040152f35b81979297116200018757855294661e84800000000038620000cb565b634e487b7160e01b82526041600452602482fd5b87513d8a823e3d90fd5b8280fd5b8551632d618d8160e21b8152600490fd5b8680fd5b8380fd5b634e487b7160e01b86526041600452602486fd5b600080fd5b51906001600160a01b0382168203620001d65756fe608060405260043610156200001357600080fd5b60003560e01c80630180a023146200033b578063091d2788146200033557806313137d65146200032f57806315706fdf146200032957806317442b70146200032357806317b6dd42146200031d5780631906f343146200031757806332bff02214620003115780633a96fdd7146200030b578063592c08bf14620003055780635e280f1114620002ff5780635f82a51414620002f957806364dd273014620002f357806365377ee514620002ed5780636e2313cf14620002e7578063715018a614620002e1578063735ea4e714620002db57806375b0984e14620002d55780637d20941c14620002cf5780637d25a05e14620002c957806382b12dd714620002c35780638b907f0614620002bd5780638da5cb5b14620002b7578063903ff6aa14620002b1578063998cdf8314620002ab5780639c23485114620002a5578063a1da9dae146200029f578063b6698fc21462000269578063b77bf6001462000299578063b92d0eff1462000293578063bb0b6a53146200028d578063c342cac31462000287578063c72242b21462000281578063cd5bb419146200027b578063d3fc6e111462000275578063de2231da146200026f578063e9a270c81462000269578063eaa3f1821462000263578063ee213869146200025d578063f2fde38b1462000257578063f4ed4c841462000251578063f73cf99c146200024b578063f77e5dd31462000245578063ff7bd03d146200023f5763ffbfa81c146200023957600080fd5b62002121565b620020d5565b62002037565b62001fac565b62001f5f565b62001ec6565b62001e98565b62001d53565b62001846565b62001d28565b62001c48565b62001b03565b620019a0565b62001907565b620018c8565b620018ab565b6200188b565b620017f2565b620017d2565b620017ad565b62000dac565b62000d81565b62000c55565b62000bd2565b62000ba7565b62000b87565b62000af5565b62000a5e565b620009f9565b620009d9565b620009b9565b62000993565b6200092c565b620008e5565b620008a3565b6200080f565b620007ca565b6200075c565b62000725565b62000701565b620006ae565b62000448565b620003c9565b6200035d565b600435906001600160801b03821682036200035857565b600080fd5b346200035857602036600319011262000358576200037a62000341565b600c546001600160a01b031633036200035857620003bb90640100000000600160a01b03600b549160201b1690640100000000600160a01b03191617600b55565b005b60009103126200035857565b346200035857600036600319011262000358576020600b546001600160801b0360405191831c168152f35b60609060031901126200035857600490565b9181601f8401121562000358578235916001600160401b0383116200035857602083818601950101116200035857565b6001600160a01b038116036200035857565b60e036600319011262000358576200046036620003f4565b6001600160401b0360843581811162000358576200048390369060040162000406565b916200049160a43562000436565b60c4359081116200035857620004ac90369060040162000406565b5050337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316036200054657620004f4620004ee84620021a7565b62002841565b9260208101358094036200050e57620003bb83836200287a565b6200051a8491620021a7565b60405163309afaf360e21b815263ffffffff9190911660048201526024810191909152604490fd5b0390fd5b6040516391ac5e4f60e01b8152336004820152602490fd5b634e487b7160e01b600052604160045260246000fd5b6001600160401b0381116200058857604052565b6200055e565b60e081019081106001600160401b038211176200058857604052565b604081019081106001600160401b038211176200058857604052565b606081019081106001600160401b038211176200058857604052565b90601f801991011681019081106001600160401b038211176200058857604052565b604051906200061382620005aa565b565b6040519060a082018281106001600160401b038211176200058857604052565b6001600160401b0381116200058857601f01601f191660200190565b9291926200065f8262000635565b916200066f6040519384620005e2565b82948184528183011162000358578281602093846000960137010152565b9080601f830112156200035857816020620006ab9335910162000651565b90565b346200035857602036600319011262000358576004356001600160401b0381116200035857620006ef620006e960209236906004016200068d565b620021b3565b6040516001600160a01b039091168152f35b34620003585760003660031901126200035857604080516001815260016020820152f35b34620003585760003660031901126200035857600d546040516001600160a01b039091168152602090f35b60ff8116036200035857565b34620003585760203660031901126200035857602062000789600435620007838162000750565b62002306565b604051908152f35b63ffffffff8116036200035857565b60409060031901126200035857600435620007bb8162000791565b90602435620006ab8162000436565b346200035857602063ffffffff620007e236620007a0565b911660009081526003835260408082206001600160a01b03938416835260205290205b5416604051908152f35b346200035857604036600319011262000358576001600160401b036004358181116200035857620008459036906004016200068d565b906024359081116200035857602091620008686200086f9236906004016200068d565b9062002370565b6040519015158152f35b60409060031901126200035857600435620008948162000436565b90602435620006ab8162000791565b346200035857602063ffffffff620008bb3662000879565b9190911660009081526003835260408082206001600160a01b039384168352602052902062000805565b346200035857600036600319011262000358576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3462000358576020366003190112620003585760806004356200094f8162000436565b60018060a01b03809116600052600e602052604060002090815416906001810154906006600382015491015491604051938452602084015260408301526060820152f35b34620003585760003660031901126200035857602063ffffffff600b5416604051908152f35b346200035857600036600319011262000358576020600754604051908152f35b346200035857600036600319011262000358576020600854604051908152f35b34620003585760008060031936011262000a5b5762000a1762002b96565b600180546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b3462000358576000604036600319011262000a5b5760043562000a818162000436565b816024359162000a918362000436565b62000a9b62002b96565b6001600160a01b0390811692833b1562000af1576024908360405195869485936338c3fb3560e11b85521660048401525af1801562000aeb5762000add575080f35b62000ae89062000574565b80f35b620023df565b8280fd5b3462000358576000602036600319011262000a5b5760043562000b188162000436565b62000b2262002b96565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691839190833b1562000af15760249083604051958694859363ca5eb5e160e01b85521660048401525af1801562000aeb5762000add575080f35b346200035857600036600319011262000358576020600654604051908152f35b3462000358576040366003190112620003585762000bc760043562000791565b602060405160008152f35b346200035857600036600319011262000358576020600554604051908152f35b602080820190602083528351809252602060408094019401926000905b83821062000c1f57505050505090565b909192939483828262000c476001948a516020809160018060a01b0381511684520151910152565b019601949392019062000c0f565b3462000358576020806003193601126200035857600480359062000c798262000436565b6001600160a01b0382166000908152600e60205260409020600301549162000ca183620023eb565b9362000cb16040519586620005e2565b838552601f1962000cc285620023eb565b0160005b81811062000d68575050508262000cec575b6040518062000ce8868262000bf2565b0390f35b60005b83811062000cfe575062000cd8565b60019062000d4762000d418562000d278660018060a01b0316600052600e602052604060002090565b0162000d33846200241e565b600052602052604060002090565b6200246c565b62000d53828862002451565b5262000d60818762002451565b500162000cef565b829062000d7462002403565b82828a0101520162000cc6565b346200035857600036600319011262000358576001546040516001600160a01b039091168152602090f35b6080366003190112620003585762000dc660043562000436565b62000dd360443562000791565b62000de060643562000436565b600b5463ffffffff62000dfd81831680926044351614156200219f565b62000e156004356001600160a01b031615156200219f565b62000e6162000e5460443562000e3f60043560018060a01b03166000526002602052604060002090565b9063ffffffff16600052602052604060002090565b546001600160a01b031690565b62000eae62000ea262000e548362000e8b60443563ffffffff166000526003602052604060002090565b9060018060a01b0316600052602052604060002090565b6001600160a01b031690565b91821515928362001797575b5062000ee762000eda62000ee0816004356001600160a01b031662002c26565b62002ccd565b9262002d09565b9162000ef762000eda3362002c26565b9262000f1262000eda6064356001600160a01b031662002c26565b62000f2362000eda60243562002d09565b6040516306fdde0360e01b815260008160048181356001600160a01b03165afa801562000aeb5762000f5f916000916200176f575b5062002ccd565b6040516395d89b4160e01b815290919060008160048181356001600160a01b03165afa801562000aeb5762000f9d916000916200176f575062002ccd565b60405163313ce56760e01b81529790939060208960048181356001600160a01b03165afa98891562000aeb5762000eda60ff620010159b62000fea936000916200174b575b501662002d09565b956200100e62000ffe62000eda8d62002e83565b986001600160a01b031662002c26565b9862002515565b906200106c620010616001600160801b03604051956200104d876200103e886020830162002600565b03601f198101895288620005e2565b60201c166200105b6200312c565b62003148565b8093604435620026a2565b50906200108862001080836005546200242d565b34146200219f565b15620016755760405163313ce56760e01b815260208160048181356001600160a01b03165afa90811562000aeb57620010db91620010d0916000916200163f575b5062002306565b60243510156200219f565b6040516370a0823160e01b8152336004820152602081806024810103816004356001600160a01b03165afa801562000aeb57620011279160009162001609575b5060243511156200219f565b6004356001600160a01b03163b1562000358576040516345825ce960e01b8152336004820152602480359082015260008180604481010381836004356001600160a01b03165af1801562000aeb57620015f2575b505b600d54620011969062000ea2906001600160a01b031681565b9260055493803b15620003585760009060046040518097819363162c2c8560e01b83525af191821562000aeb577f2e88a458fcefe33a7dd803f5c057956539b67dd8cf401bc09fd2a6e46de103a594620014d693620015d4575b5062001207620012026007546200263b565b600755565b620012206200121b60243560095462002ee3565b600955565b600a93620012386200123386546200263b565b600a55565b62001274600435620012558754600052600f602052604060002090565b80546001600160a01b0319166001600160a01b03909216919091179055565b600160243581620012908854600052600f602052604060002090565b0155620012d4620012a6600b5463ffffffff1690565b6002620012be8954600052600f602052604060002090565b019063ffffffff1663ffffffff19825416179055565b620013166044356002620012f38954600052600f602052604060002090565b019067ffffffff0000000082549160201b169067ffffffff000000001916179055565b62001367336002620013338954600052600f602052604060002090565b01805468010000000000000000600160e01b03191660409290921b68010000000000000000600160e01b0316919091179055565b600390620013a860643583620013888a54600052600f602052604060002090565b0180546001600160a01b0319166001600160a01b03909216919091179055565b426004620013c18954600052600f602052604060002090565b0155336000908152600e60205260409020620013f790600435906005905b019060018060a01b0316600052602052604060002090565b54336000908152600e6020526040902090929082016200141881546200263b565b90558754336000908152600e602052604090206200144890600281019085905b0154600052602052604060002090565b5582156200150d5750620014b4620014996024358362001491866004620014813360018060a01b0316600052600e602052604060002090565b0190600052602052604060002090565b015462002ee3565b336000908152600e6020526040902090939060049062001481565b01555b620014c162000604565b91825260006020830152339260443562003023565b5054600b5463ffffffff1662001508604051928392429143916064359160443591339160243590600435908a6200264b565b0390a1005b336000908152600e6020526040902090925082016200152d81546200263b565b9055336000908152600e602052604090208281015490620015559060043590600590620013df565b55336000908152600e602052604090206200157f9060048035916200125591810190869062001438565b336000908152600e60205260409020620015cc90620015b09060243590849062001491906004810190889062001438565b336000908152600e602052604090209093600482019162001438565b0155620014b7565b80620015e4620015eb9262000574565b80620003bd565b38620011f0565b80620015e4620016029262000574565b386200117b565b62001630915060203d60201162001637575b620016278183620005e2565b8101906200262b565b386200111b565b503d6200161b565b62001666915060203d6020116200166d575b6200165d8183620005e2565b810190620024fd565b38620010c9565b503d62001651565b60405163313ce56760e01b815260208160048181356001600160a01b03165afa90811562000aeb57620016b691620010d0916000916200163f575062002306565b6040516323b872dd60e01b8152336004820152306024808301919091523560448201526020818060648101038160006004356001600160a01b03165af1801562000aeb576200170f9160009162001715575b506200219f565b6200117d565b6200173c915060203d60201162001743575b620017338183620005e2565b81019062002613565b3862001708565b503d62001727565b62001768915060203d6020116200166d576200165d8183620005e2565b3862000fe2565b6200179091503d806000833e620017878183620005e2565b81019062002495565b3862000f58565b6004356001600160a01b03161492503862000eba565b34620003585760203660031901126200035857620017ca62002b96565b600435600555005b346200035857600036600319011262000358576020600954604051908152f35b34620003585760203660031901126200035857620003bb6200181362000341565b6200181d62002b96565b640100000000600160a01b03600b549160201b1690640100000000600160a01b03191617600b55565b3462000358576020620008056200185d3662000879565b6001600160a01b03918216600090815260028552604080822063ffffffff9093168252602092909252209091565b346200035857600036600319011262000358576020600a54604051908152f35b346200035857600036600319011262000358576020604051308152f35b3462000358576020366003190112620003585763ffffffff600435620018ee8162000791565b1660005260006020526020604060002054604051908152f35b34620003585760203660031901126200035857600435620019288162000436565b6200193262002b96565b600d80546001600160a01b0319166001600160a01b0392909216919091179055005b60005b838110620019685750506000910152565b818101518382015260200162001957565b90602091620019948151809281855285808601910162001954565b601f01601f1916010190565b34620003585760403660031901126200035857620019bd62000341565b602435906001600160801b038216918281036200035857620019de6200312c565b9261ffff600381620019f08762003c8d565b160362001a7c5762000ce862001a368686868662001a4b5750604051906001600160801b03199060801b1660208201526010815262001a2f81620005aa565b9062003d33565b60405191829160208352602083019062001979565b90604051916001600160801b0319809260801b16602084015260801b1660308201526020815262001a2f81620005aa565b60249062001a8a8662003c8d565b604051633a51740d60e01b815291166004820152fd5b602080820190602083528351809252602060408094019401926000905b83821062001acd57505050505090565b909192939483828262001af56001948a516020809160018060a01b0381511684520151910152565b019601949392019062001abd565b346200035857602080600319360112620003585760043562001b258162000436565b6001600160a01b0381166000908152600e60205260409020600601549062001b4d82620023eb565b9262001b5d6040519485620005e2565b828452601f1962001b6e84620023eb565b0160005b81811062001bf1575050508162001b94575b6040518062000ce8858262001aa0565b60005b82811062001ba6575062001b84565b60019062001bd062000d41600762000d278660018060a01b0316600052600e602052604060002090565b62001bdc828762002451565b5262001be9818662002451565b500162001b97565b829062001bfd62002403565b8282890101520162001b72565b602090602060408183019282815285518094520193019160005b82811062001c33575050505090565b83518552938101939281019260010162001c24565b3462000358576020366003190112620003585760043562001c698162000436565b60018060a01b038116600052600e60205260019060016040600020015462001c9181620023eb565b9162001ca16040519384620005e2565b818352601f1962001cb283620023eb565b013660208501378162001cd0575b6040518062000ce8858262001c0a565b60005b82811062001ce2575062001cc0565b849062001d13600262001d078560018060a01b0316600052600e602052604060002090565b0162000d33836200241e565b5462001d20828762002451565b520162001cd3565b34620003585760003660031901126200035857600c546040516001600160a01b039091168152602090f35b3462000358576020366003190112620003585762000ce860408060c0815162001d7c816200058e565b600091818380935282602082015282858201528260608201528260808201528260a082015201526004358152600f6020522090600481519262001dbf846200058e565b80546001600160a01b03908116855260018201546020860152600282015463ffffffff8082168688015262001e1c92919062001e09908260201c16606089019063ffffffff169052565b851c166001600160a01b03166080860152565b60038101546001600160a01b031660a0850152015460c0830152519182918291909160c08060e083019460018060a01b0380825116855260208201516020860152604082015163ffffffff8091166040870152606083015116606086015280608083015116608086015260a08201511660a08501520151910152565b34620003585760203660031901126200035857600c546001600160a01b031633036200035857600435600555005b3462000358576020366003190112620003585760043562001ee78162000436565b62001ef162002b96565b6001600160a01b0390811690811562001f4657600154826bffffffffffffffffffffffff60a01b821617600155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b604051631e4fbdf760e01b815260006004820152602490fd5b3462000358576020366003190112620003585760043562001f808162000436565b62001f8a62002b96565b600c80546001600160a01b0319166001600160a01b0392909216919091179055005b34620003585760203660031901126200035857600435600052600f60205260e0604060002060018060a01b038082541691600181015491600282015463ffffffff60048360038601541694015494604051968752602087015280821660408701528160201c16606086015260401c16608084015260a083015260c0820152f35b801515036200035857565b34620003585760803660031901126200035857600435620020588162000791565b6001600160401b039060243582811162000358576200207c9036906004016200068d565b6044359283116200035857366023840112156200035857620020ad620020c393369060248160040135910162000651565b9060643592620020bd846200202c565b620027b7565b60408051928352602083019190915290f35b346200035857606036600319011262000358576020620020f536620003f4565b63ffffffff8135620021078162000791565b166000526000825260406000205482604051920135148152f35b3462000358577f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b6200215336620007a0565b6200215d62002b96565b60018060a01b03169063ffffffff811660005260006020528160406000205562001508604051928392836020909392919363ffffffff60408201951681520152565b156200035857565b35620006ab8162000791565b620021be9062002a58565b6000805b82518210156200228c5773ffffffffffffffffffffffffffffffffffffff00600882901b16906001600160a01b03168082046101001490151715620022865762002272906200226b62002265620022406200223a6200223462002226888a62002a46565b516001600160f81b03191690565b620039e7565b62002b51565b6200225e620022346200222662002257896200241e565b8a62002a46565b9062002b67565b60ff1690565b9062002b7c565b9060028101809111620022865790620021c2565b6200229b565b6001600160a01b031692915050565b634e487b7160e01b600052601160045260246000fd5b60ff6056199116019060ff82116200228657565b60ff6036199116019060ff82116200228657565b60ff602f199116019060ff82116200228657565b600381901b91906001600160fd1b038116036200228657565b60ff16801562002351576001811462002351576002811462002351576003811015620023325750600190565b6002190160ff8111620022865760ff16604d81116200228657600a0a90565b50600190565b906200236c6020928281519485920162001954565b0190565b90815181518103620023d7576200239f92620023ad604051918284602097889687948585019889910162001954565b8101038084520182620005e2565b51902091620023d06040519182816200239f818301968781519384920162001954565b5190201490565b505050600090565b6040513d6000823e3d90fd5b6001600160401b038111620005885760051b60200190565b604051906200241282620005aa565b60006020838281520152565b90600182018092116200228657565b919082018092116200228657565b634e487b7160e01b600052603260045260246000fd5b8051821015620024665760209160051b010190565b6200243b565b906040516200247b81620005aa565b82546001600160a01b031681526001909201546020830152565b60208183031262000358578051906001600160401b03821162000358570181601f8201121562000358578051620024cc8162000635565b92620024dc6040519485620005e2565b818452602082840101116200035857620006ab916020808501910162001954565b90816020910312620003585751620006ab8162000750565b9199989495620025f196620025ea95620006139a959993996040519d8e9b8c976200254d602099828b80945194859301910162001954565b8d0162002563825180938b808501910162001954565b0162002578825180938a808501910162001954565b016200258d8251809389808501910162001954565b01620025a28251809388808501910162001954565b01620025b78251809387808501910162001954565b01620025cc8251809386808501910162001954565b01620025e18251809385808501910162001954565b01019062002357565b9062002357565b03601f198101845283620005e2565b906020620006ab92818152019062001979565b90816020910312620003585751620006ab816200202c565b9081602091031262000358575190565b6000198114620022865760010190565b9081526001600160a01b039182166020820152604081019290925263ffffffff92831660608301529283166080820152921660a083015290911660c082015260e08101919091526101008101919091526101200190565b906200273691620026d59493620026c6604096879485519283916020830162002600565b03601f198101835282620005e2565b620026df62002403565b50620026eb8362002841565b62002705620026f962000615565b63ffffffff9095168552565b602084015283830152606082015260006080820152815180938192631bb8518b60e31b835230906004840162002fb1565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa92831562000aeb5760009362002781575b50506020825192015190565b620027a6929350803d10620027af575b6200279d8183620005e2565b810190620031a3565b90388062002775565b503d62002791565b62002825620027de95946200273694620026c6604098899687519283916020830162002600565b620027e862002403565b50620027f48562002841565b6200280e6200280262000615565b63ffffffff9097168752565b602086015285850152606084015215156080830152565b815180938192631bb8518b60e31b835230906004840162002fb1565b63ffffffff1680600052600060205260406000205490811562002862575090565b6024906040519063f6ff4fb760e01b82526004820152fd5b9081019060208183031262000358578035906001600160401b03821162000358570190620028a8916200068d565b620028b390620031ba565b604051620028c181620005aa565b60018152601760f91b6020820152620028da90620031ba565b620028e68183620031e4565b620028f1906200327b565b620028fc90620021b3565b91620029098282620031e4565b62002914906200327b565b6200291f906200331a565b6200292b8383620031e4565b62002936906200327b565b6200294190620021b3565b6200294d8484620031e4565b62002958906200327b565b6200296390620021b3565b6200296f8585620031e4565b6200297a906200327b565b62002985906200331a565b620029918686620031e4565b6200299c906200327b565b91620029a98787620031e4565b620029b4906200327b565b93620029c18888620031e4565b620029cc906200327b565b620029d7906200331a565b97620029e49088620031e4565b620029ef906200327b565b620029fa90620033a0565b9662002a06906200327b565b62002a1190620021b3565b9760ff169563ffffffff166200061399620033c5565b805160011015620024665760210190565b805115620024665760200190565b90815181101562002466570160200190565b80516002811015908162002b2d575b508062002ae3575b62002a775790565b805160011990818101818111620022865762002a939062002be0565b9260025b82811062002aa6575050505090565b6001600160f81b031962002abb828462002a46565b511690848101818111620022865762002adb60019360001a918862002a46565b530162002a97565b506001600160f81b0319600f60fb1b8162002afe8462002a27565b51161490811562002b11575b5062002a6f565b600b60fb1b915062002b238362002a27565b5116143862002b0a565b905015620024665760208101516001600160f81b031916600360fc1b143862002a67565b60041b90610ff060f08316921682036200228657565b9060ff8091169116019060ff82116200228657565b6001600160a01b0391821690821601919082116200228657565b6001546001600160a01b0316330362002bab57565b60405163118cdaa760e01b8152336004820152602490fd5b6040519062002bd282620005c6565b602a82526040366020840137565b9062002bec8262000635565b62002bfb6040519182620005e2565b828152809262002c0e601f199162000635565b0190602036910137565b801562002286576000190190565b8062002c3162002bc3565b91603062002c3f8462002a38565b53607862002c4d8462002a27565b5360295b6001811162002c85575062002c64575090565b60405163e22e27eb60e01b8152600481019190915260146024820152604490fd5b90600f8116906010821015620024665762002cc7916f181899199a1a9b1b9c1cb0b131b232b360811b901a62002cbc848762002a46565b5360041c9162002c18565b62002c51565b906200061360216040518462002cee82965180926020808601910162001954565b8101601760f91b6020820152036001810185520183620005e2565b806000917a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008082101562002e52575b506d04ee2d6d415b85acef81000000008083101562002e42575b50662386f26fc100008083101562002e32575b506305f5e1008083101562002e22575b506127108083101562002e12575b50606482101562002e01575b600a8092101562002df6575b60019081602162002daa6001870162002be0565b95860101905b62002dbd575b5050505090565b600019019083906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a83530491821562002df05791908262002db0565b62002db6565b916001019162002d96565b919060646002910491019162002d8a565b6004919392049101913862002d7e565b6008919392049101913862002d70565b6010919392049101913862002d60565b6020919392049101913862002d4d565b60409350810491503862002d33565b6040519062002e7082620005aa565b60048252637472756560e01b6020830152565b1562002e9357620006ab62002e61565b60405162002ea181620005aa565b600581526466616c736560d81b602082015290565b6000198101919082116200228657565b60200390602082116200228657565b919082039182116200228657565b90600454828103908111620022865781111562002efe575090565b8101809111620022865790565b6040519062002f1a82620005c6565b816000815260006020820152604062002f3262002403565b910152565b9190826040910312620003585760405162002f5281620005aa565b6020808294805184520151910152565b60808183031262000358576040519162002f7c83620005c6565b8151835260208201516001600160401b03811681036200035857602084015262002fa99160400162002f37565b604082015290565b906020909392936040835263ffffffff815116604084015281810151606084015260806200300962002ff2604084015160a08488015260e087019062001979565b6060840151868203603f190160a088015262001979565b910151151560c08401526001600160a01b03909416910152565b6200308c60809492620030a996946200303b62002f0b565b5060206200304a865162003aca565b9501918251806200311a575b50620030628562002841565b9251151592620030756200280262000615565b602086015260408501526060840152151585830152565b6040518095819482936302637a4560e41b84526004840162002fb1565b03917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af190811562000aeb57600091620030eb575090565b620006ab915060803d60801162003112575b620031098183620005e2565b81019062002f62565b503d620030fd565b620031259062003aed565b3862003056565b604051600360f01b602082015260028152620006ab81620005aa565b919061ffff6003816200315b8662003c8d565b1603620031955750620006ab9192604051916001600160801b03199060801b166020830152601082526200318f82620005aa565b62003d33565b60249062001a8a8562003c8d565b906040828203126200035857620006ab9162002f37565b620031c462002403565b50602081519160405192620031d984620005aa565b835201602082015290565b9190620031f062002403565b92620031fb62002403565b5080519162003219602083019384518351906020850151926200404f565b90835160208701528351820382811162002286578652835183518101809111620022865782036200324d5750506000915052565b8551928151840180941162002286576200326d6200327794825162002ed5565b905251906200242d565b9052565b62003287815162002be0565b9060209081810151905190828401925b80831015620032e7576000199280620032bb575b5050518251821691191617905290565b9080929350039081116200228657620032d8620032de9162003daa565b62002eb6565b903880620032ab565b91909283518152828101809111620022865792828101809111620022865790601f19810190811162002286579162003297565b9060009160005b81518110156200339c5762003337818362002a46565b5160f81c60308110158062003390575b62003357575b5060010162003321565b600a949194918281029281840414901517156200228657602f19908082810111620022865782010180911162002286579260016200334d565b50603981111562003347565b5050565b620033b590620033af62002e61565b62002370565b15620033c057600190565b600090565b97939692949097959195620033ff620033f0620033e7600b5463ffffffff1690565b63ffffffff1690565b63ffffffff8b1614156200219f565b6200340c3315156200219f565b6000946200343362000e548362000e8b8d63ffffffff166000526003602052604060002090565b6001600160a01b039687821691908262003901575050506000146200382257505050508516916040519563313ce56760e01b87526020968781600481885afa90811562000aeb576200349c91620034939160009162003807575062002306565b8610156200219f565b60405163a9059cbb60e01b81526001600160a01b038416600482015260248101869052938790859060449082906000905af196871562000aeb577f1acd7fd4ef7c22dd54f95c8c1ed80c0f98f090a87e020ca9548b23640083bb779762003723956200351392600092620037e5575b50506200219f565b6200352462001233600a546200263b565b620035408162001255600a54600052600f602052604060002090565b915b62003559620035548660085462002ee3565b600855565b6200356f6200356a6006546200263b565b600655565b6001600a9086816200358c8454600052600f602052604060002090565b0155620035ab886002620012be8554600052600f602052604060002090565b620035d7620035bf600b5463ffffffff1690565b6002620012f38554600052600f602052604060002090565b620035f4846002620013338554600052600f602052604060002090565b62003611836003620013888554600052600f602052604060002090565b4260046200362a8454600052600f602052604060002090565b01556001600160a01b0383166000908152600e6020526040902081016200365281546200263b565b905581546001600160a01b0384166000908152600e6020526040902062003680906002810190849062001438565b55620036a5856008620013df8660018060a01b0316600052600e602052604060002090565b549081156200372857620036fc620036dc898362001491866007620014818b60018060a01b0316600052600e602052604060002090565b926007620014818760018060a01b0316600052600e602052604060002090565b01555b549162003711600b5463ffffffff1690565b90604051978897429643968a6200264b565b0390a1565b6001600160a01b0384166000908152600e602052604090209091506006016200375281546200263b565b90556001600160a01b0383166000908152600e6020526040902060068101549190829062003785908890600890620013df565b55620037af8662001255846007620014818960018060a01b0316600052600e602052604060002090565b620037dd620036dc898362001491866007620014818b60018060a01b0316600052600e602052604060002090565b0155620036ff565b620037ff9250803d106200174357620017338183620005e2565b38806200350b565b6200166691508a3d8c116200166d576200165d8183620005e2565b8699509088620038359597939262003f0a565b91821694620038468615156200219f565b853b1562000358576040516340c10f1960e01b81526001600160a01b038316600482015260248101859052956000908790604490829084905af192831562000aeb577f1acd7fd4ef7c22dd54f95c8c1ed80c0f98f090a87e020ca9548b23640083bb77966200372394620038ea575b50620038c762001233600a546200263b565b620038e38162001255600a54600052600f602052604060002090565b9162003542565b80620015e4620038fa9262000574565b38620038b5565b96509896509a5050505050863b1562000a5b576040516340c10f1960e01b81526001600160a01b038416600482015260248101869052968790604490829084905af192831562000aeb577f1acd7fd4ef7c22dd54f95c8c1ed80c0f98f090a87e020ca9548b23640083bb77966200372394620039d0575b506200398b620035548660085462002ee3565b6200399c6200356a6006546200263b565b620039ad62001233600a546200263b565b620039c98162001255600a54600052600f602052604060002090565b916200356f565b80620015e4620039e09262000574565b3862003978565b908160f81c60308110158062003abe575b1562003a0b57620006ab919250620022d9565b60418110158062003ab2575b1562003a2a57620006ab919250620022c5565b60618110158062003aa6575b1562003a4957620006ab919250620022b1565b60405173024b73b30b634b210313cba32903b30b63ab29d160651b60208201526001600160f81b031984166034820152620005429062003a8d8160358101620026c6565b60405162461bcd60e51b81529182916004830162002600565b50606681111562003a36565b50604681111562003a17565b506039811115620039f8565b80341062003ad55790565b6040516304fb820960e51b8152346004820152602490fd5b60405163393f876560e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116926020929091908381600481885afa90811562000aeb5760009162003c4f575b501692831562003c3d576040516323b872dd60e01b8482019081523360248301526001600160a01b039092166044820152606481019290925262003bd291600091829162003b978160848101620026c6565b519082875af13d1562003c34573d9062003bb18262000635565b9162003bc16040519384620005e2565b82523d60008584013e5b8462004185565b90815191821515918262003c10575b5050905062003bed5750565b604051635274afe760e01b81526001600160a01b03919091166004820152602490fd5b62003c2792508062003c2b94830101910162002613565b1590565b80388062003be1565b60609062003bcb565b6040516329b99a9560e11b8152600490fd5b90508381813d831162003c85575b62003c698183620005e2565b8101031262000358575162003c7e8162000436565b3862003b45565b503d62003c5d565b600281511062003c9e576002015190565b60405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b6044820152606490fd5b60209062003cf360049594938281519485920162001954565b600160f81b910181815260f09290921b6001600160f01b0319166001830152600382015281519162003d2e9083908584019060200162001954565b010190565b9061ffff9160038362003d468362003c8d565b160362003d9c57815183811162003d7d5783166001019283116200228657620026c6620006ab926040519485936020850162003cda565b604490604051906306dfcc6560e41b8252601060048301526024820152fd5b8262001a8a60249262003c8d565b601f811162002286576101000a90565b90620006136027604051809466027b6b734b33c960cd1b602083015262003deb815180926020868601910162001954565b8101036007810185520183620005e2565b906200061360236040518094624f465960e81b602083015262003e29815180926020868601910162001954565b8101036003810185520183620005e2565b9262003e789062003e6960609460ff9498979860018060a01b0316875260806020880152608087019062001979565b90858203604087015262001979565b9416910152565b63ffffffff9182168152911660208201526001600160a01b039182166040820152918116606083015261012060808301819052620006ab979296929562003efa95909462003ee59262003ed691908a019062001979565b9088820360a08a015262001979565b921660c086015284820360e086015262001979565b9161010081840391015262001979565b949091939260018060a01b039462003f488662003f4062000e548a62000e8b8963ffffffff166000526003602052604060002090565b16156200219f565b62003f538162003dba565b9662003f5f8362003dfc565b9360405190610d20808301918383106001600160401b038411176200058857878c859462003f9594620041ee8739309062003e3a565b03906000f093841562000aeb5762000e3f986200401a8362001255897fc9d2f94e2bcd234fc92c813d0c46bcd0e18a90bd21eef6bf630e334848b0f9e59c620040399a169d8e6200400081620012558762000e8b8763ffffffff166000526003602052604060002090565b6001600160a01b0316600090815260026020526040902090565b896200402b600b5463ffffffff1690565b98604051998a998a62003e7f565b0390a190565b60ff811162002286576001901b90565b91928193838111156200406b575b5050620006ab92506200242d565b9092919060208111620041235760009381620040f0575b51841693929190620040a0906200409a84846200242d565b62002ed5565b84848751165b03620040b457505050505090565b909192939481811015620040df57620040cd906200263b565b948486511690809594939291620040a6565b5050909150620006ab92506200242d565b9350620040a062004119620032d8620041136200410d8562002ec6565b620022ed565b6200403f565b1994905062004082565b8091959320916000945b62004139838362002ed5565b86116200417157828120841462004167576200415962004160916200241e565b956200263b565b946200412d565b9450505050915090565b509294915050620006ab925038806200405d565b90620041ae57508051156200419c57805190602001fd5b604051630a12f52160e11b8152600490fd5b81511580620041e3575b620041c1575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b15620041b856fe608060405234620003715762000d20803803806200001d8162000376565b928339810160808282031262000371578151906001600160a01b038216820362000371576020838101519091906001600160401b0390818111620003715782620000699187016200039c565b9160408601518281116200037157606091620000879188016200039c565b9501519460ff86168096036200037157825182811162000271576003918254916001958684811c9416801562000366575b8885101462000350578190601f94858111620002fa575b508890858311600114620002935760009262000287575b505060001982861b1c191690861b1783555b8051938411620002715760049586548681811c9116801562000266575b82821014620002515783811162000206575b50809285116001146200019857509383949184926000956200018c575b50501b92600019911b1c19161790555b600580546001600160a81b03191660089290921b610100600160a81b03169190911791909117905560405161091190816200040f8239f35b01519350388062000144565b92919084601f1981168860005285600020956000905b89838310620001eb5750505010620001d0575b50505050811b01905562000154565b01519060f884600019921b161c1916905538808080620001c1565b858701518955909701969485019488935090810190620001ae565b87600052816000208480880160051c82019284891062000247575b0160051c019087905b8281106200023a57505062000127565b600081550187906200022a565b9250819262000221565b602288634e487b7160e01b6000525260246000fd5b90607f169062000115565b634e487b7160e01b600052604160045260246000fd5b015190503880620000e6565b90889350601f19831691876000528a6000209260005b8c828210620002e35750508411620002ca575b505050811b018355620000f8565b015160001983881b60f8161c19169055388080620002bc565b8385015186558c97909501949384019301620002a9565b90915085600052886000208580850160051c8201928b861062000346575b918a91869594930160051c01915b82811062000336575050620000cf565b600081558594508a910162000326565b9250819262000318565b634e487b7160e01b600052602260045260246000fd5b93607f1693620000b8565b600080fd5b6040519190601f01601f191682016001600160401b038111838210176200027157604052565b919080601f84011215620003715782516001600160401b0381116200027157602090620003d2601f8201601f1916830162000376565b92818452828287010111620003715760005b818110620003fa57508260009394955001015290565b8581018301518482018401528201620003e456fe608060408181526004918236101561001657600080fd5b600092833560e01c91826306fdde03146106a957508163095ea7b3146105ff57816317b6dd42146105d257816318160ddd146105b357816323b872dd146104bf578163313ce5671461049d5781633b97e8561461049d57816340c10f19146103e257816345825ce9146102fe57816370a08231146102c75781637187f66a1461025b57816395d89b411461013a57508063a9059cbb1461010a5763dd62ed3e146100bf57600080fd5b34610106578060031936011261010657806020926100db6107cc565b6100e36107e7565b6001600160a01b0391821683526001865283832091168252845220549051908152f35b5080fd5b50346101065780600319360112610106576020906101336101296107cc565b60243590336107fd565b5160018152f35b83833461010657816003193601126101065780519082845460018160011c9060018316928315610251575b602093848410811461023e5783885290811561022257506001146101cd575b505050829003601f01601f191682019267ffffffffffffffff8411838510176101ba57508291826101b6925282610783565b0390f35b634e487b7160e01b815260418552602490fd5b8787529192508591837f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b83851061020e5750505050830101858080610184565b8054888601830152930192849082016101f8565b60ff1916878501525050151560051b8401019050858080610184565b634e487b7160e01b895260228a52602489fd5b91607f1691610165565b83346102c45760203660031901126102c4576102756107cc565b600554906001600160a01b03600883901c811690338290036102c0578216146102bc57610100600160a81b031990911660089190911b610100600160a81b03161760055580f35b8280fd5b8480fd5b80fd5b5050346101065760203660031901126101065760209181906001600160a01b036102ef6107cc565b16815280845220549051908152f35b839150346101065782600319360112610106576103196107cc565b6005549091602435916001600160a01b039060081c811633036102c05783169283156103cb578385528460205285852054918383106103975750508184957fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef936020938688528785520381872055816002540360025551908152a380f35b865163391434e360e21b81526001600160a01b03909216908201908152602081018390526040810184905281906060010390fd5b8551634b637e8f60e11b8152808301869052602490fd5b919050346102bc57806003193601126102bc576103fd6107cc565b60055460243592916001600160a01b039160081c8216330361049957169283156104845760025490838201809211610471575084927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9260209260025585855284835280852082815401905551908152a380f35b634e487b7160e01b865260119052602485fd5b84602492519163ec442f0560e01b8352820152fd5b8580fd5b50503461010657816003193601126101065760209060ff600554169051908152f35b905082346102c45760603660031901126102c4576104db6107cc565b6104e36107e7565b916044359360018060a01b03831680835260016020528683203384526020528683205491600019830361051f575b6020886101338989896107fd565b8683106105875781156105705733156105595750825260016020908152868320338452815291869020908590039055829061013387610511565b8751634a1406b160e11b8152908101849052602490fd5b875163e602df0560e01b8152908101849052602490fd5b8751637dc7a0d960e11b8152339181019182526020820193909352604081018790528291506060010390fd5b5050346101065781600319360112610106576020906002549051908152f35b505034610106578160031936011261010657600554905160089190911c6001600160a01b03168152602090f35b9050346102bc57816003193601126102bc576106196107cc565b602435903315610692576001600160a01b031691821561067b57508083602095338152600187528181208582528752205582519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b8351634a1406b160e11b8152908101859052602490fd5b835163e602df0560e01b8152808401869052602490fd5b849084346102bc57826003193601126102bc578260035460018160011c9060018316928315610779575b602093848410811461023e57838852908115610222575060011461072357505050829003601f01601f191682019267ffffffffffffffff8411838510176101ba57508291826101b6925282610783565b600387529192508591837fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b8385106107655750505050830101858080610184565b80548886018301529301928490820161074f565b91607f16916106d3565b6020808252825181830181905290939260005b8281106107b857505060409293506000838284010152601f8019910116010190565b818101860151848201604001528501610796565b600435906001600160a01b03821682036107e257565b600080fd5b602435906001600160a01b03821682036107e257565b916001600160a01b038084169283156108c257169283156108a95760009083825281602052604082205490838210610877575091604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652828652038282205586815220818154019055604051908152a3565b60405163391434e360e21b81526001600160a01b03919091166004820152602481019190915260448101839052606490fd5b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fdfea264697066735822122089a573821c2020ff2c4270490485e0549a8a5f167da54ba302482d6500b636af64736f6c63430008180033a2646970667358221220a753d77d4cf6c0fa34f5201bd7332c8f8836d599151cbd49d0b431208df781e364736f6c634300081800330000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b000000000000000000000000000000000000000000000000305d3509223c80000000000000000000000000000000000000000000000000000000000000007668000000000000000000000000883ba282d409e0e984bef70b338f641d0045942f
Deployed Bytecode
0x608060405260043610156200001357600080fd5b60003560e01c80630180a023146200033b578063091d2788146200033557806313137d65146200032f57806315706fdf146200032957806317442b70146200032357806317b6dd42146200031d5780631906f343146200031757806332bff02214620003115780633a96fdd7146200030b578063592c08bf14620003055780635e280f1114620002ff5780635f82a51414620002f957806364dd273014620002f357806365377ee514620002ed5780636e2313cf14620002e7578063715018a614620002e1578063735ea4e714620002db57806375b0984e14620002d55780637d20941c14620002cf5780637d25a05e14620002c957806382b12dd714620002c35780638b907f0614620002bd5780638da5cb5b14620002b7578063903ff6aa14620002b1578063998cdf8314620002ab5780639c23485114620002a5578063a1da9dae146200029f578063b6698fc21462000269578063b77bf6001462000299578063b92d0eff1462000293578063bb0b6a53146200028d578063c342cac31462000287578063c72242b21462000281578063cd5bb419146200027b578063d3fc6e111462000275578063de2231da146200026f578063e9a270c81462000269578063eaa3f1821462000263578063ee213869146200025d578063f2fde38b1462000257578063f4ed4c841462000251578063f73cf99c146200024b578063f77e5dd31462000245578063ff7bd03d146200023f5763ffbfa81c146200023957600080fd5b62002121565b620020d5565b62002037565b62001fac565b62001f5f565b62001ec6565b62001e98565b62001d53565b62001846565b62001d28565b62001c48565b62001b03565b620019a0565b62001907565b620018c8565b620018ab565b6200188b565b620017f2565b620017d2565b620017ad565b62000dac565b62000d81565b62000c55565b62000bd2565b62000ba7565b62000b87565b62000af5565b62000a5e565b620009f9565b620009d9565b620009b9565b62000993565b6200092c565b620008e5565b620008a3565b6200080f565b620007ca565b6200075c565b62000725565b62000701565b620006ae565b62000448565b620003c9565b6200035d565b600435906001600160801b03821682036200035857565b600080fd5b346200035857602036600319011262000358576200037a62000341565b600c546001600160a01b031633036200035857620003bb90640100000000600160a01b03600b549160201b1690640100000000600160a01b03191617600b55565b005b60009103126200035857565b346200035857600036600319011262000358576020600b546001600160801b0360405191831c168152f35b60609060031901126200035857600490565b9181601f8401121562000358578235916001600160401b0383116200035857602083818601950101116200035857565b6001600160a01b038116036200035857565b60e036600319011262000358576200046036620003f4565b6001600160401b0360843581811162000358576200048390369060040162000406565b916200049160a43562000436565b60c4359081116200035857620004ac90369060040162000406565b5050337f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b0316036200054657620004f4620004ee84620021a7565b62002841565b9260208101358094036200050e57620003bb83836200287a565b6200051a8491620021a7565b60405163309afaf360e21b815263ffffffff9190911660048201526024810191909152604490fd5b0390fd5b6040516391ac5e4f60e01b8152336004820152602490fd5b634e487b7160e01b600052604160045260246000fd5b6001600160401b0381116200058857604052565b6200055e565b60e081019081106001600160401b038211176200058857604052565b604081019081106001600160401b038211176200058857604052565b606081019081106001600160401b038211176200058857604052565b90601f801991011681019081106001600160401b038211176200058857604052565b604051906200061382620005aa565b565b6040519060a082018281106001600160401b038211176200058857604052565b6001600160401b0381116200058857601f01601f191660200190565b9291926200065f8262000635565b916200066f6040519384620005e2565b82948184528183011162000358578281602093846000960137010152565b9080601f830112156200035857816020620006ab9335910162000651565b90565b346200035857602036600319011262000358576004356001600160401b0381116200035857620006ef620006e960209236906004016200068d565b620021b3565b6040516001600160a01b039091168152f35b34620003585760003660031901126200035857604080516001815260016020820152f35b34620003585760003660031901126200035857600d546040516001600160a01b039091168152602090f35b60ff8116036200035857565b34620003585760203660031901126200035857602062000789600435620007838162000750565b62002306565b604051908152f35b63ffffffff8116036200035857565b60409060031901126200035857600435620007bb8162000791565b90602435620006ab8162000436565b346200035857602063ffffffff620007e236620007a0565b911660009081526003835260408082206001600160a01b03938416835260205290205b5416604051908152f35b346200035857604036600319011262000358576001600160401b036004358181116200035857620008459036906004016200068d565b906024359081116200035857602091620008686200086f9236906004016200068d565b9062002370565b6040519015158152f35b60409060031901126200035857600435620008948162000436565b90602435620006ab8162000791565b346200035857602063ffffffff620008bb3662000879565b9190911660009081526003835260408082206001600160a01b039384168352602052902062000805565b346200035857600036600319011262000358576040517f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03168152602090f35b3462000358576020366003190112620003585760806004356200094f8162000436565b60018060a01b03809116600052600e602052604060002090815416906001810154906006600382015491015491604051938452602084015260408301526060820152f35b34620003585760003660031901126200035857602063ffffffff600b5416604051908152f35b346200035857600036600319011262000358576020600754604051908152f35b346200035857600036600319011262000358576020600854604051908152f35b34620003585760008060031936011262000a5b5762000a1762002b96565b600180546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b3462000358576000604036600319011262000a5b5760043562000a818162000436565b816024359162000a918362000436565b62000a9b62002b96565b6001600160a01b0390811692833b1562000af1576024908360405195869485936338c3fb3560e11b85521660048401525af1801562000aeb5762000add575080f35b62000ae89062000574565b80f35b620023df565b8280fd5b3462000358576000602036600319011262000a5b5760043562000b188162000436565b62000b2262002b96565b6001600160a01b037f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b811691839190833b1562000af15760249083604051958694859363ca5eb5e160e01b85521660048401525af1801562000aeb5762000add575080f35b346200035857600036600319011262000358576020600654604051908152f35b3462000358576040366003190112620003585762000bc760043562000791565b602060405160008152f35b346200035857600036600319011262000358576020600554604051908152f35b602080820190602083528351809252602060408094019401926000905b83821062000c1f57505050505090565b909192939483828262000c476001948a516020809160018060a01b0381511684520151910152565b019601949392019062000c0f565b3462000358576020806003193601126200035857600480359062000c798262000436565b6001600160a01b0382166000908152600e60205260409020600301549162000ca183620023eb565b9362000cb16040519586620005e2565b838552601f1962000cc285620023eb565b0160005b81811062000d68575050508262000cec575b6040518062000ce8868262000bf2565b0390f35b60005b83811062000cfe575062000cd8565b60019062000d4762000d418562000d278660018060a01b0316600052600e602052604060002090565b0162000d33846200241e565b600052602052604060002090565b6200246c565b62000d53828862002451565b5262000d60818762002451565b500162000cef565b829062000d7462002403565b82828a0101520162000cc6565b346200035857600036600319011262000358576001546040516001600160a01b039091168152602090f35b6080366003190112620003585762000dc660043562000436565b62000dd360443562000791565b62000de060643562000436565b600b5463ffffffff62000dfd81831680926044351614156200219f565b62000e156004356001600160a01b031615156200219f565b62000e6162000e5460443562000e3f60043560018060a01b03166000526002602052604060002090565b9063ffffffff16600052602052604060002090565b546001600160a01b031690565b62000eae62000ea262000e548362000e8b60443563ffffffff166000526003602052604060002090565b9060018060a01b0316600052602052604060002090565b6001600160a01b031690565b91821515928362001797575b5062000ee762000eda62000ee0816004356001600160a01b031662002c26565b62002ccd565b9262002d09565b9162000ef762000eda3362002c26565b9262000f1262000eda6064356001600160a01b031662002c26565b62000f2362000eda60243562002d09565b6040516306fdde0360e01b815260008160048181356001600160a01b03165afa801562000aeb5762000f5f916000916200176f575b5062002ccd565b6040516395d89b4160e01b815290919060008160048181356001600160a01b03165afa801562000aeb5762000f9d916000916200176f575062002ccd565b60405163313ce56760e01b81529790939060208960048181356001600160a01b03165afa98891562000aeb5762000eda60ff620010159b62000fea936000916200174b575b501662002d09565b956200100e62000ffe62000eda8d62002e83565b986001600160a01b031662002c26565b9862002515565b906200106c620010616001600160801b03604051956200104d876200103e886020830162002600565b03601f198101895288620005e2565b60201c166200105b6200312c565b62003148565b8093604435620026a2565b50906200108862001080836005546200242d565b34146200219f565b15620016755760405163313ce56760e01b815260208160048181356001600160a01b03165afa90811562000aeb57620010db91620010d0916000916200163f575b5062002306565b60243510156200219f565b6040516370a0823160e01b8152336004820152602081806024810103816004356001600160a01b03165afa801562000aeb57620011279160009162001609575b5060243511156200219f565b6004356001600160a01b03163b1562000358576040516345825ce960e01b8152336004820152602480359082015260008180604481010381836004356001600160a01b03165af1801562000aeb57620015f2575b505b600d54620011969062000ea2906001600160a01b031681565b9260055493803b15620003585760009060046040518097819363162c2c8560e01b83525af191821562000aeb577f2e88a458fcefe33a7dd803f5c057956539b67dd8cf401bc09fd2a6e46de103a594620014d693620015d4575b5062001207620012026007546200263b565b600755565b620012206200121b60243560095462002ee3565b600955565b600a93620012386200123386546200263b565b600a55565b62001274600435620012558754600052600f602052604060002090565b80546001600160a01b0319166001600160a01b03909216919091179055565b600160243581620012908854600052600f602052604060002090565b0155620012d4620012a6600b5463ffffffff1690565b6002620012be8954600052600f602052604060002090565b019063ffffffff1663ffffffff19825416179055565b620013166044356002620012f38954600052600f602052604060002090565b019067ffffffff0000000082549160201b169067ffffffff000000001916179055565b62001367336002620013338954600052600f602052604060002090565b01805468010000000000000000600160e01b03191660409290921b68010000000000000000600160e01b0316919091179055565b600390620013a860643583620013888a54600052600f602052604060002090565b0180546001600160a01b0319166001600160a01b03909216919091179055565b426004620013c18954600052600f602052604060002090565b0155336000908152600e60205260409020620013f790600435906005905b019060018060a01b0316600052602052604060002090565b54336000908152600e6020526040902090929082016200141881546200263b565b90558754336000908152600e602052604090206200144890600281019085905b0154600052602052604060002090565b5582156200150d5750620014b4620014996024358362001491866004620014813360018060a01b0316600052600e602052604060002090565b0190600052602052604060002090565b015462002ee3565b336000908152600e6020526040902090939060049062001481565b01555b620014c162000604565b91825260006020830152339260443562003023565b5054600b5463ffffffff1662001508604051928392429143916064359160443591339160243590600435908a6200264b565b0390a1005b336000908152600e6020526040902090925082016200152d81546200263b565b9055336000908152600e602052604090208281015490620015559060043590600590620013df565b55336000908152600e602052604090206200157f9060048035916200125591810190869062001438565b336000908152600e60205260409020620015cc90620015b09060243590849062001491906004810190889062001438565b336000908152600e602052604090209093600482019162001438565b0155620014b7565b80620015e4620015eb9262000574565b80620003bd565b38620011f0565b80620015e4620016029262000574565b386200117b565b62001630915060203d60201162001637575b620016278183620005e2565b8101906200262b565b386200111b565b503d6200161b565b62001666915060203d6020116200166d575b6200165d8183620005e2565b810190620024fd565b38620010c9565b503d62001651565b60405163313ce56760e01b815260208160048181356001600160a01b03165afa90811562000aeb57620016b691620010d0916000916200163f575062002306565b6040516323b872dd60e01b8152336004820152306024808301919091523560448201526020818060648101038160006004356001600160a01b03165af1801562000aeb576200170f9160009162001715575b506200219f565b6200117d565b6200173c915060203d60201162001743575b620017338183620005e2565b81019062002613565b3862001708565b503d62001727565b62001768915060203d6020116200166d576200165d8183620005e2565b3862000fe2565b6200179091503d806000833e620017878183620005e2565b81019062002495565b3862000f58565b6004356001600160a01b03161492503862000eba565b34620003585760203660031901126200035857620017ca62002b96565b600435600555005b346200035857600036600319011262000358576020600954604051908152f35b34620003585760203660031901126200035857620003bb6200181362000341565b6200181d62002b96565b640100000000600160a01b03600b549160201b1690640100000000600160a01b03191617600b55565b3462000358576020620008056200185d3662000879565b6001600160a01b03918216600090815260028552604080822063ffffffff9093168252602092909252209091565b346200035857600036600319011262000358576020600a54604051908152f35b346200035857600036600319011262000358576020604051308152f35b3462000358576020366003190112620003585763ffffffff600435620018ee8162000791565b1660005260006020526020604060002054604051908152f35b34620003585760203660031901126200035857600435620019288162000436565b6200193262002b96565b600d80546001600160a01b0319166001600160a01b0392909216919091179055005b60005b838110620019685750506000910152565b818101518382015260200162001957565b90602091620019948151809281855285808601910162001954565b601f01601f1916010190565b34620003585760403660031901126200035857620019bd62000341565b602435906001600160801b038216918281036200035857620019de6200312c565b9261ffff600381620019f08762003c8d565b160362001a7c5762000ce862001a368686868662001a4b5750604051906001600160801b03199060801b1660208201526010815262001a2f81620005aa565b9062003d33565b60405191829160208352602083019062001979565b90604051916001600160801b0319809260801b16602084015260801b1660308201526020815262001a2f81620005aa565b60249062001a8a8662003c8d565b604051633a51740d60e01b815291166004820152fd5b602080820190602083528351809252602060408094019401926000905b83821062001acd57505050505090565b909192939483828262001af56001948a516020809160018060a01b0381511684520151910152565b019601949392019062001abd565b346200035857602080600319360112620003585760043562001b258162000436565b6001600160a01b0381166000908152600e60205260409020600601549062001b4d82620023eb565b9262001b5d6040519485620005e2565b828452601f1962001b6e84620023eb565b0160005b81811062001bf1575050508162001b94575b6040518062000ce8858262001aa0565b60005b82811062001ba6575062001b84565b60019062001bd062000d41600762000d278660018060a01b0316600052600e602052604060002090565b62001bdc828762002451565b5262001be9818662002451565b500162001b97565b829062001bfd62002403565b8282890101520162001b72565b602090602060408183019282815285518094520193019160005b82811062001c33575050505090565b83518552938101939281019260010162001c24565b3462000358576020366003190112620003585760043562001c698162000436565b60018060a01b038116600052600e60205260019060016040600020015462001c9181620023eb565b9162001ca16040519384620005e2565b818352601f1962001cb283620023eb565b013660208501378162001cd0575b6040518062000ce8858262001c0a565b60005b82811062001ce2575062001cc0565b849062001d13600262001d078560018060a01b0316600052600e602052604060002090565b0162000d33836200241e565b5462001d20828762002451565b520162001cd3565b34620003585760003660031901126200035857600c546040516001600160a01b039091168152602090f35b3462000358576020366003190112620003585762000ce860408060c0815162001d7c816200058e565b600091818380935282602082015282858201528260608201528260808201528260a082015201526004358152600f6020522090600481519262001dbf846200058e565b80546001600160a01b03908116855260018201546020860152600282015463ffffffff8082168688015262001e1c92919062001e09908260201c16606089019063ffffffff169052565b851c166001600160a01b03166080860152565b60038101546001600160a01b031660a0850152015460c0830152519182918291909160c08060e083019460018060a01b0380825116855260208201516020860152604082015163ffffffff8091166040870152606083015116606086015280608083015116608086015260a08201511660a08501520151910152565b34620003585760203660031901126200035857600c546001600160a01b031633036200035857600435600555005b3462000358576020366003190112620003585760043562001ee78162000436565b62001ef162002b96565b6001600160a01b0390811690811562001f4657600154826bffffffffffffffffffffffff60a01b821617600155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b604051631e4fbdf760e01b815260006004820152602490fd5b3462000358576020366003190112620003585760043562001f808162000436565b62001f8a62002b96565b600c80546001600160a01b0319166001600160a01b0392909216919091179055005b34620003585760203660031901126200035857600435600052600f60205260e0604060002060018060a01b038082541691600181015491600282015463ffffffff60048360038601541694015494604051968752602087015280821660408701528160201c16606086015260401c16608084015260a083015260c0820152f35b801515036200035857565b34620003585760803660031901126200035857600435620020588162000791565b6001600160401b039060243582811162000358576200207c9036906004016200068d565b6044359283116200035857366023840112156200035857620020ad620020c393369060248160040135910162000651565b9060643592620020bd846200202c565b620027b7565b60408051928352602083019190915290f35b346200035857606036600319011262000358576020620020f536620003f4565b63ffffffff8135620021078162000791565b166000526000825260406000205482604051920135148152f35b3462000358577f238399d427b947898edb290f5ff0f9109849b1c3ba196a42e35f00c50a54b98b6200215336620007a0565b6200215d62002b96565b60018060a01b03169063ffffffff811660005260006020528160406000205562001508604051928392836020909392919363ffffffff60408201951681520152565b156200035857565b35620006ab8162000791565b620021be9062002a58565b6000805b82518210156200228c5773ffffffffffffffffffffffffffffffffffffff00600882901b16906001600160a01b03168082046101001490151715620022865762002272906200226b62002265620022406200223a6200223462002226888a62002a46565b516001600160f81b03191690565b620039e7565b62002b51565b6200225e620022346200222662002257896200241e565b8a62002a46565b9062002b67565b60ff1690565b9062002b7c565b9060028101809111620022865790620021c2565b6200229b565b6001600160a01b031692915050565b634e487b7160e01b600052601160045260246000fd5b60ff6056199116019060ff82116200228657565b60ff6036199116019060ff82116200228657565b60ff602f199116019060ff82116200228657565b600381901b91906001600160fd1b038116036200228657565b60ff16801562002351576001811462002351576002811462002351576003811015620023325750600190565b6002190160ff8111620022865760ff16604d81116200228657600a0a90565b50600190565b906200236c6020928281519485920162001954565b0190565b90815181518103620023d7576200239f92620023ad604051918284602097889687948585019889910162001954565b8101038084520182620005e2565b51902091620023d06040519182816200239f818301968781519384920162001954565b5190201490565b505050600090565b6040513d6000823e3d90fd5b6001600160401b038111620005885760051b60200190565b604051906200241282620005aa565b60006020838281520152565b90600182018092116200228657565b919082018092116200228657565b634e487b7160e01b600052603260045260246000fd5b8051821015620024665760209160051b010190565b6200243b565b906040516200247b81620005aa565b82546001600160a01b031681526001909201546020830152565b60208183031262000358578051906001600160401b03821162000358570181601f8201121562000358578051620024cc8162000635565b92620024dc6040519485620005e2565b818452602082840101116200035857620006ab916020808501910162001954565b90816020910312620003585751620006ab8162000750565b9199989495620025f196620025ea95620006139a959993996040519d8e9b8c976200254d602099828b80945194859301910162001954565b8d0162002563825180938b808501910162001954565b0162002578825180938a808501910162001954565b016200258d8251809389808501910162001954565b01620025a28251809388808501910162001954565b01620025b78251809387808501910162001954565b01620025cc8251809386808501910162001954565b01620025e18251809385808501910162001954565b01019062002357565b9062002357565b03601f198101845283620005e2565b906020620006ab92818152019062001979565b90816020910312620003585751620006ab816200202c565b9081602091031262000358575190565b6000198114620022865760010190565b9081526001600160a01b039182166020820152604081019290925263ffffffff92831660608301529283166080820152921660a083015290911660c082015260e08101919091526101008101919091526101200190565b906200273691620026d59493620026c6604096879485519283916020830162002600565b03601f198101835282620005e2565b620026df62002403565b50620026eb8362002841565b62002705620026f962000615565b63ffffffff9095168552565b602084015283830152606082015260006080820152815180938192631bb8518b60e31b835230906004840162002fb1565b03817f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03165afa92831562000aeb5760009362002781575b50506020825192015190565b620027a6929350803d10620027af575b6200279d8183620005e2565b810190620031a3565b90388062002775565b503d62002791565b62002825620027de95946200273694620026c6604098899687519283916020830162002600565b620027e862002403565b50620027f48562002841565b6200280e6200280262000615565b63ffffffff9097168752565b602086015285850152606084015215156080830152565b815180938192631bb8518b60e31b835230906004840162002fb1565b63ffffffff1680600052600060205260406000205490811562002862575090565b6024906040519063f6ff4fb760e01b82526004820152fd5b9081019060208183031262000358578035906001600160401b03821162000358570190620028a8916200068d565b620028b390620031ba565b604051620028c181620005aa565b60018152601760f91b6020820152620028da90620031ba565b620028e68183620031e4565b620028f1906200327b565b620028fc90620021b3565b91620029098282620031e4565b62002914906200327b565b6200291f906200331a565b6200292b8383620031e4565b62002936906200327b565b6200294190620021b3565b6200294d8484620031e4565b62002958906200327b565b6200296390620021b3565b6200296f8585620031e4565b6200297a906200327b565b62002985906200331a565b620029918686620031e4565b6200299c906200327b565b91620029a98787620031e4565b620029b4906200327b565b93620029c18888620031e4565b620029cc906200327b565b620029d7906200331a565b97620029e49088620031e4565b620029ef906200327b565b620029fa90620033a0565b9662002a06906200327b565b62002a1190620021b3565b9760ff169563ffffffff166200061399620033c5565b805160011015620024665760210190565b805115620024665760200190565b90815181101562002466570160200190565b80516002811015908162002b2d575b508062002ae3575b62002a775790565b805160011990818101818111620022865762002a939062002be0565b9260025b82811062002aa6575050505090565b6001600160f81b031962002abb828462002a46565b511690848101818111620022865762002adb60019360001a918862002a46565b530162002a97565b506001600160f81b0319600f60fb1b8162002afe8462002a27565b51161490811562002b11575b5062002a6f565b600b60fb1b915062002b238362002a27565b5116143862002b0a565b905015620024665760208101516001600160f81b031916600360fc1b143862002a67565b60041b90610ff060f08316921682036200228657565b9060ff8091169116019060ff82116200228657565b6001600160a01b0391821690821601919082116200228657565b6001546001600160a01b0316330362002bab57565b60405163118cdaa760e01b8152336004820152602490fd5b6040519062002bd282620005c6565b602a82526040366020840137565b9062002bec8262000635565b62002bfb6040519182620005e2565b828152809262002c0e601f199162000635565b0190602036910137565b801562002286576000190190565b8062002c3162002bc3565b91603062002c3f8462002a38565b53607862002c4d8462002a27565b5360295b6001811162002c85575062002c64575090565b60405163e22e27eb60e01b8152600481019190915260146024820152604490fd5b90600f8116906010821015620024665762002cc7916f181899199a1a9b1b9c1cb0b131b232b360811b901a62002cbc848762002a46565b5360041c9162002c18565b62002c51565b906200061360216040518462002cee82965180926020808601910162001954565b8101601760f91b6020820152036001810185520183620005e2565b806000917a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008082101562002e52575b506d04ee2d6d415b85acef81000000008083101562002e42575b50662386f26fc100008083101562002e32575b506305f5e1008083101562002e22575b506127108083101562002e12575b50606482101562002e01575b600a8092101562002df6575b60019081602162002daa6001870162002be0565b95860101905b62002dbd575b5050505090565b600019019083906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a83530491821562002df05791908262002db0565b62002db6565b916001019162002d96565b919060646002910491019162002d8a565b6004919392049101913862002d7e565b6008919392049101913862002d70565b6010919392049101913862002d60565b6020919392049101913862002d4d565b60409350810491503862002d33565b6040519062002e7082620005aa565b60048252637472756560e01b6020830152565b1562002e9357620006ab62002e61565b60405162002ea181620005aa565b600581526466616c736560d81b602082015290565b6000198101919082116200228657565b60200390602082116200228657565b919082039182116200228657565b90600454828103908111620022865781111562002efe575090565b8101809111620022865790565b6040519062002f1a82620005c6565b816000815260006020820152604062002f3262002403565b910152565b9190826040910312620003585760405162002f5281620005aa565b6020808294805184520151910152565b60808183031262000358576040519162002f7c83620005c6565b8151835260208201516001600160401b03811681036200035857602084015262002fa99160400162002f37565b604082015290565b906020909392936040835263ffffffff815116604084015281810151606084015260806200300962002ff2604084015160a08488015260e087019062001979565b6060840151868203603f190160a088015262001979565b910151151560c08401526001600160a01b03909416910152565b6200308c60809492620030a996946200303b62002f0b565b5060206200304a865162003aca565b9501918251806200311a575b50620030628562002841565b9251151592620030756200280262000615565b602086015260408501526060840152151585830152565b6040518095819482936302637a4560e41b84526004840162002fb1565b03917f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03165af190811562000aeb57600091620030eb575090565b620006ab915060803d60801162003112575b620031098183620005e2565b81019062002f62565b503d620030fd565b620031259062003aed565b3862003056565b604051600360f01b602082015260028152620006ab81620005aa565b919061ffff6003816200315b8662003c8d565b1603620031955750620006ab9192604051916001600160801b03199060801b166020830152601082526200318f82620005aa565b62003d33565b60249062001a8a8562003c8d565b906040828203126200035857620006ab9162002f37565b620031c462002403565b50602081519160405192620031d984620005aa565b835201602082015290565b9190620031f062002403565b92620031fb62002403565b5080519162003219602083019384518351906020850151926200404f565b90835160208701528351820382811162002286578652835183518101809111620022865782036200324d5750506000915052565b8551928151840180941162002286576200326d6200327794825162002ed5565b905251906200242d565b9052565b62003287815162002be0565b9060209081810151905190828401925b80831015620032e7576000199280620032bb575b5050518251821691191617905290565b9080929350039081116200228657620032d8620032de9162003daa565b62002eb6565b903880620032ab565b91909283518152828101809111620022865792828101809111620022865790601f19810190811162002286579162003297565b9060009160005b81518110156200339c5762003337818362002a46565b5160f81c60308110158062003390575b62003357575b5060010162003321565b600a949194918281029281840414901517156200228657602f19908082810111620022865782010180911162002286579260016200334d565b50603981111562003347565b5050565b620033b590620033af62002e61565b62002370565b15620033c057600190565b600090565b97939692949097959195620033ff620033f0620033e7600b5463ffffffff1690565b63ffffffff1690565b63ffffffff8b1614156200219f565b6200340c3315156200219f565b6000946200343362000e548362000e8b8d63ffffffff166000526003602052604060002090565b6001600160a01b039687821691908262003901575050506000146200382257505050508516916040519563313ce56760e01b87526020968781600481885afa90811562000aeb576200349c91620034939160009162003807575062002306565b8610156200219f565b60405163a9059cbb60e01b81526001600160a01b038416600482015260248101869052938790859060449082906000905af196871562000aeb577f1acd7fd4ef7c22dd54f95c8c1ed80c0f98f090a87e020ca9548b23640083bb779762003723956200351392600092620037e5575b50506200219f565b6200352462001233600a546200263b565b620035408162001255600a54600052600f602052604060002090565b915b62003559620035548660085462002ee3565b600855565b6200356f6200356a6006546200263b565b600655565b6001600a9086816200358c8454600052600f602052604060002090565b0155620035ab886002620012be8554600052600f602052604060002090565b620035d7620035bf600b5463ffffffff1690565b6002620012f38554600052600f602052604060002090565b620035f4846002620013338554600052600f602052604060002090565b62003611836003620013888554600052600f602052604060002090565b4260046200362a8454600052600f602052604060002090565b01556001600160a01b0383166000908152600e6020526040902081016200365281546200263b565b905581546001600160a01b0384166000908152600e6020526040902062003680906002810190849062001438565b55620036a5856008620013df8660018060a01b0316600052600e602052604060002090565b549081156200372857620036fc620036dc898362001491866007620014818b60018060a01b0316600052600e602052604060002090565b926007620014818760018060a01b0316600052600e602052604060002090565b01555b549162003711600b5463ffffffff1690565b90604051978897429643968a6200264b565b0390a1565b6001600160a01b0384166000908152600e602052604090209091506006016200375281546200263b565b90556001600160a01b0383166000908152600e6020526040902060068101549190829062003785908890600890620013df565b55620037af8662001255846007620014818960018060a01b0316600052600e602052604060002090565b620037dd620036dc898362001491866007620014818b60018060a01b0316600052600e602052604060002090565b0155620036ff565b620037ff9250803d106200174357620017338183620005e2565b38806200350b565b6200166691508a3d8c116200166d576200165d8183620005e2565b8699509088620038359597939262003f0a565b91821694620038468615156200219f565b853b1562000358576040516340c10f1960e01b81526001600160a01b038316600482015260248101859052956000908790604490829084905af192831562000aeb577f1acd7fd4ef7c22dd54f95c8c1ed80c0f98f090a87e020ca9548b23640083bb77966200372394620038ea575b50620038c762001233600a546200263b565b620038e38162001255600a54600052600f602052604060002090565b9162003542565b80620015e4620038fa9262000574565b38620038b5565b96509896509a5050505050863b1562000a5b576040516340c10f1960e01b81526001600160a01b038416600482015260248101869052968790604490829084905af192831562000aeb577f1acd7fd4ef7c22dd54f95c8c1ed80c0f98f090a87e020ca9548b23640083bb77966200372394620039d0575b506200398b620035548660085462002ee3565b6200399c6200356a6006546200263b565b620039ad62001233600a546200263b565b620039c98162001255600a54600052600f602052604060002090565b916200356f565b80620015e4620039e09262000574565b3862003978565b908160f81c60308110158062003abe575b1562003a0b57620006ab919250620022d9565b60418110158062003ab2575b1562003a2a57620006ab919250620022c5565b60618110158062003aa6575b1562003a4957620006ab919250620022b1565b60405173024b73b30b634b210313cba32903b30b63ab29d160651b60208201526001600160f81b031984166034820152620005429062003a8d8160358101620026c6565b60405162461bcd60e51b81529182916004830162002600565b50606681111562003a36565b50604681111562003a17565b506039811115620039f8565b80341062003ad55790565b6040516304fb820960e51b8152346004820152602490fd5b60405163393f876560e21b81526001600160a01b037f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b8116926020929091908381600481885afa90811562000aeb5760009162003c4f575b501692831562003c3d576040516323b872dd60e01b8482019081523360248301526001600160a01b039092166044820152606481019290925262003bd291600091829162003b978160848101620026c6565b519082875af13d1562003c34573d9062003bb18262000635565b9162003bc16040519384620005e2565b82523d60008584013e5b8462004185565b90815191821515918262003c10575b5050905062003bed5750565b604051635274afe760e01b81526001600160a01b03919091166004820152602490fd5b62003c2792508062003c2b94830101910162002613565b1590565b80388062003be1565b60609062003bcb565b6040516329b99a9560e11b8152600490fd5b90508381813d831162003c85575b62003c698183620005e2565b8101031262000358575162003c7e8162000436565b3862003b45565b503d62003c5d565b600281511062003c9e576002015190565b60405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b6044820152606490fd5b60209062003cf360049594938281519485920162001954565b600160f81b910181815260f09290921b6001600160f01b0319166001830152600382015281519162003d2e9083908584019060200162001954565b010190565b9061ffff9160038362003d468362003c8d565b160362003d9c57815183811162003d7d5783166001019283116200228657620026c6620006ab926040519485936020850162003cda565b604490604051906306dfcc6560e41b8252601060048301526024820152fd5b8262001a8a60249262003c8d565b601f811162002286576101000a90565b90620006136027604051809466027b6b734b33c960cd1b602083015262003deb815180926020868601910162001954565b8101036007810185520183620005e2565b906200061360236040518094624f465960e81b602083015262003e29815180926020868601910162001954565b8101036003810185520183620005e2565b9262003e789062003e6960609460ff9498979860018060a01b0316875260806020880152608087019062001979565b90858203604087015262001979565b9416910152565b63ffffffff9182168152911660208201526001600160a01b039182166040820152918116606083015261012060808301819052620006ab979296929562003efa95909462003ee59262003ed691908a019062001979565b9088820360a08a015262001979565b921660c086015284820360e086015262001979565b9161010081840391015262001979565b949091939260018060a01b039462003f488662003f4062000e548a62000e8b8963ffffffff166000526003602052604060002090565b16156200219f565b62003f538162003dba565b9662003f5f8362003dfc565b9360405190610d20808301918383106001600160401b038411176200058857878c859462003f9594620041ee8739309062003e3a565b03906000f093841562000aeb5762000e3f986200401a8362001255897fc9d2f94e2bcd234fc92c813d0c46bcd0e18a90bd21eef6bf630e334848b0f9e59c620040399a169d8e6200400081620012558762000e8b8763ffffffff166000526003602052604060002090565b6001600160a01b0316600090815260026020526040902090565b896200402b600b5463ffffffff1690565b98604051998a998a62003e7f565b0390a190565b60ff811162002286576001901b90565b91928193838111156200406b575b5050620006ab92506200242d565b9092919060208111620041235760009381620040f0575b51841693929190620040a0906200409a84846200242d565b62002ed5565b84848751165b03620040b457505050505090565b909192939481811015620040df57620040cd906200263b565b948486511690809594939291620040a6565b5050909150620006ab92506200242d565b9350620040a062004119620032d8620041136200410d8562002ec6565b620022ed565b6200403f565b1994905062004082565b8091959320916000945b62004139838362002ed5565b86116200417157828120841462004167576200415962004160916200241e565b956200263b565b946200412d565b9450505050915090565b509294915050620006ab925038806200405d565b90620041ae57508051156200419c57805190602001fd5b604051630a12f52160e11b8152600490fd5b81511580620041e3575b620041c1575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b15620041b856fe608060405234620003715762000d20803803806200001d8162000376565b928339810160808282031262000371578151906001600160a01b038216820362000371576020838101519091906001600160401b0390818111620003715782620000699187016200039c565b9160408601518281116200037157606091620000879188016200039c565b9501519460ff86168096036200037157825182811162000271576003918254916001958684811c9416801562000366575b8885101462000350578190601f94858111620002fa575b508890858311600114620002935760009262000287575b505060001982861b1c191690861b1783555b8051938411620002715760049586548681811c9116801562000266575b82821014620002515783811162000206575b50809285116001146200019857509383949184926000956200018c575b50501b92600019911b1c19161790555b600580546001600160a81b03191660089290921b610100600160a81b03169190911791909117905560405161091190816200040f8239f35b01519350388062000144565b92919084601f1981168860005285600020956000905b89838310620001eb5750505010620001d0575b50505050811b01905562000154565b01519060f884600019921b161c1916905538808080620001c1565b858701518955909701969485019488935090810190620001ae565b87600052816000208480880160051c82019284891062000247575b0160051c019087905b8281106200023a57505062000127565b600081550187906200022a565b9250819262000221565b602288634e487b7160e01b6000525260246000fd5b90607f169062000115565b634e487b7160e01b600052604160045260246000fd5b015190503880620000e6565b90889350601f19831691876000528a6000209260005b8c828210620002e35750508411620002ca575b505050811b018355620000f8565b015160001983881b60f8161c19169055388080620002bc565b8385015186558c97909501949384019301620002a9565b90915085600052886000208580850160051c8201928b861062000346575b918a91869594930160051c01915b82811062000336575050620000cf565b600081558594508a910162000326565b9250819262000318565b634e487b7160e01b600052602260045260246000fd5b93607f1693620000b8565b600080fd5b6040519190601f01601f191682016001600160401b038111838210176200027157604052565b919080601f84011215620003715782516001600160401b0381116200027157602090620003d2601f8201601f1916830162000376565b92818452828287010111620003715760005b818110620003fa57508260009394955001015290565b8581018301518482018401528201620003e456fe608060408181526004918236101561001657600080fd5b600092833560e01c91826306fdde03146106a957508163095ea7b3146105ff57816317b6dd42146105d257816318160ddd146105b357816323b872dd146104bf578163313ce5671461049d5781633b97e8561461049d57816340c10f19146103e257816345825ce9146102fe57816370a08231146102c75781637187f66a1461025b57816395d89b411461013a57508063a9059cbb1461010a5763dd62ed3e146100bf57600080fd5b34610106578060031936011261010657806020926100db6107cc565b6100e36107e7565b6001600160a01b0391821683526001865283832091168252845220549051908152f35b5080fd5b50346101065780600319360112610106576020906101336101296107cc565b60243590336107fd565b5160018152f35b83833461010657816003193601126101065780519082845460018160011c9060018316928315610251575b602093848410811461023e5783885290811561022257506001146101cd575b505050829003601f01601f191682019267ffffffffffffffff8411838510176101ba57508291826101b6925282610783565b0390f35b634e487b7160e01b815260418552602490fd5b8787529192508591837f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b83851061020e5750505050830101858080610184565b8054888601830152930192849082016101f8565b60ff1916878501525050151560051b8401019050858080610184565b634e487b7160e01b895260228a52602489fd5b91607f1691610165565b83346102c45760203660031901126102c4576102756107cc565b600554906001600160a01b03600883901c811690338290036102c0578216146102bc57610100600160a81b031990911660089190911b610100600160a81b03161760055580f35b8280fd5b8480fd5b80fd5b5050346101065760203660031901126101065760209181906001600160a01b036102ef6107cc565b16815280845220549051908152f35b839150346101065782600319360112610106576103196107cc565b6005549091602435916001600160a01b039060081c811633036102c05783169283156103cb578385528460205285852054918383106103975750508184957fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef936020938688528785520381872055816002540360025551908152a380f35b865163391434e360e21b81526001600160a01b03909216908201908152602081018390526040810184905281906060010390fd5b8551634b637e8f60e11b8152808301869052602490fd5b919050346102bc57806003193601126102bc576103fd6107cc565b60055460243592916001600160a01b039160081c8216330361049957169283156104845760025490838201809211610471575084927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9260209260025585855284835280852082815401905551908152a380f35b634e487b7160e01b865260119052602485fd5b84602492519163ec442f0560e01b8352820152fd5b8580fd5b50503461010657816003193601126101065760209060ff600554169051908152f35b905082346102c45760603660031901126102c4576104db6107cc565b6104e36107e7565b916044359360018060a01b03831680835260016020528683203384526020528683205491600019830361051f575b6020886101338989896107fd565b8683106105875781156105705733156105595750825260016020908152868320338452815291869020908590039055829061013387610511565b8751634a1406b160e11b8152908101849052602490fd5b875163e602df0560e01b8152908101849052602490fd5b8751637dc7a0d960e11b8152339181019182526020820193909352604081018790528291506060010390fd5b5050346101065781600319360112610106576020906002549051908152f35b505034610106578160031936011261010657600554905160089190911c6001600160a01b03168152602090f35b9050346102bc57816003193601126102bc576106196107cc565b602435903315610692576001600160a01b031691821561067b57508083602095338152600187528181208582528752205582519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b8351634a1406b160e11b8152908101859052602490fd5b835163e602df0560e01b8152808401869052602490fd5b849084346102bc57826003193601126102bc578260035460018160011c9060018316928315610779575b602093848410811461023e57838852908115610222575060011461072357505050829003601f01601f191682019267ffffffffffffffff8411838510176101ba57508291826101b6925282610783565b600387529192508591837fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b8385106107655750505050830101858080610184565b80548886018301529301928490820161074f565b91607f16916106d3565b6020808252825181830181905290939260005b8281106107b857505060409293506000838284010152601f8019910116010190565b818101860151848201604001528501610796565b600435906001600160a01b03821682036107e257565b600080fd5b602435906001600160a01b03821682036107e257565b916001600160a01b038084169283156108c257169283156108a95760009083825281602052604082205490838210610877575091604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652828652038282205586815220818154019055604051908152a3565b60405163391434e360e21b81526001600160a01b03919091166004820152602481019190915260448101839052606490fd5b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fdfea264697066735822122089a573821c2020ff2c4270490485e0549a8a5f167da54ba302482d6500b636af64736f6c63430008180033a2646970667358221220a753d77d4cf6c0fa34f5201bd7332c8f8836d599151cbd49d0b431208df781e364736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b000000000000000000000000000000000000000000000000305d3509223c80000000000000000000000000000000000000000000000000000000000000007668000000000000000000000000883ba282d409e0e984bef70b338f641d0045942f
-----Decoded View---------------
Arg [0] : _endpoint (address): 0x6F475642a6e85809B1c36Fa62763669b1b48DD5B
Arg [1] : _paramBridgeFee (uint256): 3485000000000000000
Arg [2] : _paramChainId (uint32): 30312
Arg [3] : _paramOmnifyAddress (address): 0x883bA282D409e0E984Bef70B338f641D0045942F
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b
Arg [1] : 000000000000000000000000000000000000000000000000305d3509223c8000
Arg [2] : 0000000000000000000000000000000000000000000000000000000000007668
Arg [3] : 000000000000000000000000883ba282d409e0e984bef70b338f641d0045942f
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.