Source Code
Overview
ETH Balance
0.000197486995666487 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 25 from a total of 924 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Execute | 7263422 | 2 hrs ago | IN | 0 ETH | 0.00036322 | ||||
Execute | 7263214 | 3 hrs ago | IN | 0 ETH | 0.00048491 | ||||
Execute | 7263214 | 3 hrs ago | IN | 0 ETH | 0.00046706 | ||||
Execute | 7263188 | 3 hrs ago | IN | 0 ETH | 0.00061247 | ||||
Execute | 7263188 | 3 hrs ago | IN | 0 ETH | 0.00061242 | ||||
Execute | 7263131 | 3 hrs ago | IN | 0 ETH | 0.00072056 | ||||
Execute | 7262818 | 4 hrs ago | IN | 0 ETH | 0.00170657 | ||||
Execute | 7262404 | 6 hrs ago | IN | 0 ETH | 0.00065107 | ||||
Execute | 7261799 | 8 hrs ago | IN | 0 ETH | 0.00823244 | ||||
Execute | 7261684 | 8 hrs ago | IN | 0 ETH | 0.00024717 | ||||
Execute | 7261591 | 8 hrs ago | IN | 0 ETH | 0.00015819 | ||||
Execute | 7261556 | 9 hrs ago | IN | 0 ETH | 0.00001326 | ||||
Execute | 7261556 | 9 hrs ago | IN | 0 ETH | 0.00001376 | ||||
Execute | 7260964 | 11 hrs ago | IN | 0 ETH | 0.00015807 | ||||
Execute | 7260167 | 13 hrs ago | IN | 0 ETH | 0.0001639 | ||||
Execute | 7260140 | 14 hrs ago | IN | 0 ETH | 0.00018345 | ||||
Execute | 7259055 | 17 hrs ago | IN | 0 ETH | 0.00070649 | ||||
Execute | 7258732 | 19 hrs ago | IN | 0 ETH | 0.00087786 | ||||
Execute | 7256833 | 25 hrs ago | IN | 0 ETH | 0.00910454 | ||||
Execute | 7255804 | 29 hrs ago | IN | 0 ETH | 0.00302358 | ||||
Execute | 7255199 | 31 hrs ago | IN | 0 ETH | 0.00018878 | ||||
Execute | 7255170 | 31 hrs ago | IN | 0 ETH | 0.00022903 | ||||
Execute | 7252755 | 40 hrs ago | IN | 0 ETH | 0.00226767 | ||||
Execute | 7250812 | 46 hrs ago | IN | 0 ETH | 0.01953026 | ||||
Execute | 7250387 | 2 days ago | IN | 0 ETH | 0.00316046 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
7262730 | 4 hrs ago | 0.00271542 ETH | ||||
7262730 | 4 hrs ago | 0.00271542 ETH | ||||
7261091 | 10 hrs ago | 0.00271542 ETH | ||||
7261091 | 10 hrs ago | 0.00271542 ETH | ||||
7260847 | 11 hrs ago | 0.0081719 ETH | ||||
7260847 | 11 hrs ago | 0.04415181 ETH | ||||
7260847 | 11 hrs ago | 0.04415181 ETH | ||||
7260845 | 11 hrs ago | 0.0081719 ETH | ||||
7260845 | 11 hrs ago | 0.04415181 ETH | ||||
7260845 | 11 hrs ago | 0.04415181 ETH | ||||
7260424 | 13 hrs ago | 0.0081719 ETH | ||||
7260424 | 13 hrs ago | 0.01078944 ETH | ||||
7260424 | 13 hrs ago | 0.01078944 ETH | ||||
7260064 | 14 hrs ago | 0.00544793 ETH | ||||
7260064 | 14 hrs ago | 0.00544793 ETH | ||||
7260025 | 14 hrs ago | 0.00544793 ETH | ||||
7260025 | 14 hrs ago | 0.00544793 ETH | ||||
7259162 | 17 hrs ago | 0.00271542 ETH | ||||
7259162 | 17 hrs ago | 0.00271542 ETH | ||||
7259041 | 17 hrs ago | 0.00271542 ETH | ||||
7259041 | 17 hrs ago | 0.00271542 ETH | ||||
7258390 | 20 hrs ago | 0.00549915 ETH | ||||
7258390 | 20 hrs ago | 0.00549915 ETH | ||||
7258136 | 21 hrs ago | 0.00271542 ETH | ||||
7258136 | 21 hrs ago | 0.00271542 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
SynthrBridgeLightChainAxelar
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.24; import "./BaseBridgeAxelar.sol"; import "../../interfaces/ISynthrIssuer.sol"; import "../../interfaces/IExchanger.sol"; import "../../interfaces/IWrappedSynthr.sol"; import "../../libraries/BytesLib.sol"; /** * @title SynthrBridgeLightChainAxelar * @dev Bridge contract for cross-chain communication using Axelar in the Synthr protocol */ contract SynthrBridgeLightChainAxelar is BaseBridgeAxelar { using BytesLib for bytes; error source_chainID_lookup_not_set(); error Call_from_invalid_source(); error Bridging_on_same_chain(); error Margin_delta_zero(); error Unknown_packetType(uint16 packetType); /** * @dev Constructor to initialize the SynthrBridgeLightChainAxelar contract. * @param _selfAxelarGateway Address of the Axelar gateway contract * @param _selfGasReceiver Address of the gas receiver contract */ constructor(address _selfAxelarGateway, address _selfGasReceiver) BaseBridgeAxelar(_selfAxelarGateway, _selfGasReceiver) { lzFeePercentage = 100; } /** * @notice Get the main chain ID * @return The main chain ID */ function mainChainId() external view returns (uint16) { return _mainChainId; } /** * @notice Initialize the contract with the given parameters * @param __synthrAddressResolver The address resolver for Synthr * @param __mainChainId The ID of the main chain * @param __selfChainId The ID of the current chain */ function initialize( address __synthrAddressResolver, uint16 __mainChainId, uint16 __selfChainId ) external onlyOwner { _mainChainId = __mainChainId; _synthrAddressResolver = __synthrAddressResolver; _selfChainId = __selfChainId; } function _execute( string calldata _sourceChain, string calldata _sourceAddress, bytes calldata _payload ) internal override { uint16 srcChainID = srcChainIdLookup[_sourceChain]; if (srcChainID == 0) { revert source_chainID_lookup_not_set(); } AxelarChainInfo memory axelarChainInfo = axelarDstChainLookup[srcChainID]; // destination chain can also be source for mainchain bridge (while call from lightchain -> mainchain bridge) if ( keccak256(abi.encodePacked(_sourceAddress)) != keccak256(abi.encodePacked(axelarChainInfo.dstChainAddress)) && keccak256(abi.encodePacked(_sourceChain)) != keccak256(abi.encodePacked(axelarChainInfo.dstChainName)) ) { revert Call_from_invalid_source(); } _receiveCall(srcChainID, _payload); } function _receiveCall(uint16 _srcChainId, bytes memory _payload) internal { uint16 packetType; assembly { packetType := mload(add(_payload, 32)) } address account; if (packetType == PT_MINT_SYNTH) { // receive mint synth message // from only the main chain (, bytes memory accountBytes, bytes32 synthKey, uint amount) = abi.decode(_payload, (uint16, bytes, bytes32, uint)); account = accountBytes.toAddress(0); ISynthrIssuer(getAddressFromResolver("Issuer")).destIssue(account, synthKey, amount); } else if (packetType == PT_WITHDRAW_COLLATERAL) { // withdraw collateral message // from only the main chain (, bytes memory accountBytes, bytes32 collateralKey, uint amount) = abi.decode(_payload, (uint16, bytes, bytes32, uint)); account = accountBytes.toAddress(0); IWrappedSynthr(getAddressFromResolver("WrappedSynthr")).withdrawCollateral(account, account, collateralKey, amount); } else if (packetType == PT_EXCHANGE) { // exchange syTokens // from every chain (, bytes memory accountBytes, , , bytes32 destKey, uint destAmount, ) = abi.decode(_payload, (uint16, bytes, bytes32, uint, bytes32, uint, uint)); account = accountBytes.toAddress(0); IExchanger(getAddressFromResolver("Exchanger")).updateDestinationForExchange(account, destKey, destAmount); } else if (packetType == PT_LIQUIDATE) { // liquidate collateral // message from only the main chain (, bytes memory accountBytes, bytes32 collateralKey, uint collateralAmount) = abi.decode(_payload, (uint16, bytes, bytes32, uint)); account = accountBytes.toAddress(0); IWrappedSynthr(getAddressFromResolver("WrappedSynthr")).collateralTransfer(account, collateralKey, collateralAmount); } else if (packetType == PT_BRIDGE_SYNTH) { // bridge syToken // message from every chain (, bytes memory accountBytes, bytes32 synthKey, uint amount) = abi.decode(_payload, (uint16, bytes, bytes32, uint)); account = accountBytes.toAddress(0); ISynthrIssuer(getAddressFromResolver("Issuer")).destIssue(account, synthKey, amount); } else if (packetType == PT_WITHDRAW_MARGIN) { (, bytes memory accountBytes, uint amount) = abi.decode(_payload, (uint16, bytes, uint)); account = accountBytes.toAddress(0); // bytes32("sUSD") = 0x7355534400000000000000000000000000000000000000000000000000000000 ISynthrIssuer(getAddressFromResolver("Issuer")).destIssue(account, 0x7355534400000000000000000000000000000000000000000000000000000000, amount); } else if (packetType == PT_CROSS_SWAP_CASE_1) { ( , bytes memory accountBytes, bytes32 srcKey, uint srcAmount, bytes32 dstKey, uint dstAmount, // uint16 dstChainId // uint fee , , bytes memory dexPayload, bytes memory dexAddressBytes ) = abi.decode(_payload, (uint16, bytes, bytes32, uint, bytes32, uint, uint16, uint, bytes, bytes)); account = accountBytes.toAddress(0); address dexAddress = dexAddressBytes.toAddress(0); ISynthrSwap(getAddressFromResolver("SynthrSwap")).destSwapSynthToNative(account, srcKey, srcAmount, dstKey, dstAmount, dexAddress, dexPayload); } else if (packetType == PT_CROSS_SWAP_CASE_2) { ( , bytes memory accountBytes, bytes32 srcKey, uint srcAmount, bytes32 dstKey, uint dstAmount, // uint16 dstChainId // uint fee , ) = abi.decode(_payload, (uint16, bytes, bytes32, uint, bytes32, uint, uint16, uint)); account = accountBytes.toAddress(0); ISynthrSwap(getAddressFromResolver("SynthrSwap")).destSwapNativeToSynth(account, srcKey, srcAmount, dstKey, dstAmount); } else if (packetType == PT_CROSS_SWAP_CASE_3) { ( , bytes memory accountBytes, bytes32 srcKey, uint srcAmount, bytes32 dstKey, uint dstAmount, // uint16 dstChainId // uint fee, , , bytes memory dexPayload, bytes memory dexAddressBytes ) = abi.decode(_payload, (uint16, bytes, bytes32, uint, bytes32, uint, uint16, uint, bytes, bytes)); account = accountBytes.toAddress(0); address dexAddress = dexAddressBytes.toAddress(0); ISynthrSwap(getAddressFromResolver("SynthrSwap")).destSwapNativeToNative(account, srcKey, srcAmount, dstKey, dstAmount, dexAddress, dexPayload); } else if (packetType == PT_CROSS_SWAP_DEX_CASE_1) { ( , bytes memory accountBytes, bytes32 srcKey, uint srcAmount, bytes32 dstKey, uint dstAmount, //uint16 dstChainId // uint fee , ) = abi.decode(_payload, (uint16, bytes, bytes32, uint, bytes32, uint, uint16, uint)); account = accountBytes.toAddress(0); ISynthrSwapDex(getAddressFromResolver("SynthrSwapWithDex")).destSwapSynthToNative(account, srcKey, srcAmount, dstKey, dstAmount); } else if (packetType == PT_CROSS_SWAP_DEX_CASE_3) { ( , bytes memory accountBytes, bytes32 srcKey, uint srcAmount, bytes32 dstKey, uint dstAmount, // uint16 dstChainId // uint fee , ) = abi.decode(_payload, (uint16, bytes, bytes32, uint, bytes32, uint, uint16, uint)); account = accountBytes.toAddress(0); ISynthrSwapDex(getAddressFromResolver("SynthrSwapWithDex")).destSwapNativeToNative(account, srcKey, srcAmount, dstKey, dstAmount); } else { revert Unknown_packetType(packetType); } { emit ReceiveMsg(account, packetType, _srcChainId); } } // send a message to only the main chain /** * @notice Send a deposit collateral message to the main chain * @param account The account depositing collateral * @param collateralKey The key representing the collateral * @param amount The amount of collateral to deposit * Boolean indicating if ZRO token payment is used for LayerZero fee */ function sendDepositCollateral( address account, bytes32 collateralKey, uint amount, bool // the param to check ZRO token payment - true: ZRO token payment for LZ fee, false: native token payment for LZ fee ) external payable onlySynthr { bytes memory lzPayload = abi.encode(PT_DEPOSIT_COLLATERAL, abi.encodePacked(account), collateralKey, amount); _broadcast(account, lzPayload, PT_DEPOSIT_COLLATERAL, _mainChainId, msg.value, false); } /** * @notice Send a burn synth message to the main chain * @param account The account burning synth tokens * @param synthKey The key representing the synth token * @param amount The amount of synth tokens to burn * Boolean indicating if ZRO token payment is used for LayerZero fee */ function sendBurn( address account, bytes32 synthKey, uint amount, bool // the param to check ZRO token payment - true: ZRO token payment for LZ fee, false: native token payment for LZ fee ) external payable onlySynthr { bytes memory lzPayload = abi.encode(PT_BURN_SYNTH, abi.encodePacked(account), synthKey, amount); _broadcast(account, lzPayload, PT_BURN_SYNTH, _mainChainId, msg.value, false); } // send a message to the dest chain and main chain function sendExchange( address account, bytes32 srcSynthKey, bytes32 dstSynthKey, uint srcAmount, uint dstAmount, uint reclaimed, uint refund, uint fee, uint16 dstChainId, bool // the param to check ZRO token payment - true: ZRO token payment for LZ fee, false: native token payment for LZ fee ) external payable onlySynthr { srcAmount += reclaimed - refund; if (dstChainId == 0) { dstChainId = _selfChainId; } bytes memory lzPayload = abi.encode(PT_EXCHANGE, abi.encodePacked(account), srcSynthKey, srcAmount, dstSynthKey, dstAmount, fee, dstChainId); uint value = msg.value; if (dstChainId != _selfChainId) { uint consumed = _broadcast(account, lzPayload, PT_EXCHANGE, dstChainId, value, false); value -= consumed; } if (dstChainId != _mainChainId) { _broadcast(account, lzPayload, PT_EXCHANGE, _mainChainId, value, false); } } /** * @notice Send a bridge synth token message to the destination chain * @param account The account bridging synth tokens * @param synthKey The key representing the synth token * @param amount The amount of synth tokens to bridge * @param dstChainId The destination chain ID * Boolean indicating if ZRO token payment is used for LayerZero fee */ function sendBridgeSyToken( address account, bytes32 synthKey, uint amount, uint16 dstChainId, bool // the param to check ZRO token payment - true: ZRO token payment for LZ fee, false: native token payment for LZ fee ) external payable onlySynthr { if (dstChainId == 0) { revert Bridging_on_same_chain(); } bytes memory lzPayload = abi.encode(PT_BRIDGE_SYNTH, abi.encodePacked(account), synthKey, amount, dstChainId); uint value = msg.value; uint consumed = _broadcast(account, lzPayload, PT_BRIDGE_SYNTH, dstChainId, value, false); value -= consumed; if (dstChainId != _mainChainId) { _broadcast(account, lzPayload, PT_BRIDGE_SYNTH, _mainChainId, value, false); } } // This function is on only the light chain as we don't need to bridge `transfer margin` message to the other chain /** * @notice Send a transfer margin message to the main chain * @param account The account transferring margin * @param marginDelta The amount of margin to transfer * @param marketKey The key representing the market * Boolean indicating if ZRO token payment is used for LayerZero fee */ function sendTransferMargin( address account, uint marginDelta, bytes32 marketKey, bool // the param to check ZRO token payment - true: ZRO token payment for LZ fee, false: native token payment for LZ fee ) external payable onlySynthr { if (marginDelta == 0) { revert Margin_delta_zero(); } bytes memory lzPayload = abi.encode(PT_TRANSFER_MARGIN, abi.encodePacked(account), marginDelta, marketKey); _broadcast(account, lzPayload, PT_TRANSFER_MARGIN, _mainChainId, msg.value, false); } // TODO // DO we need to check the hash of the dexPayload? /** * @notice Send a cross-chain swap from synth to native asset * @param account The account performing the swap * @param srcKey The key representing the source synth token * @param srcAmount The amount of source synth tokens * @param dstKey The key representing the destination native asset * @param dstAmount The amount of destination native asset * @param dstChainId The destination chain ID * @param fee The fee for the swap * @param dexPayload The payload data for the DEX * @param dexAddress The address of the DEX * Boolean indicating if ZRO token payment is used for LayerZero fee */ function sendCrossSwapSyAssetToNative( address account, bytes32 srcKey, uint srcAmount, bytes32 dstKey, uint dstAmount, uint16 dstChainId, uint fee, bytes calldata dexPayload, address dexAddress, bool // the param to check ZRO token payment - true: ZRO token payment for LZ fee, false: native token payment for LZ fee ) external payable onlySynthr { bytes memory lzPayload = abi.encode( PT_CROSS_SWAP_CASE_1, abi.encodePacked(account), srcKey, srcAmount, dstKey, dstAmount, dstChainId, fee, dexPayload, abi.encodePacked(dexAddress) ); uint value = msg.value; uint consumed = _broadcast(account, lzPayload, PT_CROSS_SWAP_CASE_1, _mainChainId, msg.value, false); value -= consumed; // to the light chain if (dstChainId != _mainChainId) { _broadcast(account, lzPayload, PT_CROSS_SWAP_CASE_1, dstChainId, value, false); } } /** * @notice Send a cross-chain swap from native asset to synth * @param account The account performing the swap * @param srcKey The key representing the source native asset * @param srcAmount The amount of source native asset * @param dstKey The key representing the destination synth token * @param dstAmount The amount of destination synth tokens * @param dstChainId The destination chain ID * @param fee The fee for the swap * Boolean indicating if ZRO token payment is used for LayerZero fee */ function sendCrossSwapNativeToSyAsset( address account, bytes32 srcKey, uint srcAmount, bytes32 dstKey, uint dstAmount, uint16 dstChainId, uint fee, bool // the param to check ZRO token payment - true: ZRO token payment for LZ fee, false: native token payment for LZ fee ) external payable onlySynthr { bytes memory lzPayload = abi.encode(PT_CROSS_SWAP_CASE_2, abi.encodePacked(account), srcKey, srcAmount, dstKey, dstAmount, dstChainId, fee); uint value = msg.value; uint consumed = _broadcast(account, lzPayload, PT_CROSS_SWAP_CASE_2, _mainChainId, msg.value, false); value -= consumed; if (dstChainId != _mainChainId) { _broadcast(account, lzPayload, PT_CROSS_SWAP_CASE_2, dstChainId, value, false); } } /** * @notice Send a cross-chain swap from native asset to native asset * @param account The account performing the swap * @param srcKey The key representing the source native asset * @param srcAmount The amount of source native asset * @param dstKey The key representing the destination native asset * @param dstAmount The amount of destination native asset * @param dstChainId The destination chain ID * @param fee The fee for the swap * @param dexAddress The address of the DEX * @param dexPayload The payload data for the DEX * Boolean indicating if ZRO token payment is used for LayerZero fee */ function sendCrossSwapNativeToNative( address account, bytes32 srcKey, uint srcAmount, bytes32 dstKey, uint dstAmount, uint16 dstChainId, uint fee, address dexAddress, bytes calldata dexPayload, bool // the param to check ZRO token payment - true: ZRO token payment for LZ fee, false: native token payment for LZ fee ) external payable onlySynthr { bytes memory lzPayload = abi.encode( PT_CROSS_SWAP_CASE_3, abi.encodePacked(account), srcKey, srcAmount, dstKey, dstAmount, dstChainId, fee, dexPayload, abi.encodePacked(dexAddress) ); uint value = msg.value; uint consumed = _broadcast(account, lzPayload, PT_CROSS_SWAP_CASE_3, _mainChainId, value, false); value -= consumed; if (dstChainId != _mainChainId) { _broadcast(account, lzPayload, PT_CROSS_SWAP_CASE_3, dstChainId, value, false); } } /** * @notice Send a cross-chain swap from synth to native asset using a DEX * @param account The account performing the swap * @param srcKey The key representing the source synth token * @param srcAmount The amount of source synth tokens * @param dstKey The key representing the destination native asset * @param dstAmount The amount of destination native asset * @param dstChainId The destination chain ID * @param fee The fee for the swap * Boolean indicating if ZRO token payment is used for LayerZero fee */ function sendCrossSwapSyAssetToNativeWithDex( address account, bytes32 srcKey, uint srcAmount, bytes32 dstKey, uint dstAmount, uint16 dstChainId, uint fee, bool // the param to check ZRO token payment - true: ZRO token payment for LZ fee, false: native token payment for LZ fee ) external payable onlySynthr { bytes memory lzPayload = abi.encode(PT_CROSS_SWAP_DEX_CASE_1, abi.encodePacked(account), srcKey, srcAmount, dstKey, dstAmount, dstChainId, fee); uint value = msg.value; uint consumed = _broadcast(account, lzPayload, PT_CROSS_SWAP_DEX_CASE_1, _mainChainId, msg.value, false); value -= consumed; // to the light chain if (dstChainId != _mainChainId) { _broadcast(account, lzPayload, PT_CROSS_SWAP_DEX_CASE_1, dstChainId, value, false); } } /** * @notice Send a cross-chain swap from native asset to native asset using a DEX * @param account The account performing the swap * @param srcKey The key representing the source native asset * @param srcAmount The amount of source native asset * @param dstKey The key representing the destination native asset * @param dstAmount The amount of destination native asset * @param dstChainId The destination chain ID * @param fee The fee for the swap * Boolean indicating if ZRO token payment is used for LayerZero fee */ function sendCrossSwapNativeToNativeWithDex( address account, bytes32 srcKey, uint srcAmount, bytes32 dstKey, uint dstAmount, uint16 dstChainId, uint fee, bool // the param to check ZRO token payment - true: ZRO token payment for LZ fee, false: native token payment for LZ fee ) external payable onlySynthr { bytes memory lzPayload = abi.encode(PT_CROSS_SWAP_DEX_CASE_3, abi.encodePacked(account), srcKey, srcAmount, dstKey, dstAmount, dstChainId, fee); uint value = msg.value; uint consumed = _broadcast(account, lzPayload, PT_CROSS_SWAP_DEX_CASE_3, _mainChainId, value, false); value -= consumed; if (dstChainId != _mainChainId) { _broadcast(account, lzPayload, PT_CROSS_SWAP_DEX_CASE_3, dstChainId, value, false); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IAxelarGateway } from '../interfaces/IAxelarGateway.sol'; import { IAxelarExecutable } from '../interfaces/IAxelarExecutable.sol'; contract AxelarExecutable is IAxelarExecutable { IAxelarGateway public immutable gateway; constructor(address gateway_) { if (gateway_ == address(0)) revert InvalidAddress(); gateway = IAxelarGateway(gateway_); } function execute( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes calldata payload ) external { bytes32 payloadHash = keccak256(payload); if (!gateway.validateContractCall(commandId, sourceChain, sourceAddress, payloadHash)) revert NotApprovedByGateway(); _execute(sourceChain, sourceAddress, payload); } function executeWithToken( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, string calldata tokenSymbol, uint256 amount ) external { bytes32 payloadHash = keccak256(payload); if ( !gateway.validateContractCallAndMint( commandId, sourceChain, sourceAddress, payloadHash, tokenSymbol, amount ) ) revert NotApprovedByGateway(); _executeWithToken(sourceChain, sourceAddress, payload, tokenSymbol, amount); } function _execute( string calldata sourceChain, string calldata sourceAddress, bytes calldata payload ) internal virtual {} function _executeWithToken( string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, string calldata tokenSymbol, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IAxelarGateway } from './IAxelarGateway.sol'; interface IAxelarExecutable { error InvalidAddress(); error NotApprovedByGateway(); function gateway() external view returns (IAxelarGateway); function execute( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes calldata payload ) external; function executeWithToken( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, string calldata tokenSymbol, uint256 amount ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IInterchainGasEstimation } from './IInterchainGasEstimation.sol'; import { IUpgradable } from './IUpgradable.sol'; /** * @title IAxelarGasService Interface * @notice This is an interface for the AxelarGasService contract which manages gas payments * and refunds for cross-chain communication on the Axelar network. * @dev This interface inherits IUpgradable */ interface IAxelarGasService is IInterchainGasEstimation, IUpgradable { error InvalidAddress(); error NotCollector(); error InvalidAmounts(); error InvalidGasUpdates(); error InsufficientGasPayment(uint256 required, uint256 provided); event GasPaidForContractCall( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, address gasToken, uint256 gasFeeAmount, address refundAddress ); event GasPaidForContractCallWithToken( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, address gasToken, uint256 gasFeeAmount, address refundAddress ); event NativeGasPaidForContractCall( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, uint256 gasFeeAmount, address refundAddress ); event NativeGasPaidForContractCallWithToken( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, uint256 gasFeeAmount, address refundAddress ); event GasPaidForExpressCall( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, address gasToken, uint256 gasFeeAmount, address refundAddress ); event GasPaidForExpressCallWithToken( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, address gasToken, uint256 gasFeeAmount, address refundAddress ); event NativeGasPaidForExpressCall( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, uint256 gasFeeAmount, address refundAddress ); event NativeGasPaidForExpressCallWithToken( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, uint256 gasFeeAmount, address refundAddress ); event GasAdded( bytes32 indexed txHash, uint256 indexed logIndex, address gasToken, uint256 gasFeeAmount, address refundAddress ); event NativeGasAdded(bytes32 indexed txHash, uint256 indexed logIndex, uint256 gasFeeAmount, address refundAddress); event ExpressGasAdded( bytes32 indexed txHash, uint256 indexed logIndex, address gasToken, uint256 gasFeeAmount, address refundAddress ); event NativeExpressGasAdded( bytes32 indexed txHash, uint256 indexed logIndex, uint256 gasFeeAmount, address refundAddress ); event Refunded( bytes32 indexed txHash, uint256 indexed logIndex, address payable receiver, address token, uint256 amount ); /** * @notice Pay for gas for any type of contract execution on a destination chain. * @dev This function is called on the source chain before calling the gateway to execute a remote contract. * @dev If estimateOnChain is true, the function will estimate the gas cost and revert if the payment is insufficient. * @param sender The address making the payment * @param destinationChain The target chain where the contract call will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call * @param executionGasLimit The gas limit for the contract call * @param estimateOnChain Flag to enable on-chain gas estimation * @param refundAddress The address where refunds, if any, should be sent * @param params Additional parameters for gas payment. This can be left empty for normal contract call payments. */ function payGas( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, uint256 executionGasLimit, bool estimateOnChain, address refundAddress, bytes calldata params ) external payable; /** * @notice Pay for gas using ERC20 tokens for a contract call on a destination chain. * @dev This function is called on the source chain before calling the gateway to execute a remote contract. * @param sender The address making the payment * @param destinationChain The target chain where the contract call will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call * @param gasToken The address of the ERC20 token used to pay for gas * @param gasFeeAmount The amount of tokens to pay for gas * @param refundAddress The address where refunds, if any, should be sent */ function payGasForContractCall( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, address gasToken, uint256 gasFeeAmount, address refundAddress ) external; /** * @notice Pay for gas using ERC20 tokens for a contract call with tokens on a destination chain. * @dev This function is called on the source chain before calling the gateway to execute a remote contract. * @param sender The address making the payment * @param destinationChain The target chain where the contract call with tokens will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call with tokens * @param symbol The symbol of the token to be sent with the call * @param amount The amount of tokens to be sent with the call * @param gasToken The address of the ERC20 token used to pay for gas * @param gasFeeAmount The amount of tokens to pay for gas * @param refundAddress The address where refunds, if any, should be sent */ function payGasForContractCallWithToken( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, string calldata symbol, uint256 amount, address gasToken, uint256 gasFeeAmount, address refundAddress ) external; /** * @notice Pay for gas using native currency for a contract call on a destination chain. * @dev This function is called on the source chain before calling the gateway to execute a remote contract. * @param sender The address making the payment * @param destinationChain The target chain where the contract call will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call * @param refundAddress The address where refunds, if any, should be sent */ function payNativeGasForContractCall( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, address refundAddress ) external payable; /** * @notice Pay for gas using native currency for a contract call with tokens on a destination chain. * @dev This function is called on the source chain before calling the gateway to execute a remote contract. * @param sender The address making the payment * @param destinationChain The target chain where the contract call with tokens will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call with tokens * @param symbol The symbol of the token to be sent with the call * @param amount The amount of tokens to be sent with the call * @param refundAddress The address where refunds, if any, should be sent */ function payNativeGasForContractCallWithToken( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, string calldata symbol, uint256 amount, address refundAddress ) external payable; /** * @notice Pay for gas using ERC20 tokens for an express contract call on a destination chain. * @dev This function is called on the source chain before calling the gateway to express execute a remote contract. * @param sender The address making the payment * @param destinationChain The target chain where the contract call will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call * @param gasToken The address of the ERC20 token used to pay for gas * @param gasFeeAmount The amount of tokens to pay for gas * @param refundAddress The address where refunds, if any, should be sent */ function payGasForExpressCall( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, address gasToken, uint256 gasFeeAmount, address refundAddress ) external; /** * @notice Pay for gas using ERC20 tokens for an express contract call with tokens on a destination chain. * @dev This function is called on the source chain before calling the gateway to express execute a remote contract. * @param sender The address making the payment * @param destinationChain The target chain where the contract call with tokens will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call with tokens * @param symbol The symbol of the token to be sent with the call * @param amount The amount of tokens to be sent with the call * @param gasToken The address of the ERC20 token used to pay for gas * @param gasFeeAmount The amount of tokens to pay for gas * @param refundAddress The address where refunds, if any, should be sent */ function payGasForExpressCallWithToken( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, string calldata symbol, uint256 amount, address gasToken, uint256 gasFeeAmount, address refundAddress ) external; /** * @notice Pay for gas using native currency for an express contract call on a destination chain. * @dev This function is called on the source chain before calling the gateway to execute a remote contract. * @param sender The address making the payment * @param destinationChain The target chain where the contract call will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call * @param refundAddress The address where refunds, if any, should be sent */ function payNativeGasForExpressCall( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, address refundAddress ) external payable; /** * @notice Pay for gas using native currency for an express contract call with tokens on a destination chain. * @dev This function is called on the source chain before calling the gateway to execute a remote contract. * @param sender The address making the payment * @param destinationChain The target chain where the contract call with tokens will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call with tokens * @param symbol The symbol of the token to be sent with the call * @param amount The amount of tokens to be sent with the call * @param refundAddress The address where refunds, if any, should be sent */ function payNativeGasForExpressCallWithToken( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, string calldata symbol, uint256 amount, address refundAddress ) external payable; /** * @notice Add additional gas payment using ERC20 tokens after initiating a cross-chain call. * @dev This function can be called on the source chain after calling the gateway to execute a remote contract. * @param txHash The transaction hash of the cross-chain call * @param logIndex The log index for the cross-chain call * @param gasToken The ERC20 token address used to add gas * @param gasFeeAmount The amount of tokens to add as gas * @param refundAddress The address where refunds, if any, should be sent */ function addGas( bytes32 txHash, uint256 logIndex, address gasToken, uint256 gasFeeAmount, address refundAddress ) external; /** * @notice Add additional gas payment using native currency after initiating a cross-chain call. * @dev This function can be called on the source chain after calling the gateway to execute a remote contract. * @param txHash The transaction hash of the cross-chain call * @param logIndex The log index for the cross-chain call * @param refundAddress The address where refunds, if any, should be sent */ function addNativeGas( bytes32 txHash, uint256 logIndex, address refundAddress ) external payable; /** * @notice Add additional gas payment using ERC20 tokens after initiating an express cross-chain call. * @dev This function can be called on the source chain after calling the gateway to express execute a remote contract. * @param txHash The transaction hash of the cross-chain call * @param logIndex The log index for the cross-chain call * @param gasToken The ERC20 token address used to add gas * @param gasFeeAmount The amount of tokens to add as gas * @param refundAddress The address where refunds, if any, should be sent */ function addExpressGas( bytes32 txHash, uint256 logIndex, address gasToken, uint256 gasFeeAmount, address refundAddress ) external; /** * @notice Add additional gas payment using native currency after initiating an express cross-chain call. * @dev This function can be called on the source chain after calling the gateway to express execute a remote contract. * @param txHash The transaction hash of the cross-chain call * @param logIndex The log index for the cross-chain call * @param refundAddress The address where refunds, if any, should be sent */ function addNativeExpressGas( bytes32 txHash, uint256 logIndex, address refundAddress ) external payable; /** * @notice Updates the gas price for a specific chain. * @dev This function is called by the gas oracle to update the gas prices for a specific chains. * @param chains Array of chain names * @param gasUpdates Array of gas updates */ function updateGasInfo(string[] calldata chains, GasInfo[] calldata gasUpdates) external; /** * @notice Allows the gasCollector to collect accumulated fees from the contract. * @dev Use address(0) as the token address for native currency. * @param receiver The address to receive the collected fees * @param tokens Array of token addresses to be collected * @param amounts Array of amounts to be collected for each respective token address */ function collectFees( address payable receiver, address[] calldata tokens, uint256[] calldata amounts ) external; /** * @notice Refunds gas payment to the receiver in relation to a specific cross-chain transaction. * @dev Only callable by the gasCollector. * @dev Use address(0) as the token address to refund native currency. * @param txHash The transaction hash of the cross-chain call * @param logIndex The log index for the cross-chain call * @param receiver The address to receive the refund * @param token The token address to be refunded * @param amount The amount to refund */ function refund( bytes32 txHash, uint256 logIndex, address payable receiver, address token, uint256 amount ) external; /** * @notice Returns the address of the designated gas collector. * @return address of the gas collector */ function gasCollector() external returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IGovernable } from './IGovernable.sol'; import { IImplementation } from './IImplementation.sol'; interface IAxelarGateway is IImplementation, IGovernable { /**********\ |* Errors *| \**********/ error NotSelf(); error InvalidCodeHash(); error SetupFailed(); error InvalidAuthModule(); error InvalidTokenDeployer(); error InvalidAmount(); error InvalidChainId(); error InvalidCommands(); error TokenDoesNotExist(string symbol); error TokenAlreadyExists(string symbol); error TokenDeployFailed(string symbol); error TokenContractDoesNotExist(address token); error BurnFailed(string symbol); error MintFailed(string symbol); error InvalidSetMintLimitsParams(); error ExceedMintLimit(string symbol); /**********\ |* Events *| \**********/ event TokenSent( address indexed sender, string destinationChain, string destinationAddress, string symbol, uint256 amount ); event ContractCall( address indexed sender, string destinationChain, string destinationContractAddress, bytes32 indexed payloadHash, bytes payload ); event ContractCallWithToken( address indexed sender, string destinationChain, string destinationContractAddress, bytes32 indexed payloadHash, bytes payload, string symbol, uint256 amount ); event Executed(bytes32 indexed commandId); event TokenDeployed(string symbol, address tokenAddresses); event ContractCallApproved( bytes32 indexed commandId, string sourceChain, string sourceAddress, address indexed contractAddress, bytes32 indexed payloadHash, bytes32 sourceTxHash, uint256 sourceEventIndex ); event ContractCallApprovedWithMint( bytes32 indexed commandId, string sourceChain, string sourceAddress, address indexed contractAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, bytes32 sourceTxHash, uint256 sourceEventIndex ); event ContractCallExecuted(bytes32 indexed commandId); event TokenMintLimitUpdated(string symbol, uint256 limit); event OperatorshipTransferred(bytes newOperatorsData); event Upgraded(address indexed implementation); /********************\ |* Public Functions *| \********************/ function sendToken( string calldata destinationChain, string calldata destinationAddress, string calldata symbol, uint256 amount ) external; function callContract( string calldata destinationChain, string calldata contractAddress, bytes calldata payload ) external; function callContractWithToken( string calldata destinationChain, string calldata contractAddress, bytes calldata payload, string calldata symbol, uint256 amount ) external; function isContractCallApproved( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, address contractAddress, bytes32 payloadHash ) external view returns (bool); function isContractCallAndMintApproved( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, address contractAddress, bytes32 payloadHash, string calldata symbol, uint256 amount ) external view returns (bool); function validateContractCall( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes32 payloadHash ) external returns (bool); function validateContractCallAndMint( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes32 payloadHash, string calldata symbol, uint256 amount ) external returns (bool); /***********\ |* Getters *| \***********/ function authModule() external view returns (address); function tokenDeployer() external view returns (address); function tokenMintLimit(string memory symbol) external view returns (uint256); function tokenMintAmount(string memory symbol) external view returns (uint256); function allTokensFrozen() external view returns (bool); function implementation() external view returns (address); function tokenAddresses(string memory symbol) external view returns (address); function tokenFrozen(string memory symbol) external view returns (bool); function isCommandExecuted(bytes32 commandId) external view returns (bool); /************************\ |* Governance Functions *| \************************/ function setTokenMintLimits(string[] calldata symbols, uint256[] calldata limits) external; function upgrade( address newImplementation, bytes32 newImplementationCodeHash, bytes calldata setupParams ) external; /**********************\ |* External Functions *| \**********************/ function execute(bytes calldata input) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // General interface for upgradable contracts interface IContractIdentifier { /** * @notice Returns the contract ID. It can be used as a check during upgrades. * @dev Meant to be overridden in derived contracts. * @return bytes32 The contract ID */ function contractId() external pure returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title IGovernable Interface * @notice This is an interface used by the AxelarGateway contract to manage governance and mint limiter roles. */ interface IGovernable { error NotGovernance(); error NotMintLimiter(); error InvalidGovernance(); error InvalidMintLimiter(); event GovernanceTransferred(address indexed previousGovernance, address indexed newGovernance); event MintLimiterTransferred(address indexed previousGovernance, address indexed newGovernance); /** * @notice Returns the governance address. * @return address of the governance */ function governance() external view returns (address); /** * @notice Returns the mint limiter address. * @return address of the mint limiter */ function mintLimiter() external view returns (address); /** * @notice Transfer the governance role to another address. * @param newGovernance The new governance address */ function transferGovernance(address newGovernance) external; /** * @notice Transfer the mint limiter role to another address. * @param newGovernance The new mint limiter address */ function transferMintLimiter(address newGovernance) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IContractIdentifier } from './IContractIdentifier.sol'; interface IImplementation is IContractIdentifier { error NotProxy(); function setup(bytes calldata data) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title IInterchainGasEstimation Interface * @notice This is an interface for the InterchainGasEstimation contract * which allows for estimating gas fees for cross-chain communication on the Axelar network. */ interface IInterchainGasEstimation { error UnsupportedEstimationType(GasEstimationType gasEstimationType); /** * @notice Event emitted when the gas price for a specific chain is updated. * @param chain The name of the chain * @param info The gas info for the chain */ event GasInfoUpdated(string chain, GasInfo info); enum GasEstimationType { Default, OptimismEcotone } struct GasInfo { GasEstimationType gasEstimationType; // Custom gas pricing rule, such as L1 data fee on L2s uint128 axelarBaseFee; // axelar base fee for cross-chain message approval (in terms of src native gas token) uint128 expressFee; // axelar express fee for cross-chain message approval and express execution uint128 relativeGasPrice; // dest_gas_price * dest_token_market_price / src_token_market_price uint128 relativeBlobBaseFee; // dest_blob_base_fee * dest_token_market_price / src_token_market_price } /** * @notice Returns the gas price for a specific chain. * @param chain The name of the chain * @return gasInfo The gas info for the chain */ function getGasInfo(string calldata chain) external view returns (GasInfo memory); /** * @notice Estimates the gas fee for a cross-chain contract call. * @param destinationChain Axelar registered name of the destination chain * @param destinationAddress Destination contract address being called * @param executionGasLimit The gas limit to be used for the destination contract execution, * e.g. pass in 200k if your app consumes needs upto 200k for this contract call * @param params Additional parameters for the gas estimation * @return gasEstimate The cross-chain gas estimate, in terms of source chain's native gas token that should be forwarded to the gas service. */ function estimateGasFee( string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, uint256 executionGasLimit, bytes calldata params ) external view returns (uint256 gasEstimate); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title IOwnable Interface * @notice IOwnable is an interface that abstracts the implementation of a * contract with ownership control features. It's commonly used in upgradable * contracts and includes the functionality to get current owner, transfer * ownership, and propose and accept ownership. */ interface IOwnable { error NotOwner(); error InvalidOwner(); error InvalidOwnerAddress(); event OwnershipTransferStarted(address indexed newOwner); event OwnershipTransferred(address indexed newOwner); /** * @notice Returns the current owner of the contract. * @return address The address of the current owner */ function owner() external view returns (address); /** * @notice Returns the address of the pending owner of the contract. * @return address The address of the pending owner */ function pendingOwner() external view returns (address); /** * @notice Transfers ownership of the contract to a new address * @param newOwner The address to transfer ownership to */ function transferOwnership(address newOwner) external; /** * @notice Proposes to transfer the contract's ownership to a new address. * The new owner needs to accept the ownership explicitly. * @param newOwner The address to transfer ownership to */ function proposeOwnership(address newOwner) external; /** * @notice Transfers ownership to the pending owner. * @dev Can only be called by the pending owner */ function acceptOwnership() external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IOwnable } from './IOwnable.sol'; import { IImplementation } from './IImplementation.sol'; // General interface for upgradable contracts interface IUpgradable is IOwnable, IImplementation { error InvalidCodeHash(); error InvalidImplementation(); error SetupFailed(); event Upgraded(address indexed newImplementation); function implementation() external view returns (address); function upgrade( address newImplementation, bytes32 newImplementationCodeHash, bytes calldata params ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library StringToAddress { error InvalidAddressString(); function toAddress(string memory addressString) internal pure returns (address) { bytes memory stringBytes = bytes(addressString); uint160 addressNumber = 0; uint8 stringByte; if (stringBytes.length != 42 || stringBytes[0] != '0' || stringBytes[1] != 'x') revert InvalidAddressString(); for (uint256 i = 2; i < 42; ++i) { stringByte = uint8(stringBytes[i]); if ((stringByte >= 97) && (stringByte <= 102)) stringByte -= 87; else if ((stringByte >= 65) && (stringByte <= 70)) stringByte -= 55; else if ((stringByte >= 48) && (stringByte <= 57)) stringByte -= 48; else revert InvalidAddressString(); addressNumber |= uint160(uint256(stringByte) << ((41 - i) << 2)); } return address(addressNumber); } } library AddressToString { function toString(address address_) internal pure returns (string memory) { bytes memory addressBytes = abi.encodePacked(address_); bytes memory characters = '0123456789abcdef'; bytes memory stringBytes = new bytes(42); stringBytes[0] = '0'; stringBytes[1] = 'x'; for (uint256 i; i < 20; ++i) { stringBytes[2 + i * 2] = characters[uint8(addressBytes[i] >> 4)]; stringBytes[3 + i * 2] = characters[uint8(addressBytes[i] & 0x0f)]; } return string(stringBytes); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity =0.8.24; import "../BaseBridge.sol"; import {AxelarExecutable} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol"; import {IAxelarGasService} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol"; import { StringToAddress, AddressToString } from "@axelar-network/axelar-gmp-sdk-solidity/contracts/libs/AddressString.sol"; /** * @title BaseBridgeAxelar * @dev Base contract for interacting with Axelar Network for cross-chain transactions. */ abstract contract BaseBridgeAxelar is BaseBridge, AxelarExecutable { error Fee_Percentage_less_than_100(); error Minimum_Gas_Invalid(uint256 gasAmount); error Execution_gas_limit_not_set_for_this_packet_type(uint16 packetType); error Insufficient_Value_Attached_For_GasPayment(uint256 attachedValue, uint256 expectedValue); struct AxelarChainInfo { string dstChainName; string dstChainAddress; // lightchain/mainchain bridge address } using AddressToString for address; using StringToAddress for string; uint16 internal _selfChainId; // lz chain-id as LZ-endpoint-ID uint16 internal _mainChainId; uint16 public lzFeePercentage; mapping(uint16 => mapping(uint16 => uint256)) public minDstGasLookup; // lzChainID -> (packetType -> gasAmount) mapping(uint16 => AxelarChainInfo) public axelarDstChainLookup; // axelar destination chain info (lzChainId -> AxelarChainInfo) mapping(string => uint16) public srcChainIdLookup; // Axelar source chain -> lzChainId (call from remote chain to address(this)) IAxelarGasService public immutable gasService; event SendMessage(address indexed account, uint16 indexed dstChainId, uint16 indexed packetType, bytes payload); event ReceiveMsg(address indexed account, uint16 indexed packetType, uint16 indexed srcChainId); event SetMinDstGas(uint16 dstChainId, uint16 packetType, uint256 minGas); event SetTrustedRemote(uint16 remoteChainId, string remoteChainName, string remoteChainAddress); /** * @dev Constructor to initialize the contract with AxelarGateway and gas receiver. * @param _selfAxelarGateway Address of the AxelarGateway contract. * @param _selfGasReceiver Address of the gas receiver contract. */ constructor(address _selfAxelarGateway, address _selfGasReceiver) AxelarExecutable(_selfAxelarGateway) { gasService = IAxelarGasService(_selfGasReceiver); } /** * @dev Calculate the fee for executing a cross-chain transaction. * @param _payload The payload data for the transaction. * @param packetType The type of the transaction packet. * @param dstChainId The destination chain ID. * @return lzFee The calculated fee in native currency. */ function calcFee(bytes memory _payload, uint16 packetType, uint16 dstChainId) public view override returns (uint256 lzFee) { uint256 _fee = _getEstimatedFees(_payload,dstChainId, packetType); if (_checkMultiBroadcast(packetType)) { _fee += _getEstimatedFees(_payload, _mainChainId, packetType); } lzFee = _fee * lzFeePercentage / 100; } /** * @dev Set the LZ fee percentage for transactions. * @param _percentage The fee percentage to be set. */ function setLZFeePercentage(uint16 _percentage) public { if (_percentage < 100) { revert Fee_Percentage_less_than_100(); } lzFeePercentage = _percentage; } /** * @dev Get the self LZ chain ID. * @return _selfChainId The current LZ chain ID. */ function selfChainId() external view returns (uint16) { return _selfChainId; // lz chain id } /** * @dev Set a trusted remote chain for interaction. * @param _remoteChainId The ID of the remote chain. * @param _remoteChainName The name of the remote chain. * @param _remoteAddress The address of the remote chain bridge. * @notice Trusted remote should be address of other bridges on different network */ function setTrustedRemote(uint16 _remoteChainId, string calldata _remoteChainName, string calldata _remoteAddress) external onlyOwner { axelarDstChainLookup[_remoteChainId] = AxelarChainInfo({dstChainName: _remoteChainName, dstChainAddress: _remoteAddress}); emit SetTrustedRemote(_remoteChainId, _remoteChainName, _remoteAddress); } /** * @dev Set the source chain ID lookup for Axelar. * @param _srcChainName The name of the source chain. * @param _srcChainId The ID of the source chain. */ function setSrcChainIdLookup(string calldata _srcChainName, uint16 _srcChainId) external onlyOwner { srcChainIdLookup[_srcChainName] = _srcChainId; } /** * @dev Set the minimum gas required for a destination chain and packet type. * @param _destinationChainId The ID of the destination chain. * @param _packetType The type of the packet. * @param _minGasAmount The minimum gas amount required. */ function setMinDestinatinGas(uint16 _destinationChainId, uint16 _packetType, uint256 _minGasAmount) external onlyOwner { if (_minGasAmount == 0) { revert Minimum_Gas_Invalid(_minGasAmount); } minDstGasLookup[_destinationChainId][_packetType] = _minGasAmount; emit SetMinDstGas(_destinationChainId, _packetType, _minGasAmount); } function _broadcast( address account, bytes memory payload, uint16 packetType, uint16 dstChainId, uint256 value, bool // the param to check ZRO token payment ) internal returns (uint256) { uint256 executionGasLimit = minDstGasLookup[dstChainId][packetType]; if (executionGasLimit == 0) { revert Execution_gas_limit_not_set_for_this_packet_type(packetType); } AxelarChainInfo memory dstChainInfo = axelarDstChainLookup[dstChainId]; uint256 nativeFee = _validateGasAmount( dstChainInfo.dstChainName, dstChainInfo.dstChainAddress, payload, executionGasLimit, value ); gasService.payNativeGasForContractCall{value: value}( address(this), dstChainInfo.dstChainName, dstChainInfo.dstChainAddress, payload, payable(address(this)) ); gateway.callContract(dstChainInfo.dstChainName, dstChainInfo.dstChainAddress, payload); emit SendMessage(account, dstChainId, packetType, payload); return nativeFee; } function _validateGasAmount( string memory chainName, string memory dstAddress, bytes memory payload, uint256 executionGasLimit, uint256 value ) internal view returns (uint256 _fee) { _fee = gasService.estimateGasFee(chainName, dstAddress, payload, executionGasLimit, bytes("0")); if (value < _fee) { revert Insufficient_Value_Attached_For_GasPayment(value, _fee); } } function _getEstimatedFees(bytes memory _payload, uint16 _dstChainId, uint16 _packetType) internal view returns (uint256 fee) { AxelarChainInfo memory _chainInfo = axelarDstChainLookup[_dstChainId]; uint256 _minDstGas = minDstGasLookup[_dstChainId][_packetType]; fee = gasService.estimateGasFee( _chainInfo.dstChainName, _chainInfo.dstChainAddress, _payload, _minDstGas, bytes("0") ); } // check for different packetTypes to invoke 2-way cross transaction in case of lightchain <> lightchain function _checkMultiBroadcast(uint16 _packetType) private view returns (bool isAllowed) { if ( ( _packetType == PT_EXCHANGE || _packetType == PT_BRIDGE_SYNTH || _packetType == PT_CROSS_SWAP_CASE_1 || _packetType == PT_CROSS_SWAP_CASE_2 || _packetType == PT_CROSS_SWAP_CASE_3 || _packetType == PT_CROSS_SWAP_DEX_CASE_1 || _packetType == PT_CROSS_SWAP_DEX_CASE_3 ) && (_selfChainId != _mainChainId) ) { isAllowed = true; } } }
// SPDX-License-Identifier: MIT pragma solidity =0.8.24; import "@openzeppelin/contracts/access/Ownable.sol"; import "../libraries/TransferHelper.sol"; import "../interfaces/ISynthrSwap.sol"; import "../interfaces/ISynthrSwapDex.sol"; import "../interfaces/IFuturesMarketManager.sol"; interface IAddressResolver { function getAddress(bytes32 name) external view returns (address); } abstract contract BaseBridge is Ownable { error Invalid_caller(); address public _synthrAddressResolver; uint16 internal constant PT_DEPOSIT_COLLATERAL = 1; uint16 internal constant PT_MINT_SYNTH = 2; uint16 internal constant PT_WITHDRAW_COLLATERAL = 3; uint16 internal constant PT_BURN_SYNTH = 4; uint16 internal constant PT_EXCHANGE = 5; uint16 internal constant PT_LIQUIDATE = 6; uint16 internal constant PT_BRIDGE_SYNTH = 7; uint16 internal constant PT_TRANSFER_MARGIN = 9; uint16 internal constant PT_WITHDRAW_MARGIN = 10; uint16 internal constant PT_CROSS_SWAP_CASE_1 = 11; uint16 internal constant PT_CROSS_SWAP_CASE_2 = 12; uint16 internal constant PT_CROSS_SWAP_CASE_3 = 13; uint16 internal constant PT_CROSS_SWAP_DEX_CASE_1 = 14; uint16 internal constant PT_CROSS_SWAP_DEX_CASE_3 = 15; constructor() {} modifier onlySynthr() { if (isAllowedCaller(msg.sender)) { _; } else { revert Invalid_caller(); } } receive() external payable {} function isAllowedCaller(address caller) private view returns (bool) { return caller == getAddressFromResolver("WrappedSynthr") || caller == getAddressFromResolver("Issuer") || caller == getAddressFromResolver("Exchanger") || caller == getAddressFromResolver("SynthrSwap") || caller == getAddressFromResolver("SynthrSwapWithDex") || caller == getAddressFromResolver("OffChainExchanger") || caller == getAddressFromResolver("FuturesMarketManager") || IFuturesMarketManager(getAddressFromResolver("FuturesMarketManager")).isMarketImplementation(caller); } function getAddressFromResolver(bytes32 name) internal view returns (address) { return IAddressResolver(_synthrAddressResolver).getAddress(name); } /** * @notice Calculate the fee for a given payload and packet type * @param payload The payload to calculate the fee for * @param packetType The packet type * @param dstChainId The destination chain ID * @return The calculated fee */ function calcFee( bytes memory payload, uint16 packetType, uint16 dstChainId ) public view virtual returns (uint); /** * @notice Withdraw a specified amount of a given token * @param token The address of the token to withdraw * @param amount The amount to withdraw */ function withdrawAsset(address token, uint amount) public onlyOwner { if (token == address(0)) { TransferHelper.safeTransferETH(msg.sender, amount); } else { TransferHelper.safeTransfer(token, msg.sender, amount); } } }
// SPDX-License-Identifier: MIT pragma solidity =0.8.24; interface IExchanger { function updateDestinationForExchange( address recipient, bytes32 destinationKey, uint destinationAmount ) external; }
// SPDX-License-Identifier: MIT pragma solidity =0.8.24; interface IFuturesMarketManager { function marketForKey(bytes32 marketKey) external view returns (address); function isMarketImplementation(address _account) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity =0.8.24; interface ISynthrIssuer { function synthsByAddress(address synthAddress) external view returns (bytes32); function destIssue( address account, bytes32 synthKey, uint synthAmount ) external; }
// SPDX-License-Identifier: MIT pragma solidity =0.8.24; interface ISynthrSwap { function destSwapSynthToNative( address account, bytes32 sourceKey, uint sourceAmount, bytes32 destKey, uint destAmount, address target, bytes memory data ) external returns (bool); function destSwapNativeToSynth( address account, bytes32 sourceKey, uint sourceAmount, bytes32 destKey, uint destAmount ) external; function destSwapNativeToNative( address account, bytes32 sourceKey, uint sourceAmount, bytes32 destKey, uint destAmount, address target, bytes memory data ) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity =0.8.24; interface ISynthrSwapDex { function destSwapSynthToNative( address account, bytes32 sourceKey, uint sourceAmount, bytes32 destKey, uint destAmount ) external returns (bool); function destSwapNativeToNative( address account, bytes32 sourceKey, uint sourceAmount, bytes32 destKey, uint destAmount ) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity =0.8.24; interface IWrappedSynthr { function getAvailableCollaterals() external view returns (bytes32[] memory); function withdrawCollateral( address from, address to, bytes32 collateralKey, uint collateralAmount ) external; function collateralTransfer( address _from, bytes32 _collateralKey, uint _collateralAmount ) external; function destBurn( address account, bytes32 synthKey, uint amount ) external returns (bool); function destTransferMargin( address account, uint marginDelta, bytes32 marketKey ) external returns (bool); }
// 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.24; 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: GPL-3.0-or-later pragma solidity =0.8.24; library TransferHelper { function safeTransfer( address token, address to, uint value ) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::safeTransfer: transfer failed"); } function safeTransferETH(address to, uint value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, "TransferHelper::safeTransferETH: ETH transfer failed"); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "viaIR": true, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
[{"inputs":[{"internalType":"address","name":"_selfAxelarGateway","type":"address"},{"internalType":"address","name":"_selfGasReceiver","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Bridging_on_same_chain","type":"error"},{"inputs":[],"name":"Call_from_invalid_source","type":"error"},{"inputs":[{"internalType":"uint16","name":"packetType","type":"uint16"}],"name":"Execution_gas_limit_not_set_for_this_packet_type","type":"error"},{"inputs":[],"name":"Fee_Percentage_less_than_100","type":"error"},{"inputs":[{"internalType":"uint256","name":"attachedValue","type":"uint256"},{"internalType":"uint256","name":"expectedValue","type":"uint256"}],"name":"Insufficient_Value_Attached_For_GasPayment","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"Invalid_caller","type":"error"},{"inputs":[],"name":"Margin_delta_zero","type":"error"},{"inputs":[{"internalType":"uint256","name":"gasAmount","type":"uint256"}],"name":"Minimum_Gas_Invalid","type":"error"},{"inputs":[],"name":"NotApprovedByGateway","type":"error"},{"inputs":[{"internalType":"uint16","name":"packetType","type":"uint16"}],"name":"Unknown_packetType","type":"error"},{"inputs":[],"name":"source_chainID_lookup_not_set","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint16","name":"packetType","type":"uint16"},{"indexed":true,"internalType":"uint16","name":"srcChainId","type":"uint16"}],"name":"ReceiveMsg","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"uint16","name":"dstChainId","type":"uint16"},{"indexed":true,"internalType":"uint16","name":"packetType","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"payload","type":"bytes"}],"name":"SendMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"dstChainId","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"packetType","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"minGas","type":"uint256"}],"name":"SetMinDstGas","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"remoteChainId","type":"uint16"},{"indexed":false,"internalType":"string","name":"remoteChainName","type":"string"},{"indexed":false,"internalType":"string","name":"remoteChainAddress","type":"string"}],"name":"SetTrustedRemote","type":"event"},{"inputs":[],"name":"_synthrAddressResolver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"axelarDstChainLookup","outputs":[{"internalType":"string","name":"dstChainName","type":"string"},{"internalType":"string","name":"dstChainAddress","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_payload","type":"bytes"},{"internalType":"uint16","name":"packetType","type":"uint16"},{"internalType":"uint16","name":"dstChainId","type":"uint16"}],"name":"calcFee","outputs":[{"internalType":"uint256","name":"lzFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"commandId","type":"bytes32"},{"internalType":"string","name":"sourceChain","type":"string"},{"internalType":"string","name":"sourceAddress","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"commandId","type":"bytes32"},{"internalType":"string","name":"sourceChain","type":"string"},{"internalType":"string","name":"sourceAddress","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"string","name":"tokenSymbol","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"executeWithToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gasService","outputs":[{"internalType":"contract IAxelarGasService","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gateway","outputs":[{"internalType":"contract IAxelarGateway","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"__synthrAddressResolver","type":"address"},{"internalType":"uint16","name":"__mainChainId","type":"uint16"},{"internalType":"uint16","name":"__selfChainId","type":"uint16"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lzFeePercentage","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mainChainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint16","name":"","type":"uint16"}],"name":"minDstGasLookup","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"selfChainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"synthKey","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint16","name":"dstChainId","type":"uint16"},{"internalType":"bool","name":"","type":"bool"}],"name":"sendBridgeSyToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"synthKey","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"name":"sendBurn","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"srcKey","type":"bytes32"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"bytes32","name":"dstKey","type":"bytes32"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint16","name":"dstChainId","type":"uint16"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"address","name":"dexAddress","type":"address"},{"internalType":"bytes","name":"dexPayload","type":"bytes"},{"internalType":"bool","name":"","type":"bool"}],"name":"sendCrossSwapNativeToNative","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"srcKey","type":"bytes32"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"bytes32","name":"dstKey","type":"bytes32"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint16","name":"dstChainId","type":"uint16"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"name":"sendCrossSwapNativeToNativeWithDex","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"srcKey","type":"bytes32"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"bytes32","name":"dstKey","type":"bytes32"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint16","name":"dstChainId","type":"uint16"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"name":"sendCrossSwapNativeToSyAsset","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"srcKey","type":"bytes32"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"bytes32","name":"dstKey","type":"bytes32"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint16","name":"dstChainId","type":"uint16"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"bytes","name":"dexPayload","type":"bytes"},{"internalType":"address","name":"dexAddress","type":"address"},{"internalType":"bool","name":"","type":"bool"}],"name":"sendCrossSwapSyAssetToNative","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"srcKey","type":"bytes32"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"bytes32","name":"dstKey","type":"bytes32"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint16","name":"dstChainId","type":"uint16"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"name":"sendCrossSwapSyAssetToNativeWithDex","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"collateralKey","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"name":"sendDepositCollateral","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"srcSynthKey","type":"bytes32"},{"internalType":"bytes32","name":"dstSynthKey","type":"bytes32"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"dstAmount","type":"uint256"},{"internalType":"uint256","name":"reclaimed","type":"uint256"},{"internalType":"uint256","name":"refund","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint16","name":"dstChainId","type":"uint16"},{"internalType":"bool","name":"","type":"bool"}],"name":"sendExchange","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"marginDelta","type":"uint256"},{"internalType":"bytes32","name":"marketKey","type":"bytes32"},{"internalType":"bool","name":"","type":"bool"}],"name":"sendTransferMargin","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_percentage","type":"uint16"}],"name":"setLZFeePercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_destinationChainId","type":"uint16"},{"internalType":"uint16","name":"_packetType","type":"uint16"},{"internalType":"uint256","name":"_minGasAmount","type":"uint256"}],"name":"setMinDestinatinGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_srcChainName","type":"string"},{"internalType":"uint16","name":"_srcChainId","type":"uint16"}],"name":"setSrcChainIdLookup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"internalType":"string","name":"_remoteChainName","type":"string"},{"internalType":"string","name":"_remoteAddress","type":"string"}],"name":"setTrustedRemote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"srcChainIdLookup","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60c034620001a657601f620041fc38819003918201601f19168301916001600160401b03831184841017620001ab578084926040948552833981010312620001a6576200005a60206200005283620001c1565b9201620001c1565b60008054336001600160a01b03198216811783556040516001600160a01b0395909386939192918416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3169081156200019757506080521660a0526001805461ffff60c01b1916601960c21b1790556040516140259081620001d782396080518181816104e501528181610de301528181611b3001528181612135015281816122e90152818161247d01528181612610015281816127a40152818161293801528181612acc01528181612c6001528181612df40152612f88015260a051818181610f5e015281816120d2015281816122860152818161241a015281816125ad01528181612741015281816128d501528181612a6901528181612bfd01528181612d9101528181612f250152818161319301526136830152f35b63e6c4247b60e01b8152600490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203620001a65756fe6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c806302de00921461020b5780630cf2abc6146102065780630f45ad4314610201578063116191b6146101fc5780631a98b2e0146101f75780631c4b995a146101f25780632abe893f146101ed5780632bb821bd146101e85780632c957005146101e35780632d89c635146101de57806338e4f064146101d9578063397b2b3a146101d457806349160658146101cf5780634fa34310146101ca5780636a22d8cc146101c55780636fcdef87146101c0578063715018a6146101bb57806380a2eb14146101b6578063863c576f146101b15780638cfd8f5c146101ac5780638da5cb5b146101a7578063af02b429146101a2578063bcc44cb11461019d578063cc9e3e8914610198578063dfb0b30f14610193578063e289c24a1461018e578063e4f84c3f14610189578063f2fde38b14610184578063f3e0893b1461017f578063f4a4229b1461017a5763f7736f3d0361000e576118ae565b6117f1565b611781565b6116ba565b61164f565b611526565b6114a4565b611445565b611354565b6112f8565b6112cf565b611274565b6111c8565b611097565b611039565b610f8d565b610f48565b610e71565b610d15565b610c92565b610b7d565b610998565b61096f565b6107f2565b61066a565b6105a3565b610514565b6104cf565b6104aa565b610405565b610269565b6001600160a01b0381160361022157565b600080fd5b61ffff81160361022157565b9181601f84011215610221578235916001600160401b038311610221576020838186019501011161022157565b8015150361022157565b6101403660031901126102215760043561028281610210565b60a43561028e81610226565b60e4359061029b82610210565b610104356001600160401b038111610221576102bb903690600401610232565b90926102c96101243561025f565b6102d233611e43565b156103c357604051606086901b6001600160601b031916602082015261037492610368906103389061034484603481015b0395610317601f199788810188528761077f565b604051938491602083016014916001600160601b03199060601b1681520190565b0386810184528361077f565b6040519788948860c435916084359060643590604435906024359060208c016119d3565b0390810184528361077f565b61ffff9161039461038e348560015460b01c168488612d19565b34611a7e565b926103b06103a960015461ffff9060b01c1690565b61ffff1690565b908316036103ba57005b61001993612d19565b604051632e79a65160e01b8152600490fd5b6080906003190112610221576004356103ed81610210565b9060243590604435906064356104028161025f565b90565b61040e366103d5565b5061041b92919233611e43565b156103c3576040516001600160601b0319606084901b16602082015260148152610019936104769261048d92601f1992909161045860348461077f565b604051958693600160208601526080604086015260a085019061162a565b91606084015260808301520390810183528261077f565b61ffff60015460b01c16903492612055565b600091031261022157565b3461022157600036600319011261022157602061ffff60015460b01c16604051908152f35b34610221576000366003190112610221576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346102215760c0366003190112610221576001600160401b0360243581811161022157610545903690600401610232565b6044358381116102215761055d903690600401610232565b60649291923585811161022157610578903690600401610232565b9160843596871161022157610594610019973690600401610232565b95909460a43597600435611aac565b34610221576060366003190112610221576004356105c081610210565b602435906105cd82610226565b6044356105d981610226565b6105e1613041565b600180546001600160a01b039093166001600160c01b031990931660b09490941b61ffff60b01b16939093179190911760a09190911b61ffff60a01b16179055005b6101009060031901126102215760043561063c81610210565b906024359060443590606435906084359060a43561065981610226565b9060c4359060e4356104028161025f565b61067336610623565b509290939161068133611e43565b156103c3576040516001600160601b0319606089901b166020820152601481526106cf94601f19949193610368939192889291906106c060348861077f565b6040519a8b9760208901611ba2565b61ffff916106e760015484349160b01c16838761220e565b340392348411610716576107038160015460b01c1661ffff1690565b9083160361070d57005b6100199361220e565b611a68565b634e487b7160e01b600052604160045260246000fd5b604081019081106001600160401b0382111761074c57604052565b61071b565b6001600160401b03811161074c57604052565b608081019081106001600160401b0382111761074c57604052565b90601f801991011681019081106001600160401b0382111761074c57604052565b6001600160401b03811161074c57601f01601f191660200190565b9291926107c7826107a0565b916107d5604051938461077f565b829481845281830111610221578281602093846000960137010152565b34610221576060366003190112610221576004356001600160401b0381116102215736602382011215610221576108cb6108c461083c6108db9336906024816004013591016107bb565b60243561084881610226565b61085e8160443561085881610226565b84613113565b91600061ffff8084169060058214918215610964575b8215610959575b821561094e575b8215610943575b8215610938575b821561092d575b5081610914575b5061090c575b6108df575b50506001546108be9060c01c61ffff166103a9565b90611c40565b6064900490565b6040519081529081906020820190565b0390f35b61090592916108ff916108f960015461ffff9060b01c1690565b90613113565b90611c33565b38806108a9565b5060016108a4565b905060015490808260b01c169160a01c1614153861089e565b600f14915038610897565b600e81149250610890565b600d81149250610889565b600c81149250610882565b600b8114925061087b565b600781149250610874565b34610221576000366003190112610221576001546040516001600160a01b039091168152602090f35b34610221576060366003190112610221576004356109b581610226565b6001600160401b03602435818111610221576109d5903690600401610232565b92604435838111610221576109ee903690600401610232565b946109f7613041565b604051610a0381610731565b610a0e3683876107bb565b8152610a1b3688856107bb565b6020966020830191825260009761ffff871689526003602052604089209351805192831161074c57610a5783610a51875461154b565b87611c53565b602091601f8411600114610ae05750899a9593610ab884610ac395610acf9a98956001957fe23d07b94549231dae818bc0a03de052bcbc3b986e7861d3c1ab2aed275a92f19f92610ad5575b50508160011b916000199060031b1c19161790565b83555b519101611ca9565b60405195869586611d72565b0390a180f35b015190503880610aa3565b9190601f198416610af687600052602060002090565b938c905b828210610b6557505084610acf9997946001947fe23d07b94549231dae818bc0a03de052bcbc3b986e7861d3c1ab2aed275a92f19e9f9a9894610ac398879510610b4c575b505050811b018355610abb565b015160001960f88460031b161c19169055388080610b3f565b80600186978294978701518155019601940190610afa565b3461022157604036600319011261022157600435610b9a81610210565b602435610ba5613041565b6001600160a01b038216610bbe57610019915033613228565b600091829182604051602081019263a9059cbb60e01b8452336024830152604482015260448152610bee81610764565b51925af1610bfa6131f8565b81610c63575b5015610c0857005b60405162461bcd60e51b815260206004820152602d60248201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260448201526c185b9cd9995c8819985a5b1959609a1b6064820152608490fd5b8051801592508215610c78575b505038610c00565b610c8b9250602080918301019101611a8b565b3880610c70565b610c9b366103d5565b50610ca892919233611e43565b156103c3576040516001600160601b0319606084901b166020820152601481526100199361047692610d0392601f19929091610ce560348461077f565b604051958693600460208601526080604086015260a085019061162a565b61ffff60015460b01c169034926123a2565b3461022157600319608036820112610221576004906001600160401b039060243582811161022157610d4a9036908501610232565b909260443581811161022157610d639036908701610232565b92909160643590811161022157610d7d9036908801610232565b9590946020610dd5610d90368a8a6107bb565b805190830120604051635f6970c360e01b81528b358c82015260806024820152938492839291610dc4608485018a8a6119b2565b908482030160448501528a8a6119b2565b6064830191909152038160007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af1908115610e6c57600091610e3d575b5015610e2c5761001996506132c5565b604051631403112d60e21b81528790fd5b610e5f915060203d602011610e65575b610e57818361077f565b810190611a8b565b38610e1c565b503d610e4d565b611aa0565b608036600319011261022157600435610e8981610210565b60243590610e9860643561025f565b610ea133611e43565b156103c3578115610f3757610f0b610f256100199360405180610ed986602083016014916001600160601b03199060601b1681520190565b0391610eed601f199384810184528361077f565b604051948592600960208501526080604085015260a084019061162a565b90606083015260443560808301520390810183528261077f565b60015460b01c61ffff16903492612535565b60405162da776760e51b8152600490fd5b34610221576000366003190112610221576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b610f9636610623565b5092909391610fa433611e43565b156103c3576040516001600160601b0319606089901b16602082015260148152610ff294601f1994919361036893919288929190610fe360348861077f565b6040519a8b9760208901611be7565b61ffff9161100a60015484349160b01c1683876126c9565b340392348411610716576110268160015460b01c1661ffff1690565b9083160361103057005b610019936126c9565b346102215760008060031936011261109457611053613041565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b610140366003190112610221576004356110b081610210565b610104356110bd81610226565b6110c96101243561025f565b6110d233611e43565b156103c357806110f16110e960c43560a435611a7e565b606435611c33565b61ffff809216156111b5575b6040516001600160601b0319606086901b166020820152601481529061115b90601f199061112c60348561077f565b61114f8660405195869360e4359160843591604435916024359060208901611da2565b0390810183528261077f565b34926111716103a960015461ffff9060a01c1690565b9083811691820361119b575b5060015460b01c61ffff169283160361119257005b6100199361285d565b6111ae91945061038e903490848861285d565b923861117d565b60015490925060a01c61ffff16916110fd565b6111d136610623565b50929093916111df33611e43565b156103c3576040516001600160601b0319606089901b1660208201526014815261122d94601f199491936103689391928892919061121e60348861077f565b6040519a8b9760208901611c0d565b61ffff9161124560015484349160b01c1683876129f1565b340392348411610716576112618160015460b01c1661ffff1690565b9083160361126b57005b610019936129f1565b346102215760403660031901126102215760206112c660043561129681610226565b61ffff602435916112a683610226565b166000526002835260406000209061ffff16600052602052604060002090565b54604051908152f35b34610221576000366003190112610221576000546040516001600160a01b039091168152602090f35b346102215760203660031901126102215760043561131581610226565b606461ffff821610611342576001805461ffff60c01b191660c09290921b61ffff60c01b16919091179055005b60405163fccfd58b60e01b8152600490fd5b60a03660031901126102215760043561136c81610210565b60643561137881610226565b61138360843561025f565b61138c33611e43565b156103c35761ffff8082169182156114335761140e61038e82611405604051806113cb8a602083016014916001600160601b03199060601b1681520190565b03906113df601f199283810183528261077f565b6113f9604051978892604435906024359060208601611de8565b0390810186528561077f565b34908488612b85565b9261142060015461ffff9060b01c1690565b9283160361142a57005b61001993612b85565b604051636794524760e01b8152600490fd5b3461022157600036600319011261022157602061ffff60015460a01c16604051908152f35b60005b83811061147d5750506000910152565b818101518382015260200161146d565b906114a06020928281519485920161146a565b0190565b34610221576020366003190112610221576004356001600160401b03811161022157366023820112156102215761ffff61150360206114f06108db9436906024816004013591016107bb565b816040519382858094519384920161146a565b8101600481520301902054166040519182918291909161ffff6020820193169052565b3461022157600036600319011261022157602061ffff60015460c01c16604051908152f35b90600182811c9216801561157b575b602083101461156557565b634e487b7160e01b600052602260045260246000fd5b91607f169161155a565b906040519182600082546115988161154b565b9081845260209460019160018116908160001461160857506001146115c9575b5050506115c79250038361077f565b565b600090815285812095935091905b8183106115f05750506115c793508201013880806115b8565b855488840185015294850194879450918301916115d7565b925050506115c794925060ff191682840152151560051b8201013880806115b8565b906020916116438151809281855285808601910161146a565b601f01601f1916010190565b346102215760203660031901126102215761ffff60043561166f81610226565b1660005260036020526116ac60406000206108db611698600161169184611585565b9301611585565b60405193849360408552604085019061162a565b90838203602085015261162a565b34610221576020366003190112610221576004356116d781610210565b6116df613041565b6001600160a01b03908116801561172d57600080546001600160a01b03198116831782559092167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b34610221576040366003190112610221576004356001600160401b038111610221576117b461ffff913690600401610232565b60243592916020906117c585610226565b6117cd613041565b82604051938492833781016004815203019020911661ffff19825416179055600080f35b346102215760603660031901126102215760043561180e81610226565b6024359061181b82610226565b60443590611827613041565b811561189557916060917f9d5c7c0b934da8fefa9c7760c98383778a12dfbfc0c3b3106518f43fb9508ac09361ffff80911692836000526002602052826118808260406000209061ffff16600052602052604060002090565b556040519384521660208301526040820152a1005b6040516355b56ea760e01b815260048101839052602490fd5b610140366003190112610221576004356118c781610210565b60a4356118d381610226565b60e4356001600160401b038111610221576118f2903690600401610232565b6101049291923561190281610210565b61190e6101243561025f565b61191733611e43565b156103c357604051606086901b6001600160601b031916602082015261197092610368906103389061194c8460348101610303565b6040519788948860c435916084359060643590604435906024359060208c01611a3c565b61ffff9161198a61038e348560015460b01c168488612ead565b9261199f6103a960015461ffff9060b01c1690565b908316036119a957005b61001993612ead565b908060209392818452848401376000828201840152601f01601f1916010190565b98946104029a9894611a2d98946119ff61ffff9599948d61014090600d8152816020820152019061162a565b9860408d015260608c015260808b015260a08a01521660c088015260e08701528583036101008701526119b2565b9161012081840391015261162a565b98946104029a9894611a2d98946119ff61ffff9599948d61014090600b8152816020820152019061162a565b634e487b7160e01b600052601160045260246000fd5b9190820391821161071657565b9081602091031261022157516104028161025f565b6040513d6000823e3d90fd5b9592611b0e611ac860209a9499939b97611b22979636916107bb565b8a815191012094611afa6040519c8d9b8c9b631876eed960e01b8d5260048d015260c060248d015260c48c01916119b2565b9060031993848b84030160448c01526119b2565b9360648801528684030160848701526119b2565b60a4830191909152038160007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af1908115610e6c57600091611b83575b5015611b7157565b604051631403112d60e21b8152600490fd5b611b9c915060203d602011610e6557610e57818361077f565b38611b69565b9361ffff93611bc860e097939a9998949a610100600c89528060208a015288019061162a565b9960408701526060860152608085015260a08401521660c08201520152565b9361ffff93611bc860e097939a9998949a610100600f89528060208a015288019061162a565b9361ffff93611bc860e097939a9998949a610100600e89528060208a015288019061162a565b9190820180921161071657565b8181029291811591840414171561071657565b90601f8111611c6157505050565b6000916000526020600020906020601f850160051c83019410611c9f575b601f0160051c01915b828110611c9457505050565b818155600101611c88565b9092508290611c7f565b91909182516001600160401b03811161074c57611cd081611cca845461154b565b84611c53565b602080601f8311600114611d0757508190611d03939495600092610ad55750508160011b916000199060031b1c19161790565b9055565b90601f19831695611d1d85600052602060002090565b926000905b888210611d5a57505083600195969710611d41575b505050811b019055565b015160001960f88460031b161c19169055388080611d37565b80600185968294968601518155019501930190611d22565b9391610402959361ffff611d94931686526060602087015260608601916119b2565b9260408185039101526119b2565b95919796929361ffff94611dc860e0979361010060058b528060208c01528a019061162a565b9960408901526060880152608087015260a086015260c085015216910152565b92936080929594611e0b61ffff936007875260a0602088015260a087019061162a565b966040860152606085015216910152565b908092918237016000815290565b6020908260405193849283378101600481520301902090565b611e5a611e4e6133fa565b6001600160a01b031690565b6001600160a01b03821690811491908215611f7a575b8215611f65575b8215611f50575b8215611f3b575b8215611f26575b8215611f10575b508115611e9e575090565b611ee19150602090611eb4611e4e611e4e6135fd565b6040516308651a8360e31b81526001600160a01b0390921660048301529092839190829081906024820190565b03915afa908115610e6c57600091611ef7575090565b610402915060203d602011610e6557610e57818361077f565b909150611f1e611e4e6135fd565b149038611e93565b9150611f33611e4e6135ab565b821491611e8c565b9150611f48611e4e613559565b821491611e85565b9150611f5d611e4e61350e565b821491611e7e565b9150611f72611e4e6134c4565b821491611e77565b9150611f87611e4e61347d565b821491611e70565b90604051611f9c81610731565b6020611fb660018395611fae81611585565b855201611585565b910152565b93611ff8608094611fea612006949599989960018060a01b03809716895260a060208a015260a089019061162a565b90878203604089015261162a565b90858203606087015261162a565b9416910152565b9161203690612028610402959360608652606086019061162a565b90848203602086015261162a565b91604081840391015261162a565b90602061040292818152019061162a565b906120816120718461ffff166000526002602052604060002090565b6001600052602052604060002090565b549384156121f5576120a96120a48561ffff166000526003602052604060002090565b611f8f565b6120be828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f00000000000000000000000000000000000000000000000000000000000000008616803b1561022157876000936121229560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c576121e2575b50827f0000000000000000000000000000000000000000000000000000000000000000169151905190823b15610221576121889260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff936001986121c9575b506040519384931696169482612044565b0390a490565b806121d66121dc92610751565b8061049f565b386121b2565b806121d66121ef92610751565b38612131565b60405163056a947960e11b815260016004820152602490fd5b9061223a61222a8461ffff166000526002602052604060002090565b600c600052602052604060002090565b549384156123895761225d6120a48561ffff166000526003602052604060002090565b612272828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f00000000000000000000000000000000000000000000000000000000000000008616803b1561022157876000936122d69560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c57612376575b50827f0000000000000000000000000000000000000000000000000000000000000000169151905190823b156102215761233c9260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff93600c986121c957506040519384931696169482612044565b806121d661238392610751565b386122e5565b60405163056a947960e11b8152600c6004820152602490fd5b906123ce6123be8461ffff166000526002602052604060002090565b6004600052602052604060002090565b5493841561251d576123f16120a48561ffff166000526003602052604060002090565b612406828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f00000000000000000000000000000000000000000000000000000000000000008616803b15610221578760009361246a9560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c5761250a575b50827f0000000000000000000000000000000000000000000000000000000000000000169151905190823b15610221576124d09260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff936004986121c957506040519384931696169482612044565b806121d661251792610751565b38612479565b60405163056a947960e11b8152600480820152602490fd5b906125616125518461ffff166000526002602052604060002090565b6009600052602052604060002090565b549384156126b0576125846120a48561ffff166000526003602052604060002090565b612599828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f00000000000000000000000000000000000000000000000000000000000000008616803b1561022157876000936125fd9560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c5761269d575b50827f0000000000000000000000000000000000000000000000000000000000000000169151905190823b15610221576126639260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff936009986121c957506040519384931696169482612044565b806121d66126aa92610751565b3861260c565b60405163056a947960e11b815260096004820152602490fd5b906126f56126e58461ffff166000526002602052604060002090565b600f600052602052604060002090565b54938415612844576127186120a48561ffff166000526003602052604060002090565b61272d828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f00000000000000000000000000000000000000000000000000000000000000008616803b1561022157876000936127919560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c57612831575b50827f0000000000000000000000000000000000000000000000000000000000000000169151905190823b15610221576127f79260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff93600f986121c957506040519384931696169482612044565b806121d661283e92610751565b386127a0565b60405163056a947960e11b8152600f6004820152602490fd5b906128896128798461ffff166000526002602052604060002090565b6005600052602052604060002090565b549384156129d8576128ac6120a48561ffff166000526003602052604060002090565b6128c1828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f00000000000000000000000000000000000000000000000000000000000000008616803b1561022157876000936129259560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c576129c5575b50827f0000000000000000000000000000000000000000000000000000000000000000169151905190823b156102215761298b9260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff936005986121c957506040519384931696169482612044565b806121d66129d292610751565b38612934565b60405163056a947960e11b815260056004820152602490fd5b90612a1d612a0d8461ffff166000526002602052604060002090565b600e600052602052604060002090565b54938415612b6c57612a406120a48561ffff166000526003602052604060002090565b612a55828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f00000000000000000000000000000000000000000000000000000000000000008616803b156102215787600093612ab99560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c57612b59575b50827f0000000000000000000000000000000000000000000000000000000000000000169151905190823b1561022157612b1f9260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff93600e986121c957506040519384931696169482612044565b806121d6612b6692610751565b38612ac8565b60405163056a947960e11b8152600e6004820152602490fd5b90612bb1612ba18461ffff166000526002602052604060002090565b6007600052602052604060002090565b54938415612d0057612bd46120a48561ffff166000526003602052604060002090565b612be9828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f00000000000000000000000000000000000000000000000000000000000000008616803b156102215787600093612c4d9560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c57612ced575b50827f0000000000000000000000000000000000000000000000000000000000000000169151905190823b1561022157612cb39260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff936007986121c957506040519384931696169482612044565b806121d6612cfa92610751565b38612c5c565b60405163056a947960e11b815260076004820152602490fd5b90612d45612d358461ffff166000526002602052604060002090565b600d600052602052604060002090565b54938415612e9457612d686120a48561ffff166000526003602052604060002090565b612d7d828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f00000000000000000000000000000000000000000000000000000000000000008616803b156102215787600093612de19560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c57612e81575b50827f0000000000000000000000000000000000000000000000000000000000000000169151905190823b1561022157612e479260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff93600d986121c957506040519384931696169482612044565b806121d6612e8e92610751565b38612df0565b60405163056a947960e11b8152600d6004820152602490fd5b90612ed9612ec98461ffff166000526002602052604060002090565b600b600052602052604060002090565b5493841561302857612efc6120a48561ffff166000526003602052604060002090565b612f11828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f00000000000000000000000000000000000000000000000000000000000000008616803b156102215787600093612f759560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c57613015575b50827f0000000000000000000000000000000000000000000000000000000000000000169151905190823b1561022157612fdb9260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff93600b986121c957506040519384931696169482612044565b806121d661302292610751565b38612f84565b60405163056a947960e11b8152600b6004820152602490fd5b6000546001600160a01b0316330361305557565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b604051906130a682610731565b60018252600360fc1b6020830152565b90816020910312610221575190565b91926130f261040296946130e46131009460a0875260a087019061162a565b90858203602087015261162a565b90838203604085015261162a565b926060820152608081840391015261162a565b919061315f60209261ffff83166000526003845261314c6131376040600020611f8f565b9361ffff166000526002602052604060002090565b9061ffff16600052602052604060002090565b549061318f83825192015192613173613099565b906040519687958695630135eaa760e41b8752600487016130c5565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610e6c576000916131cf575090565b610402915060203d6020116131f1575b6131e9818361077f565b8101906130b6565b503d6131df565b3d15613223573d90613209826107a0565b91613217604051938461077f565b82523d6000602084013e565b606090565b60405160208101908082106001600160401b0383111761074c576000938493848094938194604052525af161325b6131f8565b501561326357565b60405162461bcd60e51b815260206004820152603460248201527f5472616e7366657248656c7065723a3a736166655472616e736665724554483a60448201527308115512081d1c985b9cd9995c8819985a5b195960621b6064820152608490fd5b91909394926132df6132d78685611e2a565b5461ffff1690565b9461ffff8616156133e85761331c916133096120a48861ffff166000526003602052604060002090565b9360405193849160208301938491611e1c565b0392613330601f199485810183528261077f565b51902060208401516040516133598161334d60208201809561148d565b0386810183528261077f565b51902014159384613394575b50505050613382576115c79261337c9136916107bb565b90613968565b604051635bb95f3d60e11b8152600490fd5b6133b291929394506133be9060405192839160208301958691611e1c565b0384810183528261077f565b5190209151906133da604051918261114f60208201809661148d565b519020141538808080613365565b6040516378ccabe760e01b8152600490fd5b6001546040516321f8a72160e01b81526c2bb930b83832b229bcb73a343960991b600482015290602090829060249082906001600160a01b03165afa908115610e6c57600091613448575090565b90506020813d602011613475575b816134636020938361077f565b81010312610221575161040281610210565b3d9150613456565b6001546040516321f8a72160e01b81526524b9b9bab2b960d11b600482015290602090829060249082906001600160a01b03165afa908115610e6c57600091613448575090565b6001546040516321f8a72160e01b81526822bc31b430b733b2b960b91b600482015290602090829060249082906001600160a01b03165afa908115610e6c57600091613448575090565b6001546040516321f8a72160e01b815269053796e746872537761760b41b600482015290602090829060249082906001600160a01b03165afa908115610e6c57600091613448575090565b6001546040516321f8a72160e01b8152700a6f2dce8d0e4a6eec2e0aed2e8d088caf607b1b600482015290602090829060249082906001600160a01b03165afa908115610e6c57600091613448575090565b6001546040516321f8a72160e01b81527027b33321b430b4b722bc31b430b733b2b960791b600482015290602090829060249082906001600160a01b03165afa908115610e6c57600091613448575090565b6001546040516321f8a72160e01b815273233aba3ab932b9a6b0b935b2ba26b0b730b3b2b960611b600482015290602090829060249082906001600160a01b03165afa908115610e6c57600091613448575090565b61367f602093969594613663613099565b906040519889958695630135eaa760e41b8752600487016130c5565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa928315610e6c576000936136e7575b50828082106136c9575050565b6044925060405191631cf7a67960e11b835260048301526024820152fd5b61370191935060203d6020116131f1576131e9818361077f565b91386136bc565b51906115c782610226565b81601f82011215610221578051613729816107a0565b92613737604051948561077f565b8184526020828401011161022157610402916020808501910161146a565b9190916101008184031261022157805161376e81610226565b926020820151906001600160401b0382116102215761378e918301613713565b9160408201519160608101519160808201519160a08101519160e060c08301516137b781610226565b92015190565b91909161014081840312610221576137d481613708565b9260208201516001600160401b039081811161022157826137f6918501613713565b9360408401519360608101519360808201519360a08301519361381b60c08501613708565b9360e081015193610100820151848111610221578161383b918401613713565b93610120830151908111610221576104029201613713565b9360e095919361040298979360018060a01b03809616875260208701526040860152606085015260808401521660a08201528160c0820152019061162a565b90916060828403126102215781516138a981610226565b9260208301516001600160401b038111610221576040916137b7918501613713565b9190916080818403126102215780516138e381610226565b926020820151906001600160401b03821161022157613903918301613713565b916060604083015192015190565b909160e08284031261022157815161392881610226565b926020830151906001600160401b03821161022157613948918401613713565b9160408101519160608201519160808101519160c060a083015192015190565b906020908181019283519261ffff928385169460028614600014613a4457509461399a91866139a397510101906138cb565b92509590613f7f565b946139b2611e4e611e4e61347d565b91823b1561022157604051631a4ac9bf60e21b81526001600160a01b038816600482015260248101929092526044820152906000908290606490829084905af18015610e6c57613a31575b505b16916001600160a01b03167fa3a26805904503468e23304f9bd1cdaddc39bac907d3ce175f35a1d1771d9f93600080a4565b806121d6613a3e92610751565b386139fd565b60038603613add57509461399a9186613a6097510101906138cb565b94613a6f611e4e611e4e6133fa565b91823b15610221576040516358ff317f60e11b81526001600160a01b03881660048201819052602482015260448101929092526064820152906000908290818381608481015b03925af18015610e6c57613aca575b506139ff565b806121d6613ad792610751565b38613ac4565b60058603613b58575094613af99186613b069751010190613911565b5094509792915050613f7f565b94613b15611e4e611e4e6134c4565b91823b1561022157604051630a77839d60e11b81526001600160a01b03881660048201526024810192909252604482015290600090829081838160648101613ab5565b60068603613bd357509461399a9186613b7497510101906138cb565b94613b83611e4e611e4e6133fa565b91823b1561022157604051630533242960e31b81526001600160a01b038816600482015260248101929092526044820152906000908290606490829084905af18015610e6c57613aca57506139ff565b60078603613c4157509461399a9186613bef97510101906138cb565b94613bfe611e4e611e4e61347d565b91823b1561022157604051631a4ac9bf60e21b81526001600160a01b03881660048201526024810192909252604482015290600090829081838160648101613ab5565b600a8603613cca575094613c5d9186613c659751010190613892565b959150613f7f565b93613c74611e4e611e4e61347d565b803b1561022157604051631a4ac9bf60e21b81526001600160a01b0387166004820152631cd554d160e21b602482015260448101929092526000908290606490829084905af18015610e6c57613aca57506139ff565b600b8603613d6b575081613d37613d03613cef613d0b998486600097510101906137bd565b969850939b96915050979297969096613f7f565b9d8e93613f7f565b613d19611e4e611e4e61350e565b966040519a8b998a9889976314cf934360e11b895260048901613853565b03925af18015610e6c57613d4d575b50506139ff565b81613d6392903d10610e6557610e57818361077f565b503880613d46565b600c8603613e08575094613d879186613d969751010190613755565b50509390945097909197613f7f565b96613da5611e4e611e4e61350e565b90813b15610221576040516315491d7d60e21b81526001600160a01b038a166004820152602481019190915260448101929092526064820193909352608481019190915290600090829060a490829084905af18015610e6c57613aca57506139ff565b909590600d8603613e5c575081613d37613d03613cef600094848b613e309c510101906137bd565b613e3e611e4e611e4e61350e565b966040519a8b998a988997631077bc3b60e01b895260048901613853565b958296600e8714600014613ee65750613e8c918382613e7e9351010190613755565b5050929a9450949092613f7f565b9860008a613d37613ea1611e4e611e4e613559565b946040519889978896879563b4c4dff960e01b8752600487019192608093969594919660a084019760018060a01b031684526020840152604083015260608201520152565b91925090600f8603613f615750613e7e86928383613f079451010190613755565b9860008a613d37613f1c611e4e611e4e613559565b946040519889978896879563b9eacb7560e01b8752600487019192608093969594919660a084019760018060a01b031684526020840152604083015260608201520152565b604051634f18ccbb60e11b815261ffff919091166004820152602490fd5b6014815110613f92576020015160601c90565b60405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b6044820152606490fdfef34f07c5b9fc3912963edcdd4888dd8a9a13cd778c9451ca3f0335c2a32278fea26469706673582212206f366ecb69fa148e7327cfa4d94ab211d54c4c571a9b35f8c84d7216172e956064736f6c63430008180033000000000000000000000000e432150cce91c13a887f7d836923d5597add8e31000000000000000000000000be406f0189a0b4cf3a05c286473d23791dd44cc6
Deployed Bytecode
0x6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c806302de00921461020b5780630cf2abc6146102065780630f45ad4314610201578063116191b6146101fc5780631a98b2e0146101f75780631c4b995a146101f25780632abe893f146101ed5780632bb821bd146101e85780632c957005146101e35780632d89c635146101de57806338e4f064146101d9578063397b2b3a146101d457806349160658146101cf5780634fa34310146101ca5780636a22d8cc146101c55780636fcdef87146101c0578063715018a6146101bb57806380a2eb14146101b6578063863c576f146101b15780638cfd8f5c146101ac5780638da5cb5b146101a7578063af02b429146101a2578063bcc44cb11461019d578063cc9e3e8914610198578063dfb0b30f14610193578063e289c24a1461018e578063e4f84c3f14610189578063f2fde38b14610184578063f3e0893b1461017f578063f4a4229b1461017a5763f7736f3d0361000e576118ae565b6117f1565b611781565b6116ba565b61164f565b611526565b6114a4565b611445565b611354565b6112f8565b6112cf565b611274565b6111c8565b611097565b611039565b610f8d565b610f48565b610e71565b610d15565b610c92565b610b7d565b610998565b61096f565b6107f2565b61066a565b6105a3565b610514565b6104cf565b6104aa565b610405565b610269565b6001600160a01b0381160361022157565b600080fd5b61ffff81160361022157565b9181601f84011215610221578235916001600160401b038311610221576020838186019501011161022157565b8015150361022157565b6101403660031901126102215760043561028281610210565b60a43561028e81610226565b60e4359061029b82610210565b610104356001600160401b038111610221576102bb903690600401610232565b90926102c96101243561025f565b6102d233611e43565b156103c357604051606086901b6001600160601b031916602082015261037492610368906103389061034484603481015b0395610317601f199788810188528761077f565b604051938491602083016014916001600160601b03199060601b1681520190565b0386810184528361077f565b6040519788948860c435916084359060643590604435906024359060208c016119d3565b0390810184528361077f565b61ffff9161039461038e348560015460b01c168488612d19565b34611a7e565b926103b06103a960015461ffff9060b01c1690565b61ffff1690565b908316036103ba57005b61001993612d19565b604051632e79a65160e01b8152600490fd5b6080906003190112610221576004356103ed81610210565b9060243590604435906064356104028161025f565b90565b61040e366103d5565b5061041b92919233611e43565b156103c3576040516001600160601b0319606084901b16602082015260148152610019936104769261048d92601f1992909161045860348461077f565b604051958693600160208601526080604086015260a085019061162a565b91606084015260808301520390810183528261077f565b61ffff60015460b01c16903492612055565b600091031261022157565b3461022157600036600319011261022157602061ffff60015460b01c16604051908152f35b34610221576000366003190112610221576040517f000000000000000000000000e432150cce91c13a887f7d836923d5597add8e316001600160a01b03168152602090f35b346102215760c0366003190112610221576001600160401b0360243581811161022157610545903690600401610232565b6044358381116102215761055d903690600401610232565b60649291923585811161022157610578903690600401610232565b9160843596871161022157610594610019973690600401610232565b95909460a43597600435611aac565b34610221576060366003190112610221576004356105c081610210565b602435906105cd82610226565b6044356105d981610226565b6105e1613041565b600180546001600160a01b039093166001600160c01b031990931660b09490941b61ffff60b01b16939093179190911760a09190911b61ffff60a01b16179055005b6101009060031901126102215760043561063c81610210565b906024359060443590606435906084359060a43561065981610226565b9060c4359060e4356104028161025f565b61067336610623565b509290939161068133611e43565b156103c3576040516001600160601b0319606089901b166020820152601481526106cf94601f19949193610368939192889291906106c060348861077f565b6040519a8b9760208901611ba2565b61ffff916106e760015484349160b01c16838761220e565b340392348411610716576107038160015460b01c1661ffff1690565b9083160361070d57005b6100199361220e565b611a68565b634e487b7160e01b600052604160045260246000fd5b604081019081106001600160401b0382111761074c57604052565b61071b565b6001600160401b03811161074c57604052565b608081019081106001600160401b0382111761074c57604052565b90601f801991011681019081106001600160401b0382111761074c57604052565b6001600160401b03811161074c57601f01601f191660200190565b9291926107c7826107a0565b916107d5604051938461077f565b829481845281830111610221578281602093846000960137010152565b34610221576060366003190112610221576004356001600160401b0381116102215736602382011215610221576108cb6108c461083c6108db9336906024816004013591016107bb565b60243561084881610226565b61085e8160443561085881610226565b84613113565b91600061ffff8084169060058214918215610964575b8215610959575b821561094e575b8215610943575b8215610938575b821561092d575b5081610914575b5061090c575b6108df575b50506001546108be9060c01c61ffff166103a9565b90611c40565b6064900490565b6040519081529081906020820190565b0390f35b61090592916108ff916108f960015461ffff9060b01c1690565b90613113565b90611c33565b38806108a9565b5060016108a4565b905060015490808260b01c169160a01c1614153861089e565b600f14915038610897565b600e81149250610890565b600d81149250610889565b600c81149250610882565b600b8114925061087b565b600781149250610874565b34610221576000366003190112610221576001546040516001600160a01b039091168152602090f35b34610221576060366003190112610221576004356109b581610226565b6001600160401b03602435818111610221576109d5903690600401610232565b92604435838111610221576109ee903690600401610232565b946109f7613041565b604051610a0381610731565b610a0e3683876107bb565b8152610a1b3688856107bb565b6020966020830191825260009761ffff871689526003602052604089209351805192831161074c57610a5783610a51875461154b565b87611c53565b602091601f8411600114610ae05750899a9593610ab884610ac395610acf9a98956001957fe23d07b94549231dae818bc0a03de052bcbc3b986e7861d3c1ab2aed275a92f19f92610ad5575b50508160011b916000199060031b1c19161790565b83555b519101611ca9565b60405195869586611d72565b0390a180f35b015190503880610aa3565b9190601f198416610af687600052602060002090565b938c905b828210610b6557505084610acf9997946001947fe23d07b94549231dae818bc0a03de052bcbc3b986e7861d3c1ab2aed275a92f19e9f9a9894610ac398879510610b4c575b505050811b018355610abb565b015160001960f88460031b161c19169055388080610b3f565b80600186978294978701518155019601940190610afa565b3461022157604036600319011261022157600435610b9a81610210565b602435610ba5613041565b6001600160a01b038216610bbe57610019915033613228565b600091829182604051602081019263a9059cbb60e01b8452336024830152604482015260448152610bee81610764565b51925af1610bfa6131f8565b81610c63575b5015610c0857005b60405162461bcd60e51b815260206004820152602d60248201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260448201526c185b9cd9995c8819985a5b1959609a1b6064820152608490fd5b8051801592508215610c78575b505038610c00565b610c8b9250602080918301019101611a8b565b3880610c70565b610c9b366103d5565b50610ca892919233611e43565b156103c3576040516001600160601b0319606084901b166020820152601481526100199361047692610d0392601f19929091610ce560348461077f565b604051958693600460208601526080604086015260a085019061162a565b61ffff60015460b01c169034926123a2565b3461022157600319608036820112610221576004906001600160401b039060243582811161022157610d4a9036908501610232565b909260443581811161022157610d639036908701610232565b92909160643590811161022157610d7d9036908801610232565b9590946020610dd5610d90368a8a6107bb565b805190830120604051635f6970c360e01b81528b358c82015260806024820152938492839291610dc4608485018a8a6119b2565b908482030160448501528a8a6119b2565b6064830191909152038160007f000000000000000000000000e432150cce91c13a887f7d836923d5597add8e316001600160a01b03165af1908115610e6c57600091610e3d575b5015610e2c5761001996506132c5565b604051631403112d60e21b81528790fd5b610e5f915060203d602011610e65575b610e57818361077f565b810190611a8b565b38610e1c565b503d610e4d565b611aa0565b608036600319011261022157600435610e8981610210565b60243590610e9860643561025f565b610ea133611e43565b156103c3578115610f3757610f0b610f256100199360405180610ed986602083016014916001600160601b03199060601b1681520190565b0391610eed601f199384810184528361077f565b604051948592600960208501526080604085015260a084019061162a565b90606083015260443560808301520390810183528261077f565b60015460b01c61ffff16903492612535565b60405162da776760e51b8152600490fd5b34610221576000366003190112610221576040517f000000000000000000000000be406f0189a0b4cf3a05c286473d23791dd44cc66001600160a01b03168152602090f35b610f9636610623565b5092909391610fa433611e43565b156103c3576040516001600160601b0319606089901b16602082015260148152610ff294601f1994919361036893919288929190610fe360348861077f565b6040519a8b9760208901611be7565b61ffff9161100a60015484349160b01c1683876126c9565b340392348411610716576110268160015460b01c1661ffff1690565b9083160361103057005b610019936126c9565b346102215760008060031936011261109457611053613041565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b610140366003190112610221576004356110b081610210565b610104356110bd81610226565b6110c96101243561025f565b6110d233611e43565b156103c357806110f16110e960c43560a435611a7e565b606435611c33565b61ffff809216156111b5575b6040516001600160601b0319606086901b166020820152601481529061115b90601f199061112c60348561077f565b61114f8660405195869360e4359160843591604435916024359060208901611da2565b0390810183528261077f565b34926111716103a960015461ffff9060a01c1690565b9083811691820361119b575b5060015460b01c61ffff169283160361119257005b6100199361285d565b6111ae91945061038e903490848861285d565b923861117d565b60015490925060a01c61ffff16916110fd565b6111d136610623565b50929093916111df33611e43565b156103c3576040516001600160601b0319606089901b1660208201526014815261122d94601f199491936103689391928892919061121e60348861077f565b6040519a8b9760208901611c0d565b61ffff9161124560015484349160b01c1683876129f1565b340392348411610716576112618160015460b01c1661ffff1690565b9083160361126b57005b610019936129f1565b346102215760403660031901126102215760206112c660043561129681610226565b61ffff602435916112a683610226565b166000526002835260406000209061ffff16600052602052604060002090565b54604051908152f35b34610221576000366003190112610221576000546040516001600160a01b039091168152602090f35b346102215760203660031901126102215760043561131581610226565b606461ffff821610611342576001805461ffff60c01b191660c09290921b61ffff60c01b16919091179055005b60405163fccfd58b60e01b8152600490fd5b60a03660031901126102215760043561136c81610210565b60643561137881610226565b61138360843561025f565b61138c33611e43565b156103c35761ffff8082169182156114335761140e61038e82611405604051806113cb8a602083016014916001600160601b03199060601b1681520190565b03906113df601f199283810183528261077f565b6113f9604051978892604435906024359060208601611de8565b0390810186528561077f565b34908488612b85565b9261142060015461ffff9060b01c1690565b9283160361142a57005b61001993612b85565b604051636794524760e01b8152600490fd5b3461022157600036600319011261022157602061ffff60015460a01c16604051908152f35b60005b83811061147d5750506000910152565b818101518382015260200161146d565b906114a06020928281519485920161146a565b0190565b34610221576020366003190112610221576004356001600160401b03811161022157366023820112156102215761ffff61150360206114f06108db9436906024816004013591016107bb565b816040519382858094519384920161146a565b8101600481520301902054166040519182918291909161ffff6020820193169052565b3461022157600036600319011261022157602061ffff60015460c01c16604051908152f35b90600182811c9216801561157b575b602083101461156557565b634e487b7160e01b600052602260045260246000fd5b91607f169161155a565b906040519182600082546115988161154b565b9081845260209460019160018116908160001461160857506001146115c9575b5050506115c79250038361077f565b565b600090815285812095935091905b8183106115f05750506115c793508201013880806115b8565b855488840185015294850194879450918301916115d7565b925050506115c794925060ff191682840152151560051b8201013880806115b8565b906020916116438151809281855285808601910161146a565b601f01601f1916010190565b346102215760203660031901126102215761ffff60043561166f81610226565b1660005260036020526116ac60406000206108db611698600161169184611585565b9301611585565b60405193849360408552604085019061162a565b90838203602085015261162a565b34610221576020366003190112610221576004356116d781610210565b6116df613041565b6001600160a01b03908116801561172d57600080546001600160a01b03198116831782559092167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b34610221576040366003190112610221576004356001600160401b038111610221576117b461ffff913690600401610232565b60243592916020906117c585610226565b6117cd613041565b82604051938492833781016004815203019020911661ffff19825416179055600080f35b346102215760603660031901126102215760043561180e81610226565b6024359061181b82610226565b60443590611827613041565b811561189557916060917f9d5c7c0b934da8fefa9c7760c98383778a12dfbfc0c3b3106518f43fb9508ac09361ffff80911692836000526002602052826118808260406000209061ffff16600052602052604060002090565b556040519384521660208301526040820152a1005b6040516355b56ea760e01b815260048101839052602490fd5b610140366003190112610221576004356118c781610210565b60a4356118d381610226565b60e4356001600160401b038111610221576118f2903690600401610232565b6101049291923561190281610210565b61190e6101243561025f565b61191733611e43565b156103c357604051606086901b6001600160601b031916602082015261197092610368906103389061194c8460348101610303565b6040519788948860c435916084359060643590604435906024359060208c01611a3c565b61ffff9161198a61038e348560015460b01c168488612ead565b9261199f6103a960015461ffff9060b01c1690565b908316036119a957005b61001993612ead565b908060209392818452848401376000828201840152601f01601f1916010190565b98946104029a9894611a2d98946119ff61ffff9599948d61014090600d8152816020820152019061162a565b9860408d015260608c015260808b015260a08a01521660c088015260e08701528583036101008701526119b2565b9161012081840391015261162a565b98946104029a9894611a2d98946119ff61ffff9599948d61014090600b8152816020820152019061162a565b634e487b7160e01b600052601160045260246000fd5b9190820391821161071657565b9081602091031261022157516104028161025f565b6040513d6000823e3d90fd5b9592611b0e611ac860209a9499939b97611b22979636916107bb565b8a815191012094611afa6040519c8d9b8c9b631876eed960e01b8d5260048d015260c060248d015260c48c01916119b2565b9060031993848b84030160448c01526119b2565b9360648801528684030160848701526119b2565b60a4830191909152038160007f000000000000000000000000e432150cce91c13a887f7d836923d5597add8e316001600160a01b03165af1908115610e6c57600091611b83575b5015611b7157565b604051631403112d60e21b8152600490fd5b611b9c915060203d602011610e6557610e57818361077f565b38611b69565b9361ffff93611bc860e097939a9998949a610100600c89528060208a015288019061162a565b9960408701526060860152608085015260a08401521660c08201520152565b9361ffff93611bc860e097939a9998949a610100600f89528060208a015288019061162a565b9361ffff93611bc860e097939a9998949a610100600e89528060208a015288019061162a565b9190820180921161071657565b8181029291811591840414171561071657565b90601f8111611c6157505050565b6000916000526020600020906020601f850160051c83019410611c9f575b601f0160051c01915b828110611c9457505050565b818155600101611c88565b9092508290611c7f565b91909182516001600160401b03811161074c57611cd081611cca845461154b565b84611c53565b602080601f8311600114611d0757508190611d03939495600092610ad55750508160011b916000199060031b1c19161790565b9055565b90601f19831695611d1d85600052602060002090565b926000905b888210611d5a57505083600195969710611d41575b505050811b019055565b015160001960f88460031b161c19169055388080611d37565b80600185968294968601518155019501930190611d22565b9391610402959361ffff611d94931686526060602087015260608601916119b2565b9260408185039101526119b2565b95919796929361ffff94611dc860e0979361010060058b528060208c01528a019061162a565b9960408901526060880152608087015260a086015260c085015216910152565b92936080929594611e0b61ffff936007875260a0602088015260a087019061162a565b966040860152606085015216910152565b908092918237016000815290565b6020908260405193849283378101600481520301902090565b611e5a611e4e6133fa565b6001600160a01b031690565b6001600160a01b03821690811491908215611f7a575b8215611f65575b8215611f50575b8215611f3b575b8215611f26575b8215611f10575b508115611e9e575090565b611ee19150602090611eb4611e4e611e4e6135fd565b6040516308651a8360e31b81526001600160a01b0390921660048301529092839190829081906024820190565b03915afa908115610e6c57600091611ef7575090565b610402915060203d602011610e6557610e57818361077f565b909150611f1e611e4e6135fd565b149038611e93565b9150611f33611e4e6135ab565b821491611e8c565b9150611f48611e4e613559565b821491611e85565b9150611f5d611e4e61350e565b821491611e7e565b9150611f72611e4e6134c4565b821491611e77565b9150611f87611e4e61347d565b821491611e70565b90604051611f9c81610731565b6020611fb660018395611fae81611585565b855201611585565b910152565b93611ff8608094611fea612006949599989960018060a01b03809716895260a060208a015260a089019061162a565b90878203604089015261162a565b90858203606087015261162a565b9416910152565b9161203690612028610402959360608652606086019061162a565b90848203602086015261162a565b91604081840391015261162a565b90602061040292818152019061162a565b906120816120718461ffff166000526002602052604060002090565b6001600052602052604060002090565b549384156121f5576120a96120a48561ffff166000526003602052604060002090565b611f8f565b6120be828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f000000000000000000000000be406f0189a0b4cf3a05c286473d23791dd44cc68616803b1561022157876000936121229560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c576121e2575b50827f000000000000000000000000e432150cce91c13a887f7d836923d5597add8e31169151905190823b15610221576121889260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff936001986121c9575b506040519384931696169482612044565b0390a490565b806121d66121dc92610751565b8061049f565b386121b2565b806121d66121ef92610751565b38612131565b60405163056a947960e11b815260016004820152602490fd5b9061223a61222a8461ffff166000526002602052604060002090565b600c600052602052604060002090565b549384156123895761225d6120a48561ffff166000526003602052604060002090565b612272828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f000000000000000000000000be406f0189a0b4cf3a05c286473d23791dd44cc68616803b1561022157876000936122d69560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c57612376575b50827f000000000000000000000000e432150cce91c13a887f7d836923d5597add8e31169151905190823b156102215761233c9260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff93600c986121c957506040519384931696169482612044565b806121d661238392610751565b386122e5565b60405163056a947960e11b8152600c6004820152602490fd5b906123ce6123be8461ffff166000526002602052604060002090565b6004600052602052604060002090565b5493841561251d576123f16120a48561ffff166000526003602052604060002090565b612406828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f000000000000000000000000be406f0189a0b4cf3a05c286473d23791dd44cc68616803b15610221578760009361246a9560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c5761250a575b50827f000000000000000000000000e432150cce91c13a887f7d836923d5597add8e31169151905190823b15610221576124d09260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff936004986121c957506040519384931696169482612044565b806121d661251792610751565b38612479565b60405163056a947960e11b8152600480820152602490fd5b906125616125518461ffff166000526002602052604060002090565b6009600052602052604060002090565b549384156126b0576125846120a48561ffff166000526003602052604060002090565b612599828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f000000000000000000000000be406f0189a0b4cf3a05c286473d23791dd44cc68616803b1561022157876000936125fd9560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c5761269d575b50827f000000000000000000000000e432150cce91c13a887f7d836923d5597add8e31169151905190823b15610221576126639260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff936009986121c957506040519384931696169482612044565b806121d66126aa92610751565b3861260c565b60405163056a947960e11b815260096004820152602490fd5b906126f56126e58461ffff166000526002602052604060002090565b600f600052602052604060002090565b54938415612844576127186120a48561ffff166000526003602052604060002090565b61272d828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f000000000000000000000000be406f0189a0b4cf3a05c286473d23791dd44cc68616803b1561022157876000936127919560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c57612831575b50827f000000000000000000000000e432150cce91c13a887f7d836923d5597add8e31169151905190823b15610221576127f79260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff93600f986121c957506040519384931696169482612044565b806121d661283e92610751565b386127a0565b60405163056a947960e11b8152600f6004820152602490fd5b906128896128798461ffff166000526002602052604060002090565b6005600052602052604060002090565b549384156129d8576128ac6120a48561ffff166000526003602052604060002090565b6128c1828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f000000000000000000000000be406f0189a0b4cf3a05c286473d23791dd44cc68616803b1561022157876000936129259560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c576129c5575b50827f000000000000000000000000e432150cce91c13a887f7d836923d5597add8e31169151905190823b156102215761298b9260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff936005986121c957506040519384931696169482612044565b806121d66129d292610751565b38612934565b60405163056a947960e11b815260056004820152602490fd5b90612a1d612a0d8461ffff166000526002602052604060002090565b600e600052602052604060002090565b54938415612b6c57612a406120a48561ffff166000526003602052604060002090565b612a55828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f000000000000000000000000be406f0189a0b4cf3a05c286473d23791dd44cc68616803b156102215787600093612ab99560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c57612b59575b50827f000000000000000000000000e432150cce91c13a887f7d836923d5597add8e31169151905190823b1561022157612b1f9260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff93600e986121c957506040519384931696169482612044565b806121d6612b6692610751565b38612ac8565b60405163056a947960e11b8152600e6004820152602490fd5b90612bb1612ba18461ffff166000526002602052604060002090565b6007600052602052604060002090565b54938415612d0057612bd46120a48561ffff166000526003602052604060002090565b612be9828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f000000000000000000000000be406f0189a0b4cf3a05c286473d23791dd44cc68616803b156102215787600093612c4d9560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c57612ced575b50827f000000000000000000000000e432150cce91c13a887f7d836923d5597add8e31169151905190823b1561022157612cb39260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff936007986121c957506040519384931696169482612044565b806121d6612cfa92610751565b38612c5c565b60405163056a947960e11b815260076004820152602490fd5b90612d45612d358461ffff166000526002602052604060002090565b600d600052602052604060002090565b54938415612e9457612d686120a48561ffff166000526003602052604060002090565b612d7d828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f000000000000000000000000be406f0189a0b4cf3a05c286473d23791dd44cc68616803b156102215787600093612de19560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c57612e81575b50827f000000000000000000000000e432150cce91c13a887f7d836923d5597add8e31169151905190823b1561022157612e479260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff93600d986121c957506040519384931696169482612044565b806121d6612e8e92610751565b38612df0565b60405163056a947960e11b8152600d6004820152602490fd5b90612ed9612ec98461ffff166000526002602052604060002090565b600b600052602052604060002090565b5493841561302857612efc6120a48561ffff166000526003602052604060002090565b612f11828251978560208501998a5190613652565b8151875191976001600160a01b03949092917f000000000000000000000000be406f0189a0b4cf3a05c286473d23791dd44cc68616803b156102215787600093612f759560405196879586948593630c93e3bb60e01b855230923060048701611fbb565b03925af18015610e6c57613015575b50827f000000000000000000000000e432150cce91c13a887f7d836923d5597add8e31169151905190823b1561022157612fdb9260009283879360405196879586948593631c92115f60e01b85526004850161200d565b03925af1948515610e6c576121c3600080516020613fd08339815191529361ffff93600b986121c957506040519384931696169482612044565b806121d661302292610751565b38612f84565b60405163056a947960e11b8152600b6004820152602490fd5b6000546001600160a01b0316330361305557565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b604051906130a682610731565b60018252600360fc1b6020830152565b90816020910312610221575190565b91926130f261040296946130e46131009460a0875260a087019061162a565b90858203602087015261162a565b90838203604085015261162a565b926060820152608081840391015261162a565b919061315f60209261ffff83166000526003845261314c6131376040600020611f8f565b9361ffff166000526002602052604060002090565b9061ffff16600052602052604060002090565b549061318f83825192015192613173613099565b906040519687958695630135eaa760e41b8752600487016130c5565b03817f000000000000000000000000be406f0189a0b4cf3a05c286473d23791dd44cc66001600160a01b03165afa908115610e6c576000916131cf575090565b610402915060203d6020116131f1575b6131e9818361077f565b8101906130b6565b503d6131df565b3d15613223573d90613209826107a0565b91613217604051938461077f565b82523d6000602084013e565b606090565b60405160208101908082106001600160401b0383111761074c576000938493848094938194604052525af161325b6131f8565b501561326357565b60405162461bcd60e51b815260206004820152603460248201527f5472616e7366657248656c7065723a3a736166655472616e736665724554483a60448201527308115512081d1c985b9cd9995c8819985a5b195960621b6064820152608490fd5b91909394926132df6132d78685611e2a565b5461ffff1690565b9461ffff8616156133e85761331c916133096120a48861ffff166000526003602052604060002090565b9360405193849160208301938491611e1c565b0392613330601f199485810183528261077f565b51902060208401516040516133598161334d60208201809561148d565b0386810183528261077f565b51902014159384613394575b50505050613382576115c79261337c9136916107bb565b90613968565b604051635bb95f3d60e11b8152600490fd5b6133b291929394506133be9060405192839160208301958691611e1c565b0384810183528261077f565b5190209151906133da604051918261114f60208201809661148d565b519020141538808080613365565b6040516378ccabe760e01b8152600490fd5b6001546040516321f8a72160e01b81526c2bb930b83832b229bcb73a343960991b600482015290602090829060249082906001600160a01b03165afa908115610e6c57600091613448575090565b90506020813d602011613475575b816134636020938361077f565b81010312610221575161040281610210565b3d9150613456565b6001546040516321f8a72160e01b81526524b9b9bab2b960d11b600482015290602090829060249082906001600160a01b03165afa908115610e6c57600091613448575090565b6001546040516321f8a72160e01b81526822bc31b430b733b2b960b91b600482015290602090829060249082906001600160a01b03165afa908115610e6c57600091613448575090565b6001546040516321f8a72160e01b815269053796e746872537761760b41b600482015290602090829060249082906001600160a01b03165afa908115610e6c57600091613448575090565b6001546040516321f8a72160e01b8152700a6f2dce8d0e4a6eec2e0aed2e8d088caf607b1b600482015290602090829060249082906001600160a01b03165afa908115610e6c57600091613448575090565b6001546040516321f8a72160e01b81527027b33321b430b4b722bc31b430b733b2b960791b600482015290602090829060249082906001600160a01b03165afa908115610e6c57600091613448575090565b6001546040516321f8a72160e01b815273233aba3ab932b9a6b0b935b2ba26b0b730b3b2b960611b600482015290602090829060249082906001600160a01b03165afa908115610e6c57600091613448575090565b61367f602093969594613663613099565b906040519889958695630135eaa760e41b8752600487016130c5565b03817f000000000000000000000000be406f0189a0b4cf3a05c286473d23791dd44cc66001600160a01b03165afa928315610e6c576000936136e7575b50828082106136c9575050565b6044925060405191631cf7a67960e11b835260048301526024820152fd5b61370191935060203d6020116131f1576131e9818361077f565b91386136bc565b51906115c782610226565b81601f82011215610221578051613729816107a0565b92613737604051948561077f565b8184526020828401011161022157610402916020808501910161146a565b9190916101008184031261022157805161376e81610226565b926020820151906001600160401b0382116102215761378e918301613713565b9160408201519160608101519160808201519160a08101519160e060c08301516137b781610226565b92015190565b91909161014081840312610221576137d481613708565b9260208201516001600160401b039081811161022157826137f6918501613713565b9360408401519360608101519360808201519360a08301519361381b60c08501613708565b9360e081015193610100820151848111610221578161383b918401613713565b93610120830151908111610221576104029201613713565b9360e095919361040298979360018060a01b03809616875260208701526040860152606085015260808401521660a08201528160c0820152019061162a565b90916060828403126102215781516138a981610226565b9260208301516001600160401b038111610221576040916137b7918501613713565b9190916080818403126102215780516138e381610226565b926020820151906001600160401b03821161022157613903918301613713565b916060604083015192015190565b909160e08284031261022157815161392881610226565b926020830151906001600160401b03821161022157613948918401613713565b9160408101519160608201519160808101519160c060a083015192015190565b906020908181019283519261ffff928385169460028614600014613a4457509461399a91866139a397510101906138cb565b92509590613f7f565b946139b2611e4e611e4e61347d565b91823b1561022157604051631a4ac9bf60e21b81526001600160a01b038816600482015260248101929092526044820152906000908290606490829084905af18015610e6c57613a31575b505b16916001600160a01b03167fa3a26805904503468e23304f9bd1cdaddc39bac907d3ce175f35a1d1771d9f93600080a4565b806121d6613a3e92610751565b386139fd565b60038603613add57509461399a9186613a6097510101906138cb565b94613a6f611e4e611e4e6133fa565b91823b15610221576040516358ff317f60e11b81526001600160a01b03881660048201819052602482015260448101929092526064820152906000908290818381608481015b03925af18015610e6c57613aca575b506139ff565b806121d6613ad792610751565b38613ac4565b60058603613b58575094613af99186613b069751010190613911565b5094509792915050613f7f565b94613b15611e4e611e4e6134c4565b91823b1561022157604051630a77839d60e11b81526001600160a01b03881660048201526024810192909252604482015290600090829081838160648101613ab5565b60068603613bd357509461399a9186613b7497510101906138cb565b94613b83611e4e611e4e6133fa565b91823b1561022157604051630533242960e31b81526001600160a01b038816600482015260248101929092526044820152906000908290606490829084905af18015610e6c57613aca57506139ff565b60078603613c4157509461399a9186613bef97510101906138cb565b94613bfe611e4e611e4e61347d565b91823b1561022157604051631a4ac9bf60e21b81526001600160a01b03881660048201526024810192909252604482015290600090829081838160648101613ab5565b600a8603613cca575094613c5d9186613c659751010190613892565b959150613f7f565b93613c74611e4e611e4e61347d565b803b1561022157604051631a4ac9bf60e21b81526001600160a01b0387166004820152631cd554d160e21b602482015260448101929092526000908290606490829084905af18015610e6c57613aca57506139ff565b600b8603613d6b575081613d37613d03613cef613d0b998486600097510101906137bd565b969850939b96915050979297969096613f7f565b9d8e93613f7f565b613d19611e4e611e4e61350e565b966040519a8b998a9889976314cf934360e11b895260048901613853565b03925af18015610e6c57613d4d575b50506139ff565b81613d6392903d10610e6557610e57818361077f565b503880613d46565b600c8603613e08575094613d879186613d969751010190613755565b50509390945097909197613f7f565b96613da5611e4e611e4e61350e565b90813b15610221576040516315491d7d60e21b81526001600160a01b038a166004820152602481019190915260448101929092526064820193909352608481019190915290600090829060a490829084905af18015610e6c57613aca57506139ff565b909590600d8603613e5c575081613d37613d03613cef600094848b613e309c510101906137bd565b613e3e611e4e611e4e61350e565b966040519a8b998a988997631077bc3b60e01b895260048901613853565b958296600e8714600014613ee65750613e8c918382613e7e9351010190613755565b5050929a9450949092613f7f565b9860008a613d37613ea1611e4e611e4e613559565b946040519889978896879563b4c4dff960e01b8752600487019192608093969594919660a084019760018060a01b031684526020840152604083015260608201520152565b91925090600f8603613f615750613e7e86928383613f079451010190613755565b9860008a613d37613f1c611e4e611e4e613559565b946040519889978896879563b9eacb7560e01b8752600487019192608093969594919660a084019760018060a01b031684526020840152604083015260608201520152565b604051634f18ccbb60e11b815261ffff919091166004820152602490fd5b6014815110613f92576020015160601c90565b60405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b6044820152606490fdfef34f07c5b9fc3912963edcdd4888dd8a9a13cd778c9451ca3f0335c2a32278fea26469706673582212206f366ecb69fa148e7327cfa4d94ab211d54c4c571a9b35f8c84d7216172e956064736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000e432150cce91c13a887f7d836923d5597add8e31000000000000000000000000be406f0189a0b4cf3a05c286473d23791dd44cc6
-----Decoded View---------------
Arg [0] : _selfAxelarGateway (address): 0xe432150cce91c13a887f7D836923d5597adD8E31
Arg [1] : _selfGasReceiver (address): 0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000e432150cce91c13a887f7d836923d5597add8e31
Arg [1] : 000000000000000000000000be406f0189a0b4cf3a05c286473d23791dd44cc6
Loading...
Loading
[ Download: CSV Export ]
[ 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.