Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
MagpieCelerBridgeV2
Compiler Version
v0.8.24+commit.e11b9ed9
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {Ownable2Step} from "openzeppelin-solidity/contracts/access/Ownable2Step.sol"; import {Pausable} from "openzeppelin-solidity/contracts/security/Pausable.sol"; import {Address} from "openzeppelin-solidity/contracts/utils/Address.sol"; import {IMagpieCelerBridgeV2} from "./interfaces/IMagpieCelerBridgeV2.sol"; import {ILiquidityBridge} from "./interfaces/celer/ILiquidityBridge.sol"; import {IMessageBus} from "./interfaces/celer/IMessageBus.sol"; import {LibAsset} from "./libraries/LibAsset.sol"; import {LibBridge, DepositData, SwapData} from "./libraries/LibBridge.sol"; import {LibRouter, SwapData} from "./libraries/LibRouter.sol"; error InvalidCaller(); error ReentrancyError(); error DepositIsNotFound(); error InvalidRefundAddress(); error InvalidAddress(); error NotSupportedAsset(); contract MagpieCelerBridgeV2 is IMagpieCelerBridgeV2, Ownable2Step, Pausable { using LibAsset for address; mapping(address => bool) public internalCaller; address public weth; bytes32 public networkIdAndRouterAddress; uint64 public swapSequence; mapping(bytes32 => mapping(address => uint256)) public deposit; mapping(bytes32 => address) public refundAddresses; address public swapFeeAddress; address public celerAddress; /// @dev Restricts swap functions with signatures to only be called by whitelisted internal caller. modifier onlyInternalCaller() { if (!internalCaller[msg.sender]) { revert InvalidCaller(); } _; } /// @dev Restricts functions to only be called by the Celer Network. modifier onlyCeler() { require(msg.sender == celerAddress); _; } /// @dev See {IMagpieCelerBridgeV2-updateInternalCaller} function updateInternalCaller(address caller, bool value) external onlyOwner { internalCaller[caller] = value; emit UpdateInternalCaller(msg.sender, caller, value); } /// @dev See {IMagpieCelerBridgeV2-updateWeth} function updateWeth(address value) external onlyOwner { weth = value; } /// @dev See {IMagpieCelerBridgeV2-updateNetworkIdAndRouterAddress} function updateNetworkIdAndRouterAddress(bytes32 value) external onlyOwner { networkIdAndRouterAddress = value; } /// @dev See {IMagpieCelerBridgeV2-updateSwapFeeAddress} function updateSwapFeeAddress(address value) external onlyOwner { swapFeeAddress = value; } /// @dev See {IMagpieCelerBridgeV2-updateCelerAddress} function updateCelerAddress(address value) external onlyOwner { celerAddress = value; } /// @dev See {IMagpieCelerBridgeV2-pause} function pause() public onlyOwner whenNotPaused { _pause(); } /// @dev See {IMagpieCelerBridgeV2-unpause} function unpause() public onlyOwner whenPaused { _unpause(); } /// @dev See {IMagpieCelerBridgeV2-swapInWithMagpieSignature} function swapInWithMagpieSignature(bytes calldata) external payable whenNotPaused returns (uint256 amountOut) { SwapData memory swapData = LibRouter.getData(); amountOut = swapIn(swapData, true); } /// @dev See {IMagpieCelerBridgeV2-swapInWithUserSignature} function swapInWithUserSignature(bytes calldata) external payable onlyInternalCaller returns (uint256 amountOut) { SwapData memory swapData = LibRouter.getData(); if (swapData.fromAssetAddress.isNative()) { revert InvalidAddress(); } amountOut = swapIn(swapData, false); } /// @dev Verifies the signature for a swap operation. /// @param swapData The SwapData struct containing swap details. /// @param useCaller Flag indicating whether to use the caller's address for verification. /// @return signer The address of the signer if the signature is valid. function verifySignature(SwapData memory swapData, bool useCaller) private view returns (address) { uint256 messagePtr; bool hasAffiliate = swapData.hasAffiliate; uint256 swapMessageLength = hasAffiliate ? 384 : 320; uint256 messageLength = swapMessageLength + 288; assembly { messagePtr := mload(0x40) mstore(0x40, add(messagePtr, messageLength)) // hasAffiliate switch hasAffiliate case 1 { // keccak256("Swap(address srcBridge,address srcSender, address srcRecipient,address srcFromAsset,address srcToAsset,uint256 srcDeadline,uint256 srcAmountOutMin,uint256 srcSwapFee,uint256 srcAmountIn,address affiliate,uint256 affiliateFee,bytes32 dstRecipient,bytes32 dstFromAsset,bytes32 dstToAsset,uint256 dstAmountOutMin,uint256 dstSwapFee,uint16 dstNetworkId,bytes32 dstBridge,uint64 bridgeChainId,uint32 bridgeSlippage)") mstore(messagePtr, 0xf460c1fcb477125b9e886fa605d6b560754b3f80a9479e5af7376cf97931c2e5) } default { // keccak256("Swap(address srcBridge,address srcSender,address srcRecipient,address srcFromAsset,address srcToAsset,uint256 srcDeadline,uint256 srcAmountOutMin,uint256 srcSwapFee,uint256 srcAmountIn,bytes32 dstRecipient,bytes32 dstFromAsset,bytes32 dstToAsset,uint256 dstAmountOutMin,uint256 dstSwapFee,uint16 dstNetworkId,bytes32 dstBridge,uint64 bridgeChainId,uint32 bridgeSlippage)") mstore(messagePtr, 0x3561ed9db327f5071ddfd91adcdffcd542e94248fbe7d8b901a0f7c72af6054f) } let bridgeDataPosition := shr(240, calldataload(add(66, calldataload(36)))) let currentMessagePtr := add(messagePtr, swapMessageLength) mstore(currentMessagePtr, calldataload(bridgeDataPosition)) // toAddress currentMessagePtr := add(currentMessagePtr, 32) mstore(currentMessagePtr, calldataload(add(bridgeDataPosition, 32))) // fromAssetAddress currentMessagePtr := add(currentMessagePtr, 32) mstore(currentMessagePtr, calldataload(add(bridgeDataPosition, 64))) // toAssetAddress currentMessagePtr := add(currentMessagePtr, 32) mstore(currentMessagePtr, calldataload(add(bridgeDataPosition, 96))) // amountOutMin currentMessagePtr := add(currentMessagePtr, 32) mstore(currentMessagePtr, calldataload(add(bridgeDataPosition, 128))) // swapFee currentMessagePtr := add(currentMessagePtr, 32) mstore(currentMessagePtr, shr(240, calldataload(add(bridgeDataPosition, 160)))) // recipientNetworkId currentMessagePtr := add(currentMessagePtr, 32) mstore(currentMessagePtr, calldataload(add(bridgeDataPosition, 162))) // recipientAddress currentMessagePtr := add(currentMessagePtr, 32) mstore(currentMessagePtr, shr(192, calldataload(add(bridgeDataPosition, 194)))) // chainId currentMessagePtr := add(currentMessagePtr, 32) mstore(currentMessagePtr, shr(224, calldataload(add(bridgeDataPosition, 202)))) // slippage } return LibRouter.verifySignature( // keccak256(bytes("Magpie Celer Bridge")), 0x6ca9b0af27e81464d2ba2736dc23311469e9de96c72259b0fed3c28cca16f08c, // keccak256(bytes("2")), 0xad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5, swapData, messagePtr, messageLength, useCaller, 2 ); } /// @dev Executes an inbound swap operation. /// @param useCaller Flag indicating whether to use the caller's address for the swap. /// @return amountOut The amount received as output from the swap operation. function swapIn(SwapData memory swapData, bool useCaller) private returns (uint256 amountOut) { if (swapData.toAssetAddress.isNative()) { revert NotSupportedAsset(); } swapSequence++; uint64 currentSwapSequence = swapSequence; uint16 networkId; address routerAddress; assembly { let currentNetworkIdAndRouterAddress := sload(networkIdAndRouterAddress.slot) networkId := shr(240, currentNetworkIdAndRouterAddress) routerAddress := shr(16, shl(16, currentNetworkIdAndRouterAddress)) } address fromAddress = verifySignature(swapData, useCaller); if (swapData.hasPermit) { LibRouter.permit(swapData, fromAddress); } LibRouter.transferFees(swapData, fromAddress, swapData.swapFee == 0 ? address(0) : swapFeeAddress); bytes memory encodedDepositData = new bytes(236); // 194 + 42 LibBridge.fillEncodedDepositData(encodedDepositData, networkId, currentSwapSequence); bytes32 depositDataHash = keccak256(encodedDepositData); refundAddresses[depositDataHash] = fromAddress; amountOut = LibBridge.swapIn(swapData, encodedDepositData, fromAddress, routerAddress, weth); bridgeIn(LibBridge.getFee(swapData), swapData.toAssetAddress, amountOut, depositDataHash, currentSwapSequence); if (currentSwapSequence != swapSequence) { revert ReentrancyError(); } } /// @dev Bridges an inbound asset transfer into the contract. /// @param bridgeFee Bridge fee that has to be payed in native token. /// @param toAssetAddress The address of the asset being bridged into. /// @param amount The amount of the asset being transferred into the contract. /// @param depositDataHash Encoded hash related to the crosschain transaction. /// @param currentSwapSequence Increased swapSequence. function bridgeIn( uint256 bridgeFee, address toAssetAddress, uint256 amount, bytes32 depositDataHash, uint64 currentSwapSequence ) private { IMessageBus messageBus = IMessageBus(celerAddress); address liquidityBridgeAddress = messageBus.liquidityBridge(); toAssetAddress.approve(liquidityBridgeAddress, amount); address receiver; uint64 chainId; uint32 slippage; assembly { let bridgeDataPosition := shr(240, calldataload(add(66, calldataload(36)))) receiver := calldataload(add(bridgeDataPosition, 162)) chainId := shr(192, calldataload(add(bridgeDataPosition, 194))) slippage := shr(224, calldataload(add(bridgeDataPosition, 202))) } ILiquidityBridge(liquidityBridgeAddress).send( receiver, toAssetAddress, amount, chainId, currentSwapSequence, slippage ); bytes32 transferId = keccak256( abi.encodePacked( address(this), receiver, toAssetAddress, amount, chainId, currentSwapSequence, uint64(block.chainid) ) ); messageBus.sendMessageWithTransfer{value: bridgeFee}( receiver, chainId, liquidityBridgeAddress, transferId, LibBridge.encodeDepositDataHash(depositDataHash) ); } /// @dev See {IMagpieCelerBridgeV2-swapOut} function swapOut(bytes calldata) external onlyInternalCaller returns (uint256 amountOut) { address routerAddress; uint16 networkId; assembly { let currentNetworkIdAndRouterAddress := sload(networkIdAndRouterAddress.slot) networkId := shr(240, currentNetworkIdAndRouterAddress) routerAddress := shr(16, shl(16, currentNetworkIdAndRouterAddress)) } SwapData memory swapData = LibRouter.getData(); bytes32 depositDataHash = LibBridge.getDepositDataHash(swapData, networkId, address(this)); uint256 depositAmount = deposit[depositDataHash][swapData.fromAssetAddress]; if (depositAmount > 0) { deposit[depositDataHash][swapData.fromAssetAddress] = 0; } else if (swapData.fromAssetAddress.isNative()) { // If celer changes the mapping it makes sure that the user can still swap the from asset as native token depositAmount = deposit[depositDataHash][weth]; if (depositAmount == 0) { revert DepositIsNotFound(); } weth.unwrap(depositAmount); deposit[depositDataHash][weth] = 0; } else { revert DepositIsNotFound(); } amountOut = LibBridge.swapOut(swapData, depositAmount, depositDataHash, routerAddress, weth, swapFeeAddress); } event Deposit(bytes32 depositDataHash, uint256 amount); /// @dev See {IMagpieCelerBridge2-executeMessageWithTransfer} function executeMessageWithTransfer( address, address assetAddress, uint256 amount, uint64, bytes calldata payload, address ) external payable onlyCeler returns (IMessageBus.TxStatus) { bytes32 depositDataHash = LibBridge.decodeDepositDataHash(payload); deposit[depositDataHash][assetAddress] += amount; emit Deposit(depositDataHash, deposit[depositDataHash][assetAddress]); return IMessageBus.TxStatus.Success; } event Refund(address indexed recipient, address indexed assetAddress, bytes32 depositDataHash, uint256 amount); /// @dev See {IMagpieCelerBridgeV2-executeMessageWithTransferRefund} function executeMessageWithTransferRefund( address assetAddress, uint256 amount, bytes calldata payload, address ) external payable onlyCeler returns (IMessageBus.TxStatus) { bytes32 depositDataHash = LibBridge.decodeDepositDataHash(payload); address receiver = refundAddresses[depositDataHash]; if (receiver == address(0)) { revert InvalidRefundAddress(); } refundAddresses[depositDataHash] = address(0); if (msg.value >= amount) { assetAddress = address(0); } assetAddress.transfer(receiver, amount); emit Refund(receiver, assetAddress, depositDataHash, amount); return IMessageBus.TxStatus.Success; } /// @dev See {IMagpieCelerBridgeV2-multicall} function multicall(bytes[] calldata data) external onlyOwner returns (bytes[] memory results) { results = new bytes[](data.length); for (uint256 i = 0; i < data.length; i++) { results[i] = Address.functionDelegateCall(address(this), data[i]); } return results; } /// @dev Used to receive ethers receive() external payable {} }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; interface IBridge { event SwapIn( address indexed fromAddress, address indexed toAddress, address fromAssetAddress, address toAssetAddress, uint256 amountIn, uint256 amountOut, bytes encodedDepositData ); event SwapOut( address indexed fromAddress, address indexed toAddress, address fromAssetAddress, address toAssetAddress, uint256 amountIn, uint256 amountOut, bytes32 depositDataHash ); event UpdateInternalCaller(address indexed sender, address caller, bool value); /// @dev Allows the owner to update the whitelisted internal callers. /// @param caller Caller address. /// @param value Disable or enable the related caller. function updateInternalCaller(address caller, bool value) external; /// @dev Allows the owner to update weth. /// @param value New weth address. function updateWeth(address value) external; /// @dev Allows the owner to update Magpie networkId and routerAddress. /// @param value Compressed networkId and routerAddress. function updateNetworkIdAndRouterAddress(bytes32 value) external; /// @dev Makes it possible to execute multiple functions in the same transaction. function multicall(bytes[] calldata data) external returns (bytes[] memory results); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {IMessageBus} from "./celer/IMessageBus.sol"; import {IBridge} from "./IBridge.sol"; interface IMagpieCelerBridgeV2 is IBridge { /// @dev Allows the owner to update the swap fee receiver. /// @param value Swap fee receiver address. function updateSwapFeeAddress(address value) external; /// @dev Allows the owner to update Celer address. /// @param value New celerAddress. function updateCelerAddress(address value) external; /// @dev Called by the owner to pause, triggers stopped state. function pause() external; /// @dev Called by the owner to unpause, returns to normal state. function unpause() external; /// @dev Allows Celer Network to transfer and update the deposited amounts accordingly. function executeMessageWithTransfer( address, address, uint256 amount, uint64, bytes calldata payload, address ) external payable returns (IMessageBus.TxStatus); /// @dev Allows Celer Network to manage refunds to the designated recipient. function executeMessageWithTransferRefund( address, uint256 amount, bytes calldata payload, address ) external payable returns (IMessageBus.TxStatus); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; interface IMagpieRouterV3 { event UpdateInternalCaller(address indexed sender, address caller, bool value); /// @dev Allows the owner to update the whitelisted internal callers. /// @param caller Caller address. /// @param value Disable or enable the related caller. function updateInternalCaller(address caller, bool value) external; event UpdateBridge(address indexed sender, address caller, bool value); /// @dev Allows the owner to update the whitelisted bridges. /// @param caller Caller address. /// @param value Disable or enable the related caller. function updateBridge(address caller, bool value) external; /// @dev Allows the owner to update the swap fee receiver. /// @param value Swap fee receiver address. function updateSwapFeeAddress(address value) external; /// @dev Called by the owner to pause, triggers stopped state. function pause() external; /// @dev Called by the owner to unpause, returns to normal state. function unpause() external; event Swap( address indexed fromAddress, address indexed toAddress, address fromAssetAddress, address toAssetAddress, uint256 amountIn, uint256 amountOut ); /// @dev Makes it possible to execute multiple functions in the same transaction. function multicall(bytes[] calldata data) external returns (bytes[] memory results); /// @dev Provides an external interface to estimate the gas cost of the last hop in a route. /// @return amountOut The amount received after swapping. /// @return gasUsed The cost of gas while performing the swap. function estimateSwapGas(bytes calldata swapArgs) external payable returns (uint256 amountOut, uint256 gasUsed); /// @dev Performs token swap with magpie signature. /// @return amountOut The amount received after swapping. function swapWithMagpieSignature(bytes calldata swapArgs) external payable returns (uint256 amountOut); /// @dev Performs token swap with a user signature. /// @return amountOut The amount received after swapping. function swapWithUserSignature(bytes calldata swapArgs) external payable returns (uint256 amountOut); /// @dev Performs token swap without a signature (data will be validated in the bridge) without triggering event. /// @return amountOut The amount received after swapping. function swapWithoutSignature(bytes calldata swapArgs) external payable returns (uint256 amountOut); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; interface ILiquidityBridge { function send( address _receiver, address _token, uint256 _amount, uint64 _dstChainId, uint64 _nonce, uint32 _maxSlippage ) external; function relay( bytes calldata _relayRequest, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external; function transfers(bytes32 transferId) external view returns (bool); function withdraws(bytes32 withdrawId) external view returns (bool); function withdraw( bytes calldata _wdmsg, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external; function verifySigs( bytes memory _msg, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external view; }
// SPDX-License-Identifier: Unlicense pragma solidity 0.8.24; interface IMessageBus { struct SwapInfo { address[] path; address dex; uint256 deadline; uint256 minRecvAmt; } struct SwapRequest { SwapInfo swap; address receiver; uint64 nonce; bool nativeOut; } enum BridgeSendType { Null, Liquidity, PegDeposit, PegBurn, PegV2Deposit, PegV2Burn, PegV2BurnFrom } enum TransferType { Null, LqRelay, LqWithdraw, PegMint, PegWithdraw, PegV2Mint, PegV2Withdraw } enum MsgType { MessageWithTransfer, MessageOnly } enum TxStatus { Null, Success, Fail, Fallback, Pending } struct TransferInfo { TransferType t; address sender; address receiver; address token; uint256 amount; uint64 wdseq; uint64 srcChainId; bytes32 refId; bytes32 srcTxHash; } function sendMessageWithTransfer( address _receiver, uint256 _dstChainId, address _srcBridge, bytes32 _srcTransferId, bytes calldata _message ) external payable; function executeMessageWithTransfer( bytes calldata _message, TransferInfo calldata _transfer, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external payable; function executeMessageWithTransferRefund( bytes calldata _message, TransferInfo calldata _transfer, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external payable; function calcFee(bytes calldata _message) external view returns (uint256); function liquidityBridge() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "../interfaces/IWETH.sol"; error AssetNotReceived(); error ApprovalFailed(); error TransferFromFailed(); error TransferFailed(); error FailedWrap(); error FailedUnwrap(); library LibAsset { using LibAsset for address; address constant NATIVE_ASSETID = address(0); /// @dev Checks if the given address (self) represents a native asset (Ether). /// @param self The asset that will be checked for a native token. /// @return Flag to identify if the asset is native or not. function isNative(address self) internal pure returns (bool) { return self == NATIVE_ASSETID; } /// @dev Wraps the specified asset. /// @param self The asset that will be wrapped. function wrap(address self, uint256 amount) internal { uint256 ptr; assembly { ptr := mload(0x40) mstore(0x40, add(ptr, 4)) mstore(ptr, 0xd0e30db000000000000000000000000000000000000000000000000000000000) } if (!execute(self, amount, ptr, 4, 0, 0)) { revert FailedWrap(); } } /// @dev Unwraps the specified asset. /// @param self The asset that will be unwrapped. function unwrap(address self, uint256 amount) internal { uint256 ptr; assembly { ptr := mload(0x40) mstore(0x40, add(ptr, 36)) mstore(ptr, 0x2e1a7d4d00000000000000000000000000000000000000000000000000000000) mstore(add(ptr, 4), amount) } if (!execute(self, 0, ptr, 36, 0, 0)) { revert FailedUnwrap(); } } /// @dev Retrieves the balance of the current contract for a given asset (self). /// @param self Asset whose balance needs to be found. /// @return Balance of the specific asset. function getBalance(address self) internal view returns (uint256) { return getBalanceOf(self, address(this)); } /// @dev Retrieves the balance of the target address for a given asset (self). /// @param self Asset whose balance needs to be found. /// @param targetAddress The address where the balance is checked from. /// @return amount Balance of the specific asset. function getBalanceOf(address self, address targetAddress) internal view returns (uint256 amount) { assembly { switch self case 0 { amount := balance(targetAddress) } default { let currentInputPtr := mload(0x40) mstore(0x40, add(currentInputPtr, 68)) mstore(currentInputPtr, 0x70a0823100000000000000000000000000000000000000000000000000000000) mstore(add(currentInputPtr, 4), targetAddress) let currentOutputPtr := add(currentInputPtr, 36) if iszero(staticcall(gas(), self, currentInputPtr, 36, currentOutputPtr, 32)) { returndatacopy(0, 0, returndatasize()) revert(0, returndatasize()) } amount := mload(currentOutputPtr) } } } /// @dev Performs a safe transferFrom operation for a given asset (self) from one address (from) to another address (to). /// @param self Asset that will be transferred. /// @param from Address that will send the asset. /// @param to Address that will receive the asset. /// @param amount Transferred amount. function transferFrom(address self, address from, address to, uint256 amount) internal { uint256 ptr; assembly { ptr := mload(0x40) mstore(0x40, add(ptr, 100)) mstore(ptr, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(ptr, 4), from) mstore(add(ptr, 36), to) mstore(add(ptr, 68), amount) } if (!execute(self, 0, ptr, 100, 0, 0)) { revert TransferFromFailed(); } } /// @dev Transfers a given amount of an asset (self) to a recipient address (recipient). /// @param self Asset that will be transferred. /// @param recipient Address that will receive the transferred asset. /// @param amount Transferred amount. function transfer(address self, address recipient, uint256 amount) internal { if (self.isNative()) { (bool success, ) = payable(recipient).call{value: amount}(""); if (!success) { revert TransferFailed(); } } else { uint256 ptr; assembly { ptr := mload(0x40) mstore(0x40, add(ptr, 68)) mstore(ptr, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(ptr, 4), recipient) mstore(add(ptr, 36), amount) } if (!execute(self, 0, ptr, 68, 0, 0)) { revert TransferFailed(); } } } /// @dev Approves a spender address (spender) to spend a specified amount of an asset (self). /// @param self The asset that will be approved. /// @param spender Address of a contract that will spend the owners asset. /// @param amount Asset amount that can be spent. function approve(address self, address spender, uint256 amount) internal { uint256 ptr; assembly { ptr := mload(0x40) mstore(0x40, add(ptr, 68)) mstore(ptr, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(ptr, 4), spender) mstore(add(ptr, 36), amount) } if (!execute(self, 0, ptr, 68, 0, 0)) { assembly { mstore(add(ptr, 36), 0) } if (!execute(self, 0, ptr, 68, 0, 0)) { revert ApprovalFailed(); } assembly { mstore(add(ptr, 36), amount) } if (!execute(self, 0, ptr, 68, 0, 0)) { revert ApprovalFailed(); } } } function permit( address self, address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { assembly { let ptr := mload(0x40) mstore(0x40, add(ptr, 228)) mstore(ptr, 0xd505accf00000000000000000000000000000000000000000000000000000000) mstore(add(ptr, 4), owner) mstore(add(ptr, 36), spender) mstore(add(ptr, 68), amount) mstore(add(ptr, 100), deadline) mstore(add(ptr, 132), v) mstore(add(ptr, 164), r) mstore(add(ptr, 196), s) let success := call(gas(), self, 0, ptr, 228, 0, 0) } } /// @dev Determines if a call was successful. /// @param target Address of the target contract. /// @param success To check if the call to the contract was successful or not. /// @param data The data was sent while calling the target contract. /// @return result The success of the call. function isSuccessful(address target, bool success, bytes memory data) private view returns (bool result) { if (success) { if (data.length == 0) { // isContract if (target.code.length > 0) { result = true; } } else { assembly { result := mload(add(data, 32)) } } } } /// @dev Executes a low level call. function execute( address self, uint256 currentNativeAmount, uint256 currentInputPtr, uint256 currentInputLength, uint256 currentOutputPtr, uint256 outputLength ) internal returns (bool result) { assembly { function isSuccessfulCall(targetAddress) -> isSuccessful { switch iszero(returndatasize()) case 1 { if gt(extcodesize(targetAddress), 0) { isSuccessful := 1 } } case 0 { returndatacopy(0, 0, 32) isSuccessful := gt(mload(0), 0) } } if iszero( call( gas(), self, currentNativeAmount, currentInputPtr, currentInputLength, currentOutputPtr, outputLength ) ) { returndatacopy(0, 0, returndatasize()) revert(0, returndatasize()) } result := isSuccessfulCall(self) } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {IMagpieRouterV3} from "../interfaces/IMagpieRouterV3.sol"; import {IBridge} from "../interfaces/IBridge.sol"; import {LibAsset} from "./LibAsset.sol"; import {LibRouter, SwapData} from "./LibRouter.sol"; struct DepositData { address toAddress; address fromAssetAddress; address toAssetAddress; uint256 amountOutMin; uint256 swapFee; uint256 amountIn; uint16 networkId; // Source network id that is defined by Magpie protocol for each chain bytes32 senderAddress; // The sender address in bytes32 uint64 swapSequence; // Swap sequence (unique identifier) of the crosschain swap } error InvalidSwapData(); error InvalidSignature(); error InvalidToAddress(); error InvalidAmountIn(); error InvalidSwapFee(); error InvalidDepositAmount(); library LibBridge { using LibAsset for address; function getFee(SwapData memory swapData) internal view returns (uint256 bridgeFee) { bridgeFee = swapData.fromAssetAddress.isNative() ? msg.value - (swapData.amountIn + swapData.swapFee + swapData.affiliateFee) : msg.value; } function decodeDepositDataHash(bytes memory payload) internal pure returns (bytes32 depositDataHash) { assembly { depositDataHash := mload(add(payload, 32)) } } function encodeDepositDataHash(bytes32 depositDataHash) internal pure returns (bytes memory payload) { payload = new bytes(32); assembly { mstore(add(payload, 32), depositDataHash) } } function getDepositDataHash( SwapData memory swapData, uint16 recipientNetworkId, address recipientAddress ) internal pure returns (bytes32 depositDataHash) { assembly { let depositDataPtr := mload(0x40) mstore(0x40, add(depositDataPtr, 236)) mstore(depositDataPtr, mload(swapData)) // toAddress mstore(add(depositDataPtr, 32), mload(add(swapData, 32))) // fromAssetAddress mstore(add(depositDataPtr, 64), mload(add(swapData, 64))) // toAssetAddress mstore(add(depositDataPtr, 96), mload(add(swapData, 128))) // amountOutMin mstore(add(depositDataPtr, 128), mload(add(swapData, 160))) // swapFee mstore(add(depositDataPtr, 160), shl(240, recipientNetworkId)) // recipientNetworkId mstore(add(depositDataPtr, 162), recipientAddress) // recipientAddress calldatacopy(add(depositDataPtr, 194), shr(240, calldataload(add(66, calldataload(36)))), 42) // networkId, senderAddress, swapSequence depositDataHash := keccak256(depositDataPtr, 236) } } /// @dev Fills the specified variable with encoded deposit data. /// @param encodedDepositData Variable / Placeholder that will be filled with the deposit data. /// @param networkId The identifier of the sender network. /// @param swapSequence The current swap sequence number. function fillEncodedDepositData( bytes memory encodedDepositData, uint16 networkId, uint64 swapSequence ) internal view { assembly { // DepositData calldatacopy(add(encodedDepositData, 32), shr(240, calldataload(add(66, calldataload(36)))), 194) // TransferKey mstore(add(encodedDepositData, 226), shl(240, networkId)) // 194 + 32 mstore(add(encodedDepositData, 228), address()) // 194 + 32 + 2 mstore(add(encodedDepositData, 260), shl(192, swapSequence)) // 194 + 32 + 34 } } /// @dev Executes a swap operation using a specified router and native amount. /// @param routerAddress The address of the router contract for the swap. /// @param nativeAmount The amount of native currency to be swapped. /// @return amountOut The amount received as output from the swap operation. function swap(address routerAddress, uint256 nativeAmount) private returns (uint256 amountOut, bool success) { assembly { let inputPtr := mload(0x40) let inputLength := shr(240, calldataload(add(66, calldataload(36)))) // bridgeDataPosition let payloadLength := sub(inputLength, 68) mstore(0x40, add(inputPtr, inputLength)) mstore(inputPtr, 0x158f689400000000000000000000000000000000000000000000000000000000) // swapWithoutSignature mstore(add(inputPtr, 4), 32) mstore(add(inputPtr, 36), payloadLength) let outputPtr := mload(0x40) mstore(0x40, add(outputPtr, 32)) calldatacopy(add(inputPtr, 68), 68, payloadLength) success := call(gas(), routerAddress, nativeAmount, inputPtr, inputLength, outputPtr, 32) if eq(success, 1) { amountOut := mload(outputPtr) } } } /// @dev Executes an inbound swap operation using provided data and addresses. /// @param swapData The SwapData struct containing swap details. /// @param encodedDepositData Encoded data related to the deposit. /// @param fromAddress The address from which the swap originates. /// @param routerAddress The address of the router contract for the swap. /// @param weth The address of the Wrapped Ether contract. /// @return amountOut The amount received as output from the swap operation. function swapIn( SwapData memory swapData, bytes memory encodedDepositData, address fromAddress, address routerAddress, address weth ) internal returns (uint256 amountOut) { if (swapData.toAddress != address(this)) { revert InvalidToAddress(); } if (swapData.fromAssetAddress.isNative()) { if (msg.value < (swapData.amountIn + swapData.swapFee + swapData.affiliateFee)) { revert InvalidAmountIn(); } } if (swapData.fromAssetAddress.isNative() && swapData.toAssetAddress == weth) { weth.wrap(swapData.amountIn); amountOut = swapData.amountIn; } else if (swapData.fromAssetAddress == weth && swapData.toAssetAddress.isNative()) { swapData.fromAssetAddress.transferFrom(fromAddress, address(this), swapData.amountIn); weth.unwrap(swapData.amountIn); amountOut = swapData.amountIn; } else if (swapData.fromAssetAddress == swapData.toAssetAddress) { swapData.fromAssetAddress.transferFrom(fromAddress, address(this), swapData.amountIn); amountOut = swapData.amountIn; } else { uint256 nativeAmount = 0; if (swapData.fromAssetAddress.isNative()) { nativeAmount = swapData.amountIn; } else { swapData.fromAssetAddress.transferFrom(fromAddress, address(this), swapData.amountIn); swapData.fromAssetAddress.approve(routerAddress, swapData.amountIn); } bool success = false; (amountOut, success) = swap(routerAddress, nativeAmount); if (!success) { assembly { returndatacopy(0, 0, returndatasize()) revert(0, returndatasize()) } } } emit IBridge.SwapIn( fromAddress, swapData.toAddress, swapData.fromAssetAddress, swapData.toAssetAddress, swapData.amountIn + swapData.swapFee + swapData.affiliateFee, amountOut, encodedDepositData ); } /// @dev Executes an outbound swap operation using provided swap and deposit data. /// @param swapData The SwapData struct containing swap details. /// @param depositAmount The bridged amount that will be swapped. /// @param routerAddress The address of the router contract for the swap. /// @param weth The address of the Wrapped Ether contract. /// @return amountOut The amount received as output from the swap operation. function swapOut( SwapData memory swapData, uint256 depositAmount, bytes32 depositDataHash, address routerAddress, address weth, address swapFeeAddress ) internal returns (uint256 amountOut) { if (depositAmount != swapData.amountIn + swapData.swapFee) { revert InvalidDepositAmount(); } if (swapData.swapFee > 0) { swapData.fromAssetAddress.transfer(swapFeeAddress, swapData.swapFee); } if (swapData.amountIn > 0) { if (swapData.fromAssetAddress == weth && swapData.toAssetAddress.isNative()) { weth.unwrap(swapData.amountIn); swapData.fromAssetAddress.transfer(swapData.toAddress, swapData.amountIn); } else if (swapData.fromAssetAddress.isNative() && swapData.toAssetAddress == weth) { weth.wrap(swapData.amountIn); swapData.fromAssetAddress.transfer(swapData.toAddress, swapData.amountIn); amountOut = swapData.amountIn; } else if (swapData.fromAssetAddress == swapData.toAssetAddress) { swapData.fromAssetAddress.transfer(swapData.toAddress, swapData.amountIn); amountOut = swapData.amountIn; } else { // We dont need signature, we validate against crosschain message uint256 nativeAmount = 0; if (swapData.fromAssetAddress.isNative()) { nativeAmount = swapData.amountIn; } else { swapData.fromAssetAddress.approve(routerAddress, swapData.amountIn); } bool success = false; (amountOut, success) = swap(routerAddress, nativeAmount); if (!success) { if (!swapData.fromAssetAddress.isNative()) { swapData.fromAssetAddress.approve(routerAddress, 0); } swapData.fromAssetAddress.transfer(swapData.toAddress, swapData.amountIn); swapData.toAssetAddress = swapData.fromAssetAddress; amountOut = swapData.amountIn; } } } emit IBridge.SwapOut( msg.sender, swapData.toAddress, swapData.fromAssetAddress, swapData.toAssetAddress, swapData.amountIn + swapData.swapFee, amountOut, depositDataHash ); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {LibAsset} from "../libraries/LibAsset.sol"; struct SwapData { address toAddress; address fromAssetAddress; address toAssetAddress; uint256 deadline; uint256 amountOutMin; uint256 swapFee; uint256 amountIn; bool hasPermit; bool hasAffiliate; address affiliateAddress; uint256 affiliateFee; } error InvalidSignature(); error ExpiredTransaction(); library LibRouter { using LibAsset for address; /// @dev Prepares SwapData from calldata function getData() internal view returns (SwapData memory swapData) { // dataOffset: 68 + 2 assembly { let deadline := shr( shr(248, calldataload(132)), // dataOffset + 62 calldataload(shr(240, calldataload(133))) // dataOffset + 62 + 1 ) if lt(deadline, timestamp()) { // ExpiredTransaction mstore(0, 0x931997cf00000000000000000000000000000000000000000000000000000000) revert(0, 4) } mstore(swapData, shr(96, calldataload(72))) // toAddress / dataOffset + 2 mstore(add(swapData, 32), shr(96, calldataload(92))) // fromAssetAddress / dataOffset + 22 mstore(add(swapData, 64), shr(96, calldataload(112))) // toAssetAddress / dataOffset + 42 mstore(add(swapData, 96), deadline) mstore( add(swapData, 128), shr( shr(248, calldataload(135)), // dataOffset + 62 + 3 calldataload(shr(240, calldataload(136))) // dataOffset + 62 + 4 ) ) // amountOutMin mstore( add(swapData, 160), shr( shr(248, calldataload(138)), // dataOffset + 62 + 6 calldataload(shr(240, calldataload(139))) // dataOffset + 62 + 7 ) ) // swapFee mstore( add(swapData, 192), shr( shr(248, calldataload(141)), // dataOffset + 62 + 9 calldataload(shr(240, calldataload(142))) // dataOffset + 62 + 10 ) ) // amountIn // calldataload(144) // r // calldataload(176) // s // shr(248, calldataload(208)) // v let hasPermit := gt(shr(248, calldataload(209)), 0) // permit v mstore(add(swapData, 224), hasPermit) // hasPermit // calldataload(210) // permit r // calldataload(242) // permit s // calldataload(274) // permit deadline switch hasPermit case 1 { let hasAffiliate := shr(248, calldataload(277)) mstore(add(swapData, 256), hasAffiliate) // hasAffiliate if eq(hasAffiliate, 1) { mstore(add(swapData, 288), shr(96, calldataload(278))) // affiliateAddress mstore( add(swapData, 320), shr(shr(248, calldataload(298)), calldataload(shr(240, calldataload(299)))) ) // affiliateFee } } default { let hasAffiliate := shr(248, calldataload(210)) mstore(add(swapData, 256), hasAffiliate) // hasAffiliate if eq(hasAffiliate, 1) { mstore(add(swapData, 288), shr(96, calldataload(211))) // affiliateAddress mstore( add(swapData, 320), shr(shr(248, calldataload(231)), calldataload(shr(240, calldataload(232)))) ) // affiliateFee } } } } /// @dev Transfers the required fees for the swap operation from the user's account. /// @param swapData The data structure containing the details of the swap operation, including fee information. /// @param fromAddress The address of the user from whom the fees will be deducted. /// @param swapFeeAddress The address of the swap fee receiver. function transferFees(SwapData memory swapData, address fromAddress, address swapFeeAddress) internal { if (swapData.swapFee > 0) { if (swapData.fromAssetAddress.isNative()) { swapData.fromAssetAddress.transfer(swapFeeAddress, swapData.swapFee); } else { swapData.fromAssetAddress.transferFrom(fromAddress, swapFeeAddress, swapData.swapFee); } } if (swapData.affiliateFee > 0) { if (swapData.fromAssetAddress.isNative()) { swapData.fromAssetAddress.transfer(swapData.affiliateAddress, swapData.affiliateFee); } else { swapData.fromAssetAddress.transferFrom(fromAddress, swapData.affiliateAddress, swapData.affiliateFee); } } } /// @dev Grants permission for the user's asset to be used in a swap operation. /// @param swapData The data structure containing the details of the swap operation. /// @param fromAddress The address of the user who is granting permission for their asset to be used. function permit(SwapData memory swapData, address fromAddress) internal { uint8 v; bytes32 r; bytes32 s; uint256 deadline; assembly { v := shr(248, calldataload(209)) r := calldataload(210) s := calldataload(242) deadline := shr(shr(248, calldataload(274)), calldataload(shr(240, calldataload(275)))) } swapData.fromAssetAddress.permit( fromAddress, address(this), swapData.amountIn + swapData.swapFee + swapData.affiliateFee, deadline, v, r, s ); } /// @dev Recovers the signer's address from a hashed message and signature components. /// @param hash The hash of the message that was signed. /// @param r The `r` component of the signature. /// @param s The `s` component of the signature. /// @param v The `v` component of the signature. /// @return signer The address of the signer recovered from the signature. function recoverSigner(bytes32 hash, bytes32 r, bytes32 s, uint8 v) private pure returns (address signer) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { revert InvalidSignature(); } if (v != 27 && v != 28) { revert InvalidSignature(); } signer = ecrecover(hash, v, r, s); if (signer == address(0)) { revert InvalidSignature(); } } function getDomainSeparator(bytes32 name, bytes32 version) private view returns (bytes32) { uint256 chainId; assembly { chainId := chainid() } return keccak256( abi.encode( // keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)") 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f, name, version, chainId, address(this) ) ); } /// @dev Verifies the signature for a swap operation. /// @param swapData The SwapData struct containing swap details. /// @param messagePtr Pointer to the message data in memory. /// @param messageLength Length of the message data. /// @param useCaller Flag indicating whether to use the caller's address for verification. /// @param internalCallersSlot Slot in the internal callers storage for verification. /// @return fromAddress The address of the signer / or caller if the signature is valid. function verifySignature( bytes32 name, bytes32 version, SwapData memory swapData, uint256 messagePtr, uint256 messageLength, bool useCaller, uint8 internalCallersSlot ) internal view returns (address fromAddress) { bytes32 domainSeparator = getDomainSeparator(name, version); bytes32 digest; bytes32 r; bytes32 s; uint8 v; assembly { mstore(add(messagePtr, 32), address()) mstore(add(messagePtr, 64), caller()) mstore(add(messagePtr, 96), mload(swapData)) mstore(add(messagePtr, 128), mload(add(swapData, 32))) mstore(add(messagePtr, 160), mload(add(swapData, 64))) mstore(add(messagePtr, 192), mload(add(swapData, 96))) mstore(add(messagePtr, 224), mload(add(swapData, 128))) mstore(add(messagePtr, 256), mload(add(swapData, 160))) mstore(add(messagePtr, 288), mload(add(swapData, 192))) // hasAffiliate if eq(mload(add(swapData, 256)), 1) { mstore(add(messagePtr, 320), mload(add(swapData, 288))) mstore(add(messagePtr, 352), mload(add(swapData, 320))) } let hash := keccak256(messagePtr, messageLength) messagePtr := mload(0x40) mstore(0x40, add(messagePtr, 66)) mstore(messagePtr, "\x19\x01") mstore(add(messagePtr, 2), domainSeparator) mstore(add(messagePtr, 34), hash) digest := keccak256(messagePtr, 66) r := calldataload(144) s := calldataload(176) v := shr(248, calldataload(208)) } if (useCaller) { address internalCaller = recoverSigner(digest, r, s, v); assembly { fromAddress := caller() mstore(0, internalCaller) mstore(0x20, internalCallersSlot) if iszero(eq(sload(keccak256(0, 0x40)), 1)) { // InvalidSignature mstore(0, 0x8baa579f00000000000000000000000000000000000000000000000000000000) revert(0, 4) } } } else { fromAddress = recoverSigner(digest, r, s, v); if (fromAddress == address(this)) { revert InvalidSignature(); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./Ownable.sol"; /** * @dev Contract module which provides 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} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// 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; } }
{ "evmVersion": "paris", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"ApprovalFailed","type":"error"},{"inputs":[],"name":"DepositIsNotFound","type":"error"},{"inputs":[],"name":"FailedUnwrap","type":"error"},{"inputs":[],"name":"FailedWrap","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidAmountIn","type":"error"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[],"name":"InvalidDepositAmount","type":"error"},{"inputs":[],"name":"InvalidRefundAddress","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidToAddress","type":"error"},{"inputs":[],"name":"NotSupportedAsset","type":"error"},{"inputs":[],"name":"ReentrancyError","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"TransferFromFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"depositDataHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":false,"internalType":"bytes32","name":"depositDataHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Refund","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"},{"indexed":false,"internalType":"address","name":"fromAssetAddress","type":"address"},{"indexed":false,"internalType":"address","name":"toAssetAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"encodedDepositData","type":"bytes"}],"name":"SwapIn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"},{"indexed":false,"internalType":"address","name":"fromAssetAddress","type":"address"},{"indexed":false,"internalType":"address","name":"toAssetAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"depositDataHash","type":"bytes32"}],"name":"SwapOut","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bool","name":"value","type":"bool"}],"name":"UpdateInternalCaller","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"celerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"assetAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"","type":"uint64"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"address","name":"","type":"address"}],"name":"executeMessageWithTransfer","outputs":[{"internalType":"enum IMessageBus.TxStatus","name":"","type":"uint8"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"assetAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"address","name":"","type":"address"}],"name":"executeMessageWithTransferRefund","outputs":[{"internalType":"enum IMessageBus.TxStatus","name":"","type":"uint8"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"internalCaller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"networkIdAndRouterAddress","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"refundAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapFeeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"swapInWithMagpieSignature","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"swapInWithUserSignature","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"swapOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapSequence","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"value","type":"address"}],"name":"updateCelerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"updateInternalCaller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"value","type":"bytes32"}],"name":"updateNetworkIdAndRouterAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"value","type":"address"}],"name":"updateSwapFeeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"value","type":"address"}],"name":"updateWeth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040523480156200001157600080fd5b506200001d3362000030565b6001805460ff60a01b191690556200009e565b600180546001600160a01b03191690556200004b816200004e565b50565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b612a9e80620000ae6000396000f3fe6080604052600436106101a05760003560e01c806379ba5097116100ec578063cec4c8551161008a578063e516008011610064578063e5160080146104c5578063f2fde38b146104d8578063f80d154b146104f8578063fd97f7391461051857600080fd5b8063cec4c8551461044f578063d4f0475d14610487578063e30c3978146104a757600080fd5b80638da5cb5b116100c65780638da5cb5b146103ce578063ac9650d8146103ec578063b8f38c7414610419578063ce4a46a41461043957600080fd5b806379ba5097146103915780637cd2bffc146103a65780638456cb59146103b957600080fd5b80633fc8cef3116101595780635c344ec9116101335780635c344ec91461031d5780635c975abb1461033d5780636a0c4ba61461035c578063715018a61461037c57600080fd5b80633fc8cef31461029d578063519a98e0146102bd57806357f46a1a146102dd57600080fd5b80630bcb4982146101ac5780631b5ad801146101d55780631ec4aec8146101f75780632fdf172b1461022f57806336876abb146102505780633f4ba83a1461028857600080fd5b366101a757005b600080fd5b6101bf6101ba366004612567565b61054e565b6040516101cc91906125da565b60405180910390f35b3480156101e157600080fd5b506101f56101f0366004612602565b610682565b005b34801561020357600080fd5b50600854610217906001600160a01b031681565b6040516001600160a01b0390911681526020016101cc565b61024261023d36600461261f565b6106ac565b6040519081526020016101cc565b34801561025c57600080fd5b50600554610270906001600160401b031681565b6040516001600160401b0390911681526020016101cc565b34801561029457600080fd5b506101f5610727565b3480156102a957600080fd5b50600354610217906001600160a01b031681565b3480156102c957600080fd5b506101f56102d8366004612660565b610741565b3480156102e957600080fd5b5061030d6102f8366004612602565b60026020526000908152604090205460ff1681565b60405190151581526020016101cc565b34801561032957600080fd5b506101f561033836600461269e565b6107ae565b34801561034957600080fd5b50600154600160a01b900460ff1661030d565b34801561036857600080fd5b5061024261037736600461261f565b6107bb565b34801561038857600080fd5b506101f5610951565b34801561039d57600080fd5b506101f5610963565b6101bf6103b43660046126b7565b6109e2565b3480156103c557600080fd5b506101f5610ae0565b3480156103da57600080fd5b506000546001600160a01b0316610217565b3480156103f857600080fd5b5061040c610407366004612758565b610af8565b6040516101cc919061281c565b34801561042557600080fd5b506101f5610434366004612602565b610bea565b34801561044557600080fd5b5061024260045481565b34801561045b57600080fd5b5061024261046a366004612880565b600660209081526000928352604080842090915290825290205481565b34801561049357600080fd5b50600954610217906001600160a01b031681565b3480156104b357600080fd5b506001546001600160a01b0316610217565b6102426104d336600461261f565b610c14565b3480156104e457600080fd5b506101f56104f3366004612602565b610c35565b34801561050457600080fd5b506101f5610513366004612602565b610ca6565b34801561052457600080fd5b5061021761053336600461269e565b6007602052600090815260409020546001600160a01b031681565b6009546000906001600160a01b0316331461056857600080fd5b60006105a985858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610cd092505050565b6000818152600760205260409020549091506001600160a01b0316806105e25760405163717f139360e11b815260040160405180910390fd5b600082815260076020526040902080546001600160a01b031916905534871161060a57600097505b61061e6001600160a01b0389168289610cd7565b876001600160a01b0316816001600160a01b03167f48ea87ca36d6027274d0a268d5a9c72f0638f8e789fa16e6e80c3b2facbf5b33848a60405161066c929190918252602082015260400190565b60405180910390a3506001979650505050505050565b61068a610db6565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b3360009081526002602052604081205460ff166106dc576040516348f5c3ed60e01b815260040160405180910390fd5b60006106e6610e10565b60208101519091506001600160a01b03166107145760405163e6c4247b60e01b815260040160405180910390fd5b61071f816000610f81565b949350505050565b61072f610db6565b61073761111c565b61073f61116c565b565b610749610db6565b6001600160a01b038216600081815260026020908152604091829020805460ff191685151590811790915582519384529083015233917fa71618a9ed4e81ce27edc2700d38db549c32abb5e4f32ec57f791151030fbc45910160405180910390a25050565b6107b6610db6565b600455565b3360009081526002602052604081205460ff166107eb576040516348f5c3ed60e01b815260040160405180910390fd5b6004546001600160f01b0381169060f01c6000610806610e10565b905060006108158284306111c1565b6000818152600660209081526040808320868301516001600160a01b03168452909152902054909150801561086f576000828152600660209081526040808320868301516001600160a01b03168452909152812055610921565b60208301516001600160a01b0316610908575060008181526006602090815260408083206003546001600160a01b03168452909152812054908190036108c857604051631196c86360e21b815260040160405180910390fd5b6003546108de906001600160a01b031682611225565b60008281526006602090815260408083206003546001600160a01b03168452909152812055610921565b604051631196c86360e21b815260040160405180910390fd5b600354600854610945918591849186918a916001600160a01b039081169116611271565b98975050505050505050565b610959610db6565b61073f6000611570565b60015433906001600160a01b031681146109d65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b6109df81611570565b50565b6009546000906001600160a01b031633146109fc57600080fd5b6000610a3d85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610cd092505050565b60008181526006602090815260408083206001600160a01b038d168452909152812080549293508992909190610a749084906128bb565b909155505060008181526006602090815260408083206001600160a01b038c168452825291829020548251848152918201527f98e783c3864bbf744a057ef605a2a61701c3b62b5ed68b3745b99094497daf1f910160405180910390a150600198975050505050505050565b610ae8610db6565b610af0611589565b61073f6115d6565b6060610b02610db6565b816001600160401b03811115610b1a57610b1a6128ce565b604051908082528060200260200182016040528015610b4d57816020015b6060815260200190600190039081610b385790505b50905060005b82811015610be257610bbd30858584818110610b7157610b716128e4565b9050602002810190610b8391906128fa565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061161992505050565b828281518110610bcf57610bcf6128e4565b6020908102919091010152600101610b53565b505b92915050565b610bf2610db6565b600880546001600160a01b0319166001600160a01b0392909216919091179055565b6000610c1e611589565b6000610c28610e10565b905061071f816001610f81565b610c3d610db6565b600180546001600160a01b0383166001600160a01b03199091168117909155610c6e6000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b610cae610db6565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b6020015190565b6001600160a01b038316610d5f576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610d32576040519150601f19603f3d011682016040523d82523d6000602084013e610d37565b606091505b5050905080610d59576040516312171d8360e31b815260040160405180910390fd5b50505050565b600060405190506044810160405263a9059cbb60e01b8152826004820152816024820152610d94846000836044600080611645565b610d59576040516312171d8360e31b815260040160405180910390fd5b505050565b6000546001600160a01b0316331461073f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109cd565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915260853560f01c3560843560f81c1c42811015610e905763931997cf60e01b60005260046000fd5b60483560601c8252605c3560601c602083015260703560601c60408301528060608301525060883560f01c3560873560f81c1c6080820152608b3560f01c35608a3560f81c1c60a0820152608e3560f01c35608d3560f81c1c60c0820152600060d13560f81c118060e08301528060018114610f425760d23560f81c8061010085015260018103610f3c5760d33560601c61012085015260e83560f01c3560e73560f81c1c6101408501525b50505090565b6101153560f81c8061010085015260018103610f3c576101163560601c61012085015261012b3560f01c3561012a3560f81c1c61014085015250505090565b60408201516000906001600160a01b0316610faf57604051633bade18360e11b815260040160405180910390fd5b600580546001600160401b0316906000610fc883612940565b82546101009290920a6001600160401b038181021990931691831602179091556005546004549116915060f081901c906001600160f01b0316600061100d87876116b2565b90508660e001511561102357611023878261180f565b61104c87828960a00151600014611045576008546001600160a01b0316611884565b6000611884565b6040805160ec808252610120820190925260009160208201818036833701905050905061107a81858761196a565b805160208083019190912060008181526007909252604090912080546001600160a01b0319166001600160a01b03858116919091179091556003546110c7918b9185918791899116611998565b96506110e26110d58a611c4f565b8a6040015189848a611c99565b6005546001600160401b03878116911614611110576040516329f745a760e01b815260040160405180910390fd5b50505050505092915050565b600154600160a01b900460ff1661073f5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016109cd565b61117461111c565b6001805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600060405160ec81016040528451815260208501516020820152604085015160408201526080850151606082015260a085015160808201528360f01b60a08201528260a2820152602a6024356042013560f01c60c283013760ec9020949350505050565b6000604051905060248101604052632e1a7d4d60e01b8152816004820152611254836000836024600080611645565b610db15760405163c617296b60e01b815260040160405180910390fd5b60008660a001518760c0015161128791906128bb565b86146112a65760405163fe9ba5cd60e01b815260040160405180910390fd5b60a0870151156112d6576112d6828860a0015189602001516001600160a01b0316610cd79092919063ffffffff16565b60c0870151156114d857826001600160a01b031687602001516001600160a01b0316148015611310575060408701516001600160a01b0316155b156113545760c087015161132e906001600160a01b03851690611225565b865160c0880151602089015161134f926001600160a01b0390911691610cd7565b6114d8565b60208701516001600160a01b03161580156113845750826001600160a01b031687604001516001600160a01b0316145b156113ce5760c08701516113a2906001600160a01b03851690611ecb565b865160c088015160208901516113c3926001600160a01b0390911691610cd7565b5060c08601516114d8565b86604001516001600160a01b031687602001516001600160a01b03160361141057865160c088015160208901516113c3926001600160a01b0390911691610cd7565b60208701516000906001600160a01b0316611430575060c0870151611456565b611456858960c001518a602001516001600160a01b0316611f109092919063ffffffff16565b60006114628683611fb2565b9093509050806114d55760208901516001600160a01b031615611499576020890151611499906001600160a01b0316876000611f10565b885160c08a015160208b01516114ba926001600160a01b0390911691610cd7565b60208901516001600160a01b031660408a015260c089015192505b50505b86600001516001600160a01b0316336001600160a01b03167f13d672f2c19bbdf5ce8c9c4894d9586248592fd27d555c2c03ac5e49d219f45d89602001518a604001518b60a001518c60c0015161152f91906128bb565b604080516001600160a01b03948516815293909216602084015290820152606081018590526080810189905260a00160405180910390a39695505050505050565b600180546001600160a01b03191690556109df81612017565b600154600160a01b900460ff161561073f5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016109cd565b6115de611589565b6001805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586111a43390565b606061163e8383604051806060016040528060278152602001612a4260279139612067565b9392505050565b6000611688565b60003d156001811461166357801561167457611682565b823b1561166f57600191505b611682565b60206000803e600080511191505b50919050565b81838587898b5af161169e573d6000803e3d6000fd5b6116a78761164c565b979650505050505050565b610100820151600090819081816116cb576101406116cf565b6101805b61ffff16905060006116e3826101206128bb565b905060405193508084016040528260018114611721577f3561ed9db327f5071ddfd91adcdffcd542e94248fbe7d8b901a0f7c72af6054f8552611745565b7ff460c1fcb477125b9e886fa605d6b560754b3f80a9479e5af7376cf97931c2e585525b506042602435013560f090811c80358685019081526020808301359082015260408083013590820152606080830135908201526080808301359082015260a08083013590931c9281019290925260a281013560c08084019190915260c2820135901c60e08084019190915260ca90910135901c610100909101526116a77f6ca9b0af27e81464d2ba2736dc23311469e9de96c72259b0fed3c28cca16f08c7fad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a58987858b60026120df565b60008060008060d13560f81c935060d235925060f23591506101133560f01c356101123560f81c1c905061187c85308861014001518960a001518a60c0015161185891906128bb565b61186291906128bb565b60208a01516001600160a01b031692919085898989612289565b505050505050565b60a0830151156118f35760208301516001600160a01b03166118cb576118c6818460a0015185602001516001600160a01b0316610cd79092919063ffffffff16565b6118f3565b6118f382828560a0015186602001516001600160a01b03166122de909392919063ffffffff16565b61014083015115610db15760208301516001600160a01b031661193c57610db183610120015184610140015185602001516001600160a01b0316610cd79092919063ffffffff16565b610db18284610120015185610140015186602001516001600160a01b03166122de909392919063ffffffff16565b60c26024356042013560f01c602085013760f09190911b60e28301523060e483015260c01b61010490910152565b84516000906001600160a01b031630146119c557604051638aa3a72f60e01b815260040160405180910390fd5b60208601516001600160a01b0316611a1b578561014001518660a001518760c001516119f191906128bb565b6119fb91906128bb565b341015611a1b576040516365719fe160e11b815260040160405180910390fd5b60208601516001600160a01b0316158015611a4b5750816001600160a01b031686604001516001600160a01b0316145b15611a745760c0860151611a69906001600160a01b03841690611ecb565b5060c0850151611bc4565b816001600160a01b031686602001516001600160a01b0316148015611aa4575060408601516001600160a01b0316155b15611aea57611ad184308860c0015189602001516001600160a01b03166122de909392919063ffffffff16565b60c0860151611a69906001600160a01b03841690611225565b85604001516001600160a01b031686602001516001600160a01b031603611b3357611a6984308860c0015189602001516001600160a01b03166122de909392919063ffffffff16565b60208601516000906001600160a01b0316611b53575060c0860151611ba1565b611b7b85308960c001518a602001516001600160a01b03166122de909392919063ffffffff16565b611ba1848860c0015189602001516001600160a01b0316611f109092919063ffffffff16565b6000611bad8583611fb2565b909350905080611bc1573d6000803e3d6000fd5b50505b85600001516001600160a01b0316846001600160a01b03167f37600fc06910ae05ad532c02a9de91251b21674999c33c6e6da90271029bfa23886020015189604001518a61014001518b60a001518c60c00151611c2191906128bb565b611c2b91906128bb565b868b604051611c3e959493929190612966565b60405180910390a395945050505050565b60208101516000906001600160a01b031615611c6b5734610be4565b8161014001518260a001518360c00151611c8591906128bb565b611c8f91906128bb565b610be490346129a0565b600954604080516320a6037160e21b815290516001600160a01b039092169160009183916382980dc4916004808201926020929091908290030181865afa158015611ce8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d0c91906129b3565b9050611d226001600160a01b0387168287611f10565b60405163a5977fbb60e01b81526001600160a01b03602480356042013560f01c60a281013583811660048601528a8416928501929092526044840189905260c281013560c01c606485018190526001600160401b038816608486015260ca9091013560e01c60a485018190529193909285169063a5977fbb9060c401600060405180830381600087803b158015611db857600080fd5b505af1158015611dcc573d6000803e3d6000fd5b50506040516bffffffffffffffffffffffff1930606090811b8216602084015287811b821660348401528d901b166048820152605c81018b90526001600160c01b031960c086811b8216607c8401528a811b8216608484015246901b16608c820152600092506094019050604051602081830303815290604052805190602001209050856001600160a01b0316634289fbb38c86868986611e6c8f61233d565b6040518763ffffffff1660e01b8152600401611e8c9594939291906129d0565b6000604051808303818588803b158015611ea557600080fd5b505af1158015611eb9573d6000803e3d6000fd5b50505050505050505050505050505050565b6000604051905060048101604052630d0e30db60e41b8152611ef38383836004600080611645565b610db15760405163bdc844ed60e01b815260040160405180910390fd5b600060405190506044810160405263095ea7b360e01b8152826004820152816024820152611f45846000836044600080611645565b610d595760006024820152611f61846000836044600080611645565b611f7e576040516340b27c2160e11b815260040160405180910390fd5b816024820152611f95846000836044600080611645565b610d59576040516340b27c2160e11b815260040160405180910390fd5b6000806040516024356042013560f01c60448103818301604052630563da2560e21b835260206004840152806024840152604051602081016040528160448086013760208184868a8c5af194506001850361200c57805195505b505050509250929050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060600080856001600160a01b0316856040516120849190612a12565b600060405180830381855af49150503d80600081146120bf576040519150601f19603f3d011682016040523d82523d6000602084013e6120c4565b606091505b50915091506120d586838387612367565b9695505050505050565b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091528183018a9052606082018990524660808301523060a0808401919091528351808403909101815260c090920190925280519101206000906000806000803060208b01523360408b01528a5160608b015260208b015160808b015260408b015160a08b015260608b015160c08b015260808b015160e08b015260a08b01516101008b015260c08b01516101208b015260016101008c0151036121c1576101208b01516101408b01526101408b01516101608b01525b888a206040519a5060428b0160405261190160f01b8b528560028c01528060228c01525060428a209350609035925060b035915060d03560f81c90508715612242576000612211858585856123e0565b9050339650806000528760205260016040600020541461223c57638baa579f60e01b60005260046000fd5b50612279565b61224e848484846123e0565b9550306001600160a01b0387160361227957604051638baa579f60e01b815260040160405180910390fd5b5050505050979650505050505050565b60405160e4810160405263d505accf60e01b81528760048201528660248201528560448201528460648201528360848201528260a48201528160c482015260008060e48360008d5af150505050505050505050565b60006040519050606481016040526323b872dd60e01b8152836004820152826024820152816044820152612319856000836064600080611645565b61233657604051631e4e7d0960e21b815260040160405180910390fd5b5050505050565b60408051602080825281830190925260609160208201818036833750505060208101929092525090565b606083156123d65782516000036123cf576001600160a01b0385163b6123cf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109cd565b508161071f565b61071f83836124e0565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561242357604051638baa579f60e01b815260040160405180910390fd5b8160ff16601b1415801561243b57508160ff16601c14155b1561245957604051638baa579f60e01b815260040160405180910390fd5b60408051600081526020810180835287905260ff841691810191909152606081018590526080810184905260019060a0016020604051602081039080840390855afa1580156124ac573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661071f57604051638baa579f60e01b815260040160405180910390fd5b8151156124f05781518083602001fd5b8060405162461bcd60e51b81526004016109cd9190612a2e565b6001600160a01b03811681146109df57600080fd5b60008083601f84011261253157600080fd5b5081356001600160401b0381111561254857600080fd5b60208301915083602082850101111561256057600080fd5b9250929050565b60008060008060006080868803121561257f57600080fd5b853561258a8161250a565b94506020860135935060408601356001600160401b038111156125ac57600080fd5b6125b88882890161251f565b90945092505060608601356125cc8161250a565b809150509295509295909350565b60208101600583106125fc57634e487b7160e01b600052602160045260246000fd5b91905290565b60006020828403121561261457600080fd5b813561163e8161250a565b6000806020838503121561263257600080fd5b82356001600160401b0381111561264857600080fd5b6126548582860161251f565b90969095509350505050565b6000806040838503121561267357600080fd5b823561267e8161250a565b91506020830135801515811461269357600080fd5b809150509250929050565b6000602082840312156126b057600080fd5b5035919050565b600080600080600080600060c0888a0312156126d257600080fd5b87356126dd8161250a565b965060208801356126ed8161250a565b95506040880135945060608801356001600160401b03808216821461271157600080fd5b9094506080890135908082111561272757600080fd5b506127348a828b0161251f565b90945092505060a08801356127488161250a565b8091505092959891949750929550565b6000806020838503121561276b57600080fd5b82356001600160401b038082111561278257600080fd5b818501915085601f83011261279657600080fd5b8135818111156127a557600080fd5b8660208260051b85010111156127ba57600080fd5b60209290920196919550909350505050565b60005b838110156127e75781810151838201526020016127cf565b50506000910152565b600081518084526128088160208601602086016127cc565b601f01601f19169290920160200192915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561287357603f198886030184526128618583516127f0565b94509285019290850190600101612845565b5092979650505050505050565b6000806040838503121561289357600080fd5b8235915060208301356126938161250a565b634e487b7160e01b600052601160045260246000fd5b80820180821115610be457610be46128a5565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261291157600080fd5b8301803591506001600160401b0382111561292b57600080fd5b60200191503681900382131561256057600080fd5b60006001600160401b0380831681810361295c5761295c6128a5565b6001019392505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190526000906116a7908301846127f0565b81810381811115610be457610be46128a5565b6000602082840312156129c557600080fd5b815161163e8161250a565b6001600160a01b0386811682526001600160401b0386166020830152841660408201526060810183905260a0608082018190526000906116a7908301846127f0565b60008251612a248184602087016127cc565b9190910192915050565b60208152600061163e60208301846127f056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b3531c0769308a1c0f8ee4874322b56b29aca88e60617f1d8e5035182fabfa4e64736f6c63430008180033
Deployed Bytecode
0x6080604052600436106101a05760003560e01c806379ba5097116100ec578063cec4c8551161008a578063e516008011610064578063e5160080146104c5578063f2fde38b146104d8578063f80d154b146104f8578063fd97f7391461051857600080fd5b8063cec4c8551461044f578063d4f0475d14610487578063e30c3978146104a757600080fd5b80638da5cb5b116100c65780638da5cb5b146103ce578063ac9650d8146103ec578063b8f38c7414610419578063ce4a46a41461043957600080fd5b806379ba5097146103915780637cd2bffc146103a65780638456cb59146103b957600080fd5b80633fc8cef3116101595780635c344ec9116101335780635c344ec91461031d5780635c975abb1461033d5780636a0c4ba61461035c578063715018a61461037c57600080fd5b80633fc8cef31461029d578063519a98e0146102bd57806357f46a1a146102dd57600080fd5b80630bcb4982146101ac5780631b5ad801146101d55780631ec4aec8146101f75780632fdf172b1461022f57806336876abb146102505780633f4ba83a1461028857600080fd5b366101a757005b600080fd5b6101bf6101ba366004612567565b61054e565b6040516101cc91906125da565b60405180910390f35b3480156101e157600080fd5b506101f56101f0366004612602565b610682565b005b34801561020357600080fd5b50600854610217906001600160a01b031681565b6040516001600160a01b0390911681526020016101cc565b61024261023d36600461261f565b6106ac565b6040519081526020016101cc565b34801561025c57600080fd5b50600554610270906001600160401b031681565b6040516001600160401b0390911681526020016101cc565b34801561029457600080fd5b506101f5610727565b3480156102a957600080fd5b50600354610217906001600160a01b031681565b3480156102c957600080fd5b506101f56102d8366004612660565b610741565b3480156102e957600080fd5b5061030d6102f8366004612602565b60026020526000908152604090205460ff1681565b60405190151581526020016101cc565b34801561032957600080fd5b506101f561033836600461269e565b6107ae565b34801561034957600080fd5b50600154600160a01b900460ff1661030d565b34801561036857600080fd5b5061024261037736600461261f565b6107bb565b34801561038857600080fd5b506101f5610951565b34801561039d57600080fd5b506101f5610963565b6101bf6103b43660046126b7565b6109e2565b3480156103c557600080fd5b506101f5610ae0565b3480156103da57600080fd5b506000546001600160a01b0316610217565b3480156103f857600080fd5b5061040c610407366004612758565b610af8565b6040516101cc919061281c565b34801561042557600080fd5b506101f5610434366004612602565b610bea565b34801561044557600080fd5b5061024260045481565b34801561045b57600080fd5b5061024261046a366004612880565b600660209081526000928352604080842090915290825290205481565b34801561049357600080fd5b50600954610217906001600160a01b031681565b3480156104b357600080fd5b506001546001600160a01b0316610217565b6102426104d336600461261f565b610c14565b3480156104e457600080fd5b506101f56104f3366004612602565b610c35565b34801561050457600080fd5b506101f5610513366004612602565b610ca6565b34801561052457600080fd5b5061021761053336600461269e565b6007602052600090815260409020546001600160a01b031681565b6009546000906001600160a01b0316331461056857600080fd5b60006105a985858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610cd092505050565b6000818152600760205260409020549091506001600160a01b0316806105e25760405163717f139360e11b815260040160405180910390fd5b600082815260076020526040902080546001600160a01b031916905534871161060a57600097505b61061e6001600160a01b0389168289610cd7565b876001600160a01b0316816001600160a01b03167f48ea87ca36d6027274d0a268d5a9c72f0638f8e789fa16e6e80c3b2facbf5b33848a60405161066c929190918252602082015260400190565b60405180910390a3506001979650505050505050565b61068a610db6565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b3360009081526002602052604081205460ff166106dc576040516348f5c3ed60e01b815260040160405180910390fd5b60006106e6610e10565b60208101519091506001600160a01b03166107145760405163e6c4247b60e01b815260040160405180910390fd5b61071f816000610f81565b949350505050565b61072f610db6565b61073761111c565b61073f61116c565b565b610749610db6565b6001600160a01b038216600081815260026020908152604091829020805460ff191685151590811790915582519384529083015233917fa71618a9ed4e81ce27edc2700d38db549c32abb5e4f32ec57f791151030fbc45910160405180910390a25050565b6107b6610db6565b600455565b3360009081526002602052604081205460ff166107eb576040516348f5c3ed60e01b815260040160405180910390fd5b6004546001600160f01b0381169060f01c6000610806610e10565b905060006108158284306111c1565b6000818152600660209081526040808320868301516001600160a01b03168452909152902054909150801561086f576000828152600660209081526040808320868301516001600160a01b03168452909152812055610921565b60208301516001600160a01b0316610908575060008181526006602090815260408083206003546001600160a01b03168452909152812054908190036108c857604051631196c86360e21b815260040160405180910390fd5b6003546108de906001600160a01b031682611225565b60008281526006602090815260408083206003546001600160a01b03168452909152812055610921565b604051631196c86360e21b815260040160405180910390fd5b600354600854610945918591849186918a916001600160a01b039081169116611271565b98975050505050505050565b610959610db6565b61073f6000611570565b60015433906001600160a01b031681146109d65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b6109df81611570565b50565b6009546000906001600160a01b031633146109fc57600080fd5b6000610a3d85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610cd092505050565b60008181526006602090815260408083206001600160a01b038d168452909152812080549293508992909190610a749084906128bb565b909155505060008181526006602090815260408083206001600160a01b038c168452825291829020548251848152918201527f98e783c3864bbf744a057ef605a2a61701c3b62b5ed68b3745b99094497daf1f910160405180910390a150600198975050505050505050565b610ae8610db6565b610af0611589565b61073f6115d6565b6060610b02610db6565b816001600160401b03811115610b1a57610b1a6128ce565b604051908082528060200260200182016040528015610b4d57816020015b6060815260200190600190039081610b385790505b50905060005b82811015610be257610bbd30858584818110610b7157610b716128e4565b9050602002810190610b8391906128fa565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061161992505050565b828281518110610bcf57610bcf6128e4565b6020908102919091010152600101610b53565b505b92915050565b610bf2610db6565b600880546001600160a01b0319166001600160a01b0392909216919091179055565b6000610c1e611589565b6000610c28610e10565b905061071f816001610f81565b610c3d610db6565b600180546001600160a01b0383166001600160a01b03199091168117909155610c6e6000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b610cae610db6565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b6020015190565b6001600160a01b038316610d5f576000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610d32576040519150601f19603f3d011682016040523d82523d6000602084013e610d37565b606091505b5050905080610d59576040516312171d8360e31b815260040160405180910390fd5b50505050565b600060405190506044810160405263a9059cbb60e01b8152826004820152816024820152610d94846000836044600080611645565b610d59576040516312171d8360e31b815260040160405180910390fd5b505050565b6000546001600160a01b0316331461073f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109cd565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915260853560f01c3560843560f81c1c42811015610e905763931997cf60e01b60005260046000fd5b60483560601c8252605c3560601c602083015260703560601c60408301528060608301525060883560f01c3560873560f81c1c6080820152608b3560f01c35608a3560f81c1c60a0820152608e3560f01c35608d3560f81c1c60c0820152600060d13560f81c118060e08301528060018114610f425760d23560f81c8061010085015260018103610f3c5760d33560601c61012085015260e83560f01c3560e73560f81c1c6101408501525b50505090565b6101153560f81c8061010085015260018103610f3c576101163560601c61012085015261012b3560f01c3561012a3560f81c1c61014085015250505090565b60408201516000906001600160a01b0316610faf57604051633bade18360e11b815260040160405180910390fd5b600580546001600160401b0316906000610fc883612940565b82546101009290920a6001600160401b038181021990931691831602179091556005546004549116915060f081901c906001600160f01b0316600061100d87876116b2565b90508660e001511561102357611023878261180f565b61104c87828960a00151600014611045576008546001600160a01b0316611884565b6000611884565b6040805160ec808252610120820190925260009160208201818036833701905050905061107a81858761196a565b805160208083019190912060008181526007909252604090912080546001600160a01b0319166001600160a01b03858116919091179091556003546110c7918b9185918791899116611998565b96506110e26110d58a611c4f565b8a6040015189848a611c99565b6005546001600160401b03878116911614611110576040516329f745a760e01b815260040160405180910390fd5b50505050505092915050565b600154600160a01b900460ff1661073f5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016109cd565b61117461111c565b6001805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600060405160ec81016040528451815260208501516020820152604085015160408201526080850151606082015260a085015160808201528360f01b60a08201528260a2820152602a6024356042013560f01c60c283013760ec9020949350505050565b6000604051905060248101604052632e1a7d4d60e01b8152816004820152611254836000836024600080611645565b610db15760405163c617296b60e01b815260040160405180910390fd5b60008660a001518760c0015161128791906128bb565b86146112a65760405163fe9ba5cd60e01b815260040160405180910390fd5b60a0870151156112d6576112d6828860a0015189602001516001600160a01b0316610cd79092919063ffffffff16565b60c0870151156114d857826001600160a01b031687602001516001600160a01b0316148015611310575060408701516001600160a01b0316155b156113545760c087015161132e906001600160a01b03851690611225565b865160c0880151602089015161134f926001600160a01b0390911691610cd7565b6114d8565b60208701516001600160a01b03161580156113845750826001600160a01b031687604001516001600160a01b0316145b156113ce5760c08701516113a2906001600160a01b03851690611ecb565b865160c088015160208901516113c3926001600160a01b0390911691610cd7565b5060c08601516114d8565b86604001516001600160a01b031687602001516001600160a01b03160361141057865160c088015160208901516113c3926001600160a01b0390911691610cd7565b60208701516000906001600160a01b0316611430575060c0870151611456565b611456858960c001518a602001516001600160a01b0316611f109092919063ffffffff16565b60006114628683611fb2565b9093509050806114d55760208901516001600160a01b031615611499576020890151611499906001600160a01b0316876000611f10565b885160c08a015160208b01516114ba926001600160a01b0390911691610cd7565b60208901516001600160a01b031660408a015260c089015192505b50505b86600001516001600160a01b0316336001600160a01b03167f13d672f2c19bbdf5ce8c9c4894d9586248592fd27d555c2c03ac5e49d219f45d89602001518a604001518b60a001518c60c0015161152f91906128bb565b604080516001600160a01b03948516815293909216602084015290820152606081018590526080810189905260a00160405180910390a39695505050505050565b600180546001600160a01b03191690556109df81612017565b600154600160a01b900460ff161561073f5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016109cd565b6115de611589565b6001805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586111a43390565b606061163e8383604051806060016040528060278152602001612a4260279139612067565b9392505050565b6000611688565b60003d156001811461166357801561167457611682565b823b1561166f57600191505b611682565b60206000803e600080511191505b50919050565b81838587898b5af161169e573d6000803e3d6000fd5b6116a78761164c565b979650505050505050565b610100820151600090819081816116cb576101406116cf565b6101805b61ffff16905060006116e3826101206128bb565b905060405193508084016040528260018114611721577f3561ed9db327f5071ddfd91adcdffcd542e94248fbe7d8b901a0f7c72af6054f8552611745565b7ff460c1fcb477125b9e886fa605d6b560754b3f80a9479e5af7376cf97931c2e585525b506042602435013560f090811c80358685019081526020808301359082015260408083013590820152606080830135908201526080808301359082015260a08083013590931c9281019290925260a281013560c08084019190915260c2820135901c60e08084019190915260ca90910135901c610100909101526116a77f6ca9b0af27e81464d2ba2736dc23311469e9de96c72259b0fed3c28cca16f08c7fad7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a58987858b60026120df565b60008060008060d13560f81c935060d235925060f23591506101133560f01c356101123560f81c1c905061187c85308861014001518960a001518a60c0015161185891906128bb565b61186291906128bb565b60208a01516001600160a01b031692919085898989612289565b505050505050565b60a0830151156118f35760208301516001600160a01b03166118cb576118c6818460a0015185602001516001600160a01b0316610cd79092919063ffffffff16565b6118f3565b6118f382828560a0015186602001516001600160a01b03166122de909392919063ffffffff16565b61014083015115610db15760208301516001600160a01b031661193c57610db183610120015184610140015185602001516001600160a01b0316610cd79092919063ffffffff16565b610db18284610120015185610140015186602001516001600160a01b03166122de909392919063ffffffff16565b60c26024356042013560f01c602085013760f09190911b60e28301523060e483015260c01b61010490910152565b84516000906001600160a01b031630146119c557604051638aa3a72f60e01b815260040160405180910390fd5b60208601516001600160a01b0316611a1b578561014001518660a001518760c001516119f191906128bb565b6119fb91906128bb565b341015611a1b576040516365719fe160e11b815260040160405180910390fd5b60208601516001600160a01b0316158015611a4b5750816001600160a01b031686604001516001600160a01b0316145b15611a745760c0860151611a69906001600160a01b03841690611ecb565b5060c0850151611bc4565b816001600160a01b031686602001516001600160a01b0316148015611aa4575060408601516001600160a01b0316155b15611aea57611ad184308860c0015189602001516001600160a01b03166122de909392919063ffffffff16565b60c0860151611a69906001600160a01b03841690611225565b85604001516001600160a01b031686602001516001600160a01b031603611b3357611a6984308860c0015189602001516001600160a01b03166122de909392919063ffffffff16565b60208601516000906001600160a01b0316611b53575060c0860151611ba1565b611b7b85308960c001518a602001516001600160a01b03166122de909392919063ffffffff16565b611ba1848860c0015189602001516001600160a01b0316611f109092919063ffffffff16565b6000611bad8583611fb2565b909350905080611bc1573d6000803e3d6000fd5b50505b85600001516001600160a01b0316846001600160a01b03167f37600fc06910ae05ad532c02a9de91251b21674999c33c6e6da90271029bfa23886020015189604001518a61014001518b60a001518c60c00151611c2191906128bb565b611c2b91906128bb565b868b604051611c3e959493929190612966565b60405180910390a395945050505050565b60208101516000906001600160a01b031615611c6b5734610be4565b8161014001518260a001518360c00151611c8591906128bb565b611c8f91906128bb565b610be490346129a0565b600954604080516320a6037160e21b815290516001600160a01b039092169160009183916382980dc4916004808201926020929091908290030181865afa158015611ce8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d0c91906129b3565b9050611d226001600160a01b0387168287611f10565b60405163a5977fbb60e01b81526001600160a01b03602480356042013560f01c60a281013583811660048601528a8416928501929092526044840189905260c281013560c01c606485018190526001600160401b038816608486015260ca9091013560e01c60a485018190529193909285169063a5977fbb9060c401600060405180830381600087803b158015611db857600080fd5b505af1158015611dcc573d6000803e3d6000fd5b50506040516bffffffffffffffffffffffff1930606090811b8216602084015287811b821660348401528d901b166048820152605c81018b90526001600160c01b031960c086811b8216607c8401528a811b8216608484015246901b16608c820152600092506094019050604051602081830303815290604052805190602001209050856001600160a01b0316634289fbb38c86868986611e6c8f61233d565b6040518763ffffffff1660e01b8152600401611e8c9594939291906129d0565b6000604051808303818588803b158015611ea557600080fd5b505af1158015611eb9573d6000803e3d6000fd5b50505050505050505050505050505050565b6000604051905060048101604052630d0e30db60e41b8152611ef38383836004600080611645565b610db15760405163bdc844ed60e01b815260040160405180910390fd5b600060405190506044810160405263095ea7b360e01b8152826004820152816024820152611f45846000836044600080611645565b610d595760006024820152611f61846000836044600080611645565b611f7e576040516340b27c2160e11b815260040160405180910390fd5b816024820152611f95846000836044600080611645565b610d59576040516340b27c2160e11b815260040160405180910390fd5b6000806040516024356042013560f01c60448103818301604052630563da2560e21b835260206004840152806024840152604051602081016040528160448086013760208184868a8c5af194506001850361200c57805195505b505050509250929050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060600080856001600160a01b0316856040516120849190612a12565b600060405180830381855af49150503d80600081146120bf576040519150601f19603f3d011682016040523d82523d6000602084013e6120c4565b606091505b50915091506120d586838387612367565b9695505050505050565b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091528183018a9052606082018990524660808301523060a0808401919091528351808403909101815260c090920190925280519101206000906000806000803060208b01523360408b01528a5160608b015260208b015160808b015260408b015160a08b015260608b015160c08b015260808b015160e08b015260a08b01516101008b015260c08b01516101208b015260016101008c0151036121c1576101208b01516101408b01526101408b01516101608b01525b888a206040519a5060428b0160405261190160f01b8b528560028c01528060228c01525060428a209350609035925060b035915060d03560f81c90508715612242576000612211858585856123e0565b9050339650806000528760205260016040600020541461223c57638baa579f60e01b60005260046000fd5b50612279565b61224e848484846123e0565b9550306001600160a01b0387160361227957604051638baa579f60e01b815260040160405180910390fd5b5050505050979650505050505050565b60405160e4810160405263d505accf60e01b81528760048201528660248201528560448201528460648201528360848201528260a48201528160c482015260008060e48360008d5af150505050505050505050565b60006040519050606481016040526323b872dd60e01b8152836004820152826024820152816044820152612319856000836064600080611645565b61233657604051631e4e7d0960e21b815260040160405180910390fd5b5050505050565b60408051602080825281830190925260609160208201818036833750505060208101929092525090565b606083156123d65782516000036123cf576001600160a01b0385163b6123cf5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109cd565b508161071f565b61071f83836124e0565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561242357604051638baa579f60e01b815260040160405180910390fd5b8160ff16601b1415801561243b57508160ff16601c14155b1561245957604051638baa579f60e01b815260040160405180910390fd5b60408051600081526020810180835287905260ff841691810191909152606081018590526080810184905260019060a0016020604051602081039080840390855afa1580156124ac573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661071f57604051638baa579f60e01b815260040160405180910390fd5b8151156124f05781518083602001fd5b8060405162461bcd60e51b81526004016109cd9190612a2e565b6001600160a01b03811681146109df57600080fd5b60008083601f84011261253157600080fd5b5081356001600160401b0381111561254857600080fd5b60208301915083602082850101111561256057600080fd5b9250929050565b60008060008060006080868803121561257f57600080fd5b853561258a8161250a565b94506020860135935060408601356001600160401b038111156125ac57600080fd5b6125b88882890161251f565b90945092505060608601356125cc8161250a565b809150509295509295909350565b60208101600583106125fc57634e487b7160e01b600052602160045260246000fd5b91905290565b60006020828403121561261457600080fd5b813561163e8161250a565b6000806020838503121561263257600080fd5b82356001600160401b0381111561264857600080fd5b6126548582860161251f565b90969095509350505050565b6000806040838503121561267357600080fd5b823561267e8161250a565b91506020830135801515811461269357600080fd5b809150509250929050565b6000602082840312156126b057600080fd5b5035919050565b600080600080600080600060c0888a0312156126d257600080fd5b87356126dd8161250a565b965060208801356126ed8161250a565b95506040880135945060608801356001600160401b03808216821461271157600080fd5b9094506080890135908082111561272757600080fd5b506127348a828b0161251f565b90945092505060a08801356127488161250a565b8091505092959891949750929550565b6000806020838503121561276b57600080fd5b82356001600160401b038082111561278257600080fd5b818501915085601f83011261279657600080fd5b8135818111156127a557600080fd5b8660208260051b85010111156127ba57600080fd5b60209290920196919550909350505050565b60005b838110156127e75781810151838201526020016127cf565b50506000910152565b600081518084526128088160208601602086016127cc565b601f01601f19169290920160200192915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561287357603f198886030184526128618583516127f0565b94509285019290850190600101612845565b5092979650505050505050565b6000806040838503121561289357600080fd5b8235915060208301356126938161250a565b634e487b7160e01b600052601160045260246000fd5b80820180821115610be457610be46128a5565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261291157600080fd5b8301803591506001600160401b0382111561292b57600080fd5b60200191503681900382131561256057600080fd5b60006001600160401b0380831681810361295c5761295c6128a5565b6001019392505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190526000906116a7908301846127f0565b81810381811115610be457610be46128a5565b6000602082840312156129c557600080fd5b815161163e8161250a565b6001600160a01b0386811682526001600160401b0386166020830152841660408201526060810183905260a0608082018190526000906116a7908301846127f0565b60008251612a248184602087016127cc565b9190910192915050565b60208152600061163e60208301846127f056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b3531c0769308a1c0f8ee4874322b56b29aca88e60617f1d8e5035182fabfa4e64736f6c63430008180033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.