Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 36 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
C Bridge | 16965833 | 464 days ago | IN | 0.022 ETH | 0.00379004 | ||||
Multi Chain Brid... | 16958977 | 465 days ago | IN | 0.225933 ETH | 0.00273029 | ||||
Swap Router | 16945620 | 467 days ago | IN | 0 ETH | 0.00334044 | ||||
Swap Router | 16945613 | 467 days ago | IN | 0 ETH | 0.00385271 | ||||
Swap Router | 16945513 | 467 days ago | IN | 0 ETH | 0.0035262 | ||||
Swap Router | 16945507 | 467 days ago | IN | 0.001 ETH | 0.00286034 | ||||
Swap Router | 16945187 | 467 days ago | IN | 0 ETH | 0.00372271 | ||||
Swap Router | 16945132 | 467 days ago | IN | 0.001 ETH | 0.00309155 | ||||
Swap Router | 16945093 | 467 days ago | IN | 0.001 ETH | 0.00351761 | ||||
Swap Router | 16931187 | 469 days ago | IN | 0 ETH | 0.00445537 | ||||
Swap Router | 16931104 | 469 days ago | IN | 0.001 ETH | 0.00349283 | ||||
Portal Complete | 16909352 | 472 days ago | IN | 0 ETH | 0.00710337 | ||||
Portal Complete | 16907973 | 472 days ago | IN | 0 ETH | 0.00996259 | ||||
Portal Complete | 16860055 | 479 days ago | IN | 0 ETH | 0.00567188 | ||||
Multi Chain Brid... | 16779039 | 490 days ago | IN | 0 ETH | 0.00691995 | ||||
C Bridge | 16746856 | 495 days ago | IN | 0.02 ETH | 0.00388786 | ||||
Portal Complete | 16746310 | 495 days ago | IN | 0 ETH | 0.01175338 | ||||
C Bridge | 16739615 | 496 days ago | IN | 0.08 ETH | 0.00395111 | ||||
C Bridge | 16737602 | 496 days ago | IN | 0.03 ETH | 0.00416552 | ||||
Portal Complete | 16719217 | 499 days ago | IN | 0 ETH | 0.0066328 | ||||
Portal Complete | 16719095 | 499 days ago | IN | 0 ETH | 0.00753213 | ||||
Swap Router | 16718014 | 499 days ago | IN | 0.0001 ETH | 0.00255941 | ||||
Portal Complete | 16716386 | 499 days ago | IN | 0 ETH | 0.00823512 | ||||
Swap Multichain | 16690665 | 503 days ago | IN | 0.01 ETH | 0.00704454 | ||||
Swap Router | 16677276 | 505 days ago | IN | 0.000001 ETH | 0.00526079 |
Latest 14 internal transactions
Advanced mode:
Parent Transaction Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
16965833 | 464 days ago | 0.022 ETH | ||||
16958977 | 465 days ago | 0.225933 ETH | ||||
16945507 | 467 days ago | 0.001 ETH | ||||
16945132 | 467 days ago | 0.001 ETH | ||||
16945093 | 467 days ago | 0.001 ETH | ||||
16931104 | 469 days ago | 0.001 ETH | ||||
16746856 | 495 days ago | 0.02 ETH | ||||
16739615 | 496 days ago | 0.08 ETH | ||||
16737602 | 496 days ago | 0.03 ETH | ||||
16718014 | 499 days ago | 0.0001 ETH | ||||
16690665 | 503 days ago | 0.01 ETH | ||||
16677276 | 505 days ago | 0.000001 ETH | ||||
16676560 | 505 days ago | 0.00093 ETH | ||||
16675678 | 505 days ago | 0.002 ETH |
Loading...
Loading
Contract Name:
Vault
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import "@openzeppelin/contracts/access/Ownable.sol"; import "./interfaces/IBridge.sol"; import "./libraries/SafeERC20.sol"; import "./libraries/PbPool.sol"; import "./libraries/Signers.sol"; import "./libraries/OrderLib.sol"; import "./VerifySigEIP712.sol"; import "./interfaces/Structs.sol"; import "./libraries/AssetLib.sol"; interface IMultichainERC20 { function Swapout(uint256 amount, address bindaddr) external returns (bool); } contract Vault is Ownable, Signers, VerifySigEIP712 { using SafeERC20 for IERC20; IERC20 private constant NATIVE_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); //ETH chain address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address public ROUTER; address public CBRIDGE; address public POLYBRIDGE; address public PORTAL; address private dev; uint256 feePercent = 0; mapping(address => mapping(uint64 => BridgeInfo)) public userBridgeInfo; mapping(bytes32 => BridgeInfo) public transferInfo; mapping(bytes32 => bool) public transfers; mapping(address => address) public anyTokenAddress; mapping(address => bool) public allowedRouter; event Swap(address user, address srcToken, address toToken, uint256 amount, uint256 returnAmount); event Bridge(address user, uint64 chainId, address srcToken, address toDstToken, uint256 fromAmount, bytes32 transferId, string bridge); event Relayswap(address receiver, address toToken, uint256 returnAmount); receive() external payable {} constructor( address router, address cbridge, address poly, address portal ) { ROUTER = router; CBRIDGE = cbridge; POLYBRIDGE = poly; PORTAL = portal; } /// @param routers multichain router address /// Whitelist only the router address of multichain function initMultichain(address[] calldata routers) external { require(msg.sender == dev || msg.sender == owner()); uint256 len = routers.length; for (uint256 i; i < len; ) { if (routers[i] == address(0)) { revert(); } allowedRouter[routers[i]] = true; unchecked { ++i; } } } /// @param mappings Mapping between multichain anyToken and real Token function updateAddressMapping(AnyMapping[] calldata mappings) external { require(msg.sender == dev || msg.sender == owner()); for (uint64 i; i < mappings.length; i++) { anyTokenAddress[mappings[i].tokenAddress] = mappings[i].anyTokenAddress; } } /// @param bDesc Parameters to enter cBridge. /// address srcToken; /// uint256 amount; /// address receiver; /// uint64 dstChainId; /// uint64 nonce; /// uint32 maxSlippage; function cBridge(CBridgeDescription calldata bDesc) external payable { bool isNotNative = !_isNative(IERC20(bDesc.srcToken)); if (isNotNative) { IERC20(bDesc.srcToken).safeTransferFrom(msg.sender, address(this), bDesc.amount); } _cBridgeStart(bDesc.amount, bDesc); } /// @param _Pdesc Parameters to enter PortalBridge. /// address token; /// uint256 amount; /// uint16 recipientChain; /// address recipient; /// uint32 nonce; /// uint256 arbiterFee; /// bytes payload; function PortalBridge(PortalBridgeDescription calldata _Pdesc) external payable { bool isNotNative = !_isNative(IERC20(_Pdesc.token)); if (isNotNative) { IERC20(_Pdesc.token).safeTransferFrom(msg.sender, address(this), _Pdesc.amount); } _portalBridgeStart(_Pdesc.amount, _Pdesc); } function polyBridge(PolyBridgeDescription calldata pDesc) public payable { bool isNotNative = !_isNative(IERC20(pDesc.fromAsset)); if (isNotNative) { IERC20(pDesc.fromAsset).safeTransferFrom(msg.sender, address(this), pDesc.amount); } _polyBridgeStart(pDesc.amount, pDesc); } function multiChainBridge(MultiChainDescription calldata mDesc) public payable { bool isNative = !_isNative(IERC20(mDesc.srcToken)); if (isNative) { IERC20(mDesc.srcToken).safeTransferFrom(msg.sender, address(this), mDesc.amount); } _multiChainBridgeStart(mDesc.amount, mDesc); } function swapRouter(SwapData calldata _swap) external payable { _isNativeDeposit(IERC20(_swap.srcToken), _swap.amount); _userSwapStart(_swap); } function swapCBridge(SwapData calldata _swap, CBridgeDescription calldata bDesc) external payable { SwapData calldata swapData = _swap; _isNativeDeposit(IERC20(swapData.srcToken), swapData.amount); uint256 dstAmount = _swapStart(swapData); _cBridgeStart(dstAmount, bDesc); } function swapPortalBridge(SwapData calldata _swap, PortalBridgeDescription calldata pDesc) external payable { SwapData calldata swapData = _swap; _isNativeDeposit(IERC20(swapData.srcToken), swapData.amount); uint256 dstAmount = _swapStart(swapData); _portalBridgeStart(dstAmount, pDesc); } function swapPolyBridge(SwapData calldata _swap, PolyBridgeDescription calldata pdesc) external payable { SwapData calldata swapData = _swap; _isNativeDeposit(IERC20(swapData.srcToken), swapData.amount); uint256 dstAmount = _swapStart(swapData); _polyBridgeStart(dstAmount, pdesc); } function swapMultichain(SwapData calldata _swap, MultiChainDescription calldata mDesc) external payable { SwapData calldata swapData = _swap; _isNativeDeposit(IERC20(swapData.srcToken), swapData.amount); uint256 dstAmount = _swapStart(swapData); if (!allowedRouter[mDesc.router]) revert(); _multiChainBridgeStart(dstAmount, mDesc); } function _fee(address dstToken, uint256 dstAmount) private returns (uint256 returnAmount) { uint256 fee = (dstAmount * feePercent) / 10000; returnAmount = dstAmount - fee; if (fee > 0) { if (!_isNative(IERC20(dstToken))) { IERC20(dstToken).safeTransfer(owner(), fee); } else { _safeNativeTransfer(owner(), fee); } } } function _swapStart(SwapData calldata swapData) private returns (uint256 dstAmount) { SwapData calldata swap = swapData; bool isNative = _isNative(IERC20(swap.srcToken)); uint256 initDstTokenBalance = AssetLib.getBalance(swap.dstToken); (bool succ, ) = address(ROUTER).call{value: isNative ? swap.amount : 0}(swap.callData); if (succ) { uint256 dstTokenBalance = AssetLib.getBalance(swap.dstToken); dstAmount = dstTokenBalance > initDstTokenBalance ? dstTokenBalance - initDstTokenBalance : dstTokenBalance; emit Swap(swap.user, swap.srcToken, swap.dstToken, swap.amount, dstAmount); } else { revert(); } } function _userSwapStart(SwapData calldata swapData) private returns (uint256 dstAmount) { SwapData calldata swap = swapData; bool isNative = _isNative(IERC20(swap.srcToken)); uint256 initDstTokenBalance = AssetLib.userBalance(swap.user, swap.dstToken); (bool succ, ) = address(ROUTER).call{value: isNative ? swap.amount : 0}(swap.callData); if (succ) { uint256 dstTokenBalance = AssetLib.userBalance(swap.user, swap.dstToken); dstAmount = dstTokenBalance > initDstTokenBalance ? dstTokenBalance - initDstTokenBalance : dstTokenBalance; emit Swap(swap.user, swap.srcToken, swap.dstToken, swap.amount, dstAmount); } else { revert(); } } function relaySwapRouter( SwapData calldata _swap, Input calldata _sigCollect, bytes[] memory signature ) external onlyOwner { SwapData calldata swap = _swap; Input calldata sig = _sigCollect; require(sig.userAddress == swap.user && sig.amount - sig.gasFee == swap.amount && sig.toTokenAddress == swap.dstToken); relaySig(sig, signature); require(transfers[sig.txHash] == false, "safeTransfer exists"); transfers[sig.txHash] = true; bool isNotNative = !_isNative(IERC20(sig.fromTokenAddress)); uint256 fromAmount = sig.amount - sig.gasFee; if (isNotNative) { IERC20(sig.fromTokenAddress).safeApprove(ROUTER, fromAmount); if (sig.gasFee > 0) IERC20(sig.fromTokenAddress).safeTransfer(owner(), sig.gasFee); } else { if (sig.gasFee > 0) _safeNativeTransfer(owner(), sig.gasFee); } uint256 dstAmount = _userSwapStart(swap); emit Relayswap(sig.userAddress, sig.toTokenAddress, dstAmount); } function portalComplete( bytes memory encodeVm, SwapData calldata _swap, Input calldata _sigCollect, bytes[] memory signature ) public onlyOwner { SwapData calldata swap = _swap; bool isNotNative = !_isNative(IERC20(swap.srcToken)); Input calldata sig = _sigCollect; require(sig.userAddress == swap.user && sig.amount - sig.gasFee == swap.amount && sig.toTokenAddress == swap.dstToken); relaySig(sig, signature); require(transfers[sig.txHash] == false); uint256 fromAmount = sig.amount - sig.gasFee; if (isNotNative) { IBridge(PORTAL).completeTransferWithPayload(encodeVm); IERC20(sig.fromTokenAddress).safeApprove(ROUTER, fromAmount); if (sig.gasFee > 0) IERC20(sig.fromTokenAddress).safeTransfer(owner(), sig.gasFee); } else { IBridge(PORTAL).completeTransferAndUnwrapETHWithPayload(encodeVm); if (sig.gasFee > 0) _safeNativeTransfer(owner(), sig.gasFee); } uint256 dstAmount = _userSwapStart(swap); emit Relayswap(sig.userAddress, sig.toTokenAddress, dstAmount); } function EmergencyWithdraw(address _tokenAddress, uint256 amount) public onlyOwner { bool isNotNative = !_isNative(IERC20(_tokenAddress)); if (isNotNative) { IERC20(_tokenAddress).safeTransfer(owner(), amount); } else { _safeNativeTransfer(owner(), amount); } } function sigWithdraw( bytes calldata _wdmsg, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external { IBridge(CBRIDGE).withdraw(_wdmsg, _sigs, _signers, _powers); bytes32 domain = keccak256(abi.encodePacked(block.chainid, CBRIDGE, "WithdrawMsg")); verifySigs(abi.encodePacked(domain, _wdmsg), _sigs, _signers, _powers); PbPool.WithdrawMsg memory wdmsg = PbPool.decWithdrawMsg(_wdmsg); BridgeInfo memory tif = transferInfo[wdmsg.refid]; bool isNotNative = !_isNative(IERC20(tif.dstToken)); if (isNotNative) { IERC20(tif.dstToken).safeTransfer(tif.user, tif.amount); } else { _safeNativeTransfer(tif.user, tif.amount); } } function setRouterBridge( address _router, address _cbridge, address poly, address portal ) public { require(msg.sender == dev || msg.sender == owner()); ROUTER = _router; CBRIDGE = _cbridge; POLYBRIDGE = poly; PORTAL = portal; } function setFeePercent(uint256 percent) external { require(msg.sender == dev || msg.sender == owner()); feePercent = percent; } function _isNative(IERC20 token_) internal pure returns (bool) { return (token_ == NATIVE_ADDRESS); } function _isNativeDeposit(IERC20 _token, uint256 _amount) internal returns (bool isNotNative) { isNotNative = !_isNative(_token); if (isNotNative) { IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount); IERC20(_token).safeApprove(ROUTER, _amount); } } function _cBridgeStart(uint256 dstAmount, CBridgeDescription calldata bdesc) internal { CBridgeDescription memory bDesc = bdesc; dstAmount = _fee(bDesc.srcToken, dstAmount); bool isNotNative = !_isNative(IERC20(bDesc.srcToken)); if (isNotNative) { IERC20(bDesc.srcToken).safeApprove(CBRIDGE, dstAmount); IBridge(CBRIDGE).send(bDesc.receiver, bDesc.srcToken, dstAmount, bDesc.dstChainId, bDesc.nonce, bDesc.maxSlippage); } else { IBridge(CBRIDGE).sendNative{value: dstAmount}(bDesc.receiver, dstAmount, bDesc.dstChainId, bDesc.nonce, bDesc.maxSlippage); bDesc.srcToken = WETH; } bytes32 transferId = keccak256( abi.encodePacked(address(this), bDesc.receiver, bDesc.srcToken, dstAmount, bDesc.dstChainId, bDesc.nonce, uint64(block.chainid)) ); BridgeInfo memory tif = transferInfo[transferId]; require(tif.nonce == 0, " PLEXUS: transferId already exists. Check the nonce."); tif.dstToken = bDesc.srcToken; tif.chainId = bDesc.dstChainId; tif.amount = dstAmount; tif.user = msg.sender; tif.nonce = bDesc.nonce; tif.bridge = "CBridge"; transferInfo[transferId] = tif; emit Bridge(tif.user, tif.chainId, tif.dstToken, bDesc.toDstToken, dstAmount, transferId, tif.bridge); } function _polyBridgeStart(uint256 dstAmount, PolyBridgeDescription calldata _pDesc) private { PolyBridgeDescription memory pDesc = _pDesc; bool isNative = _isNative(IERC20(pDesc.fromAsset)); dstAmount = _fee(pDesc.fromAsset, dstAmount); if (!isNative) { IERC20(pDesc.fromAsset).safeApprove(POLYBRIDGE, dstAmount); IBridge(POLYBRIDGE).lock{value: pDesc.fee}(pDesc.fromAsset, pDesc.toChainId, pDesc.toAddress, dstAmount, pDesc.fee, pDesc.id); } else { pDesc.fromAsset = address(0); uint256 asset = pDesc.fee + dstAmount; IBridge(POLYBRIDGE).lock{value: asset}(pDesc.fromAsset, pDesc.toChainId, pDesc.toAddress, dstAmount, pDesc.fee, pDesc.id); } bytes32 transferId = keccak256( abi.encodePacked(address(this), pDesc.toAddress, pDesc.fromAsset, dstAmount, pDesc.toChainId, pDesc.nonce, uint64(block.chainid)) ); BridgeInfo memory tif = transferInfo[transferId]; require(tif.nonce == 0, " PLEXUS: transferId already exists. Check the nonce."); tif.dstToken = pDesc.fromAsset; tif.chainId = pDesc.toChainId; tif.amount = dstAmount; tif.user = msg.sender; tif.nonce = pDesc.nonce; tif.bridge = "PolyBridge"; transferInfo[transferId] = tif; emit Bridge(tif.user, tif.chainId, tif.dstToken, pDesc.toDstToken, dstAmount, transferId, tif.bridge); } function _multiChainBridgeStart(uint256 dstAmount, MultiChainDescription calldata mDesc) internal { address anyToken = anyTokenAddress[mDesc.srcToken]; dstAmount = _fee(mDesc.srcToken, dstAmount); if (mDesc.router == anyToken) { IMultichainERC20(anyToken).Swapout(dstAmount, mDesc.receiver); } else { if (_isNative(IERC20(mDesc.srcToken))) { IBridge(mDesc.router).anySwapOutNative{value: dstAmount}(anyToken, mDesc.receiver, mDesc.dstChainId); } else { IERC20(mDesc.srcToken).safeApprove(mDesc.router, dstAmount); IBridge(mDesc.router).anySwapOutUnderlying( anyToken != address(0) ? anyToken : mDesc.srcToken, mDesc.receiver, dstAmount, mDesc.dstChainId ); } } bytes32 transferId = keccak256( abi.encodePacked(address(this), mDesc.receiver, mDesc.srcToken, dstAmount, mDesc.dstChainId, mDesc.nonce, uint64(block.chainid)) ); BridgeInfo memory tif = transferInfo[transferId]; require(tif.nonce == 0, " PLEXUS: transferId already exists. Check the nonce."); tif.dstToken = mDesc.srcToken; tif.chainId = mDesc.dstChainId; tif.amount = dstAmount; tif.user = msg.sender; tif.nonce = mDesc.nonce; tif.bridge = "MultiChainBridge"; transferInfo[transferId] = tif; emit Bridge(tif.user, tif.chainId, tif.dstToken, mDesc.toDstToken, dstAmount, transferId, tif.bridge); } function _portalBridgeStart(uint256 dstAmount, PortalBridgeDescription calldata _Pdesc) internal { PortalBridgeDescription memory pDesc = _Pdesc; dstAmount = _fee(pDesc.token, dstAmount); bool isNotNative = !_isNative(IERC20(pDesc.token)); bytes32 userAddress = bytes32(uint256(uint160(pDesc.recipient))); if (isNotNative) { IERC20(pDesc.token).safeApprove(PORTAL, 0); IERC20(pDesc.token).safeApprove(PORTAL, dstAmount); IBridge(PORTAL).transferTokensWithPayload(pDesc.token, dstAmount, pDesc.recipientChain, userAddress, pDesc.nonce, pDesc.payload); } else { IBridge(PORTAL).wrapAndTransferETHWithPayload{value: dstAmount}(pDesc.recipientChain, userAddress, pDesc.nonce, pDesc.payload); } bytes32 transferId = keccak256( abi.encodePacked(address(this), pDesc.recipient, pDesc.token, dstAmount, pDesc.recipientChain, pDesc.nonce, uint64(block.chainid)) ); BridgeInfo memory tif = transferInfo[transferId]; require(tif.nonce == 0, " PLEXUS: transferId already exists. Check the nonce."); tif.dstToken = pDesc.token; tif.chainId = pDesc.recipientChain; tif.amount = dstAmount; tif.user = msg.sender; tif.nonce = pDesc.nonce; tif.bridge = "PortalBridge"; transferInfo[transferId] = tif; emit Bridge(tif.user, tif.chainId, tif.dstToken, pDesc.toDstToken, dstAmount, transferId, tif.bridge); } function _safeNativeTransfer(address to_, uint256 amount_) private { (bool sent, ) = to_.call{value: amount_}(""); require(sent, "Safe safeTransfer fail"); } }
// 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 anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // 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) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.0; import "./ECDSA.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ */ abstract contract EIP712 { /* solhint-disable var-name-mixedcase */ // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; uint256 private immutable _CACHED_CHAIN_ID; address private immutable _CACHED_THIS; bytes32 private immutable _HASHED_NAME; bytes32 private immutable _HASHED_VERSION; bytes32 private immutable _TYPE_HASH; /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); bytes32 typeHash = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; _CACHED_CHAIN_ID = block.chainid; _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); _CACHED_THIS = address(this); _TYPE_HASH = typeHash; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) { return _CACHED_DOMAIN_SEPARATOR; } else { return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); } } function _buildDomainSeparator( bytes32 typeHash, bytes32 nameHash, bytes32 versionHash ) private view returns (bytes32) { return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
pragma solidity 0.8.17; interface IBridge { // CBridge function send( address _receiver, address _token, uint256 _amount, uint64 _dstChainId, uint64 _nonce, uint32 _maxSilippage ) external; function sendNative( address _receiver, uint256 _amount, uint64 _dstChainId, uint64 _nonce, uint32 _maxSlippage ) external payable; function withdraw( bytes calldata _wdmsg, bytes[] memory _sigs, address[] memory _signers, uint256[] memory _powers ) external; //polyBridge function lock( address fromAsset, uint64 toChainId, bytes memory toAddress, uint256 amount, uint256 fee, uint256 id ) external payable; //PortalBridge function transferTokensWithPayload( address token, uint256 amount, uint16 recipientChain, bytes32 recipient, uint32 nonce, bytes memory payload ) external payable; function wrapAndTransferETHWithPayload( uint16 recipientChain, bytes32 recipient, uint32 nonce, bytes memory payload ) external payable; function transferTokens( address token, uint256 amount, uint16 recipientChain, bytes32 recipient, uint256 arbiterFee, uint32 nonce ) external payable returns (uint64 sequence); function wrapAndTransferETH( uint16 recipientChain, bytes32 recipient, uint256 arbiterFee, uint32 nonce ) external payable returns (uint64 sequence); function completeTransferWithPayload(bytes memory encodeVm) external returns (bytes memory); function completeTransferAndUnwrapETHWithPayload(bytes memory encodeVm) external returns (bytes memory); function completeTransfer(bytes memory encodeVm) external; function completeTransferAndUnwrapETH(bytes memory encodeVm) external; //MultichainBridge function anySwapOutUnderlying( address token, address to, uint256 amount, uint256 toChainID ) external; function anySwapOut( address token, address to, uint256 amount, uint256 toChainID ) external; function anySwapOutNative( address token, address to, uint256 toChainID ) external payable; function wNATIVE() external returns (address); function transfers(bytes32 transferId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.17; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.17; interface ISigsVerifier { /** * @notice Verifies that a message is signed by a quorum among the signers. * @param _msg signed message * @param _sigs list of signatures sorted by signer addresses * @param _signers sorted list of current signers * @param _powers powers of current signers */ function verifySigs( bytes memory _msg, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) external view; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import "../libraries/SafeERC20.sol"; using SafeERC20 for IERC20; struct BridgeInfo { string bridge; address dstToken; uint64 chainId; uint256 amount; address user; uint64 nonce; } struct CBridgeDescription { address srcToken; uint256 amount; address receiver; uint64 dstChainId; uint64 nonce; uint32 maxSlippage; address toDstToken; } struct SwapData { address user; address srcToken; address dstToken; uint256 amount; bytes callData; } struct MultiChainDescription { address srcToken; uint256 amount; address receiver; uint64 dstChainId; uint64 nonce; address router; address toDstToken; } struct PolyBridgeDescription { address fromAsset; uint64 toChainId; bytes toAddress; uint256 amount; uint256 fee; uint256 id; uint64 nonce; address toDstToken; } struct PortalBridgeDescription { address token; uint256 amount; uint16 recipientChain; address recipient; uint32 nonce; uint256 arbiterFee; bytes payload; address toDstToken; } struct AnyMapping { address tokenAddress; address anyTokenAddress; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.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 * ==== * * [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://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
pragma solidity 0.8.17; import "./SafeERC20.sol"; library AssetLib { using SafeERC20 for IERC20; uint256 private constant MAX_UINT = type(uint256).max; address internal constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; function getBalance(address token) internal view returns (uint256) { return token == NATIVE_ADDRESS ? address(this).balance : IERC20(token).balanceOf(address(this)); } function userBalance(address user, address token) internal view returns (uint256) { return token == NATIVE_ADDRESS ? user.balance : IERC20(token).balanceOf(user); } }
pragma solidity 0.8.17; library OrderLib { struct Order { uint256 salt; address makerAsset; address takerAsset; address maker; address receiver; address allowedSender; // equals to Zero address on public orders uint256 makingAmount; uint256 takingAmount; uint256 offsets; // bytes makerAssetData; // bytes takerAssetData; // bytes getMakingAmount; // this.staticcall(abi.encodePacked(bytes, swapTakerAmount)) => (swapMakerAmount) // bytes getTakingAmount; // this.staticcall(abi.encodePacked(bytes, swapMakerAmount)) => (swapTakerAmount) // bytes predicate; // this.staticcall(bytes) => (bool) // bytes permit; // On first fill: permit.1.call(abi.encodePacked(permit.selector, permit.2)) // bytes preInteraction; // bytes postInteraction; bytes interactions; // concat(makerAssetData, takerAssetData, getMakingAmount, getTakingAmount, predicate, permit, preIntercation, postInteraction) } struct OrderRFQ { uint256 info; // lowest 64 bits is the order id, next 64 bits is the expiration timestamp address makerAsset; address takerAsset; address maker; address allowedSender; // equals to Zero address on public orders uint256 makingAmount; uint256 takingAmount; } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.17; // runtime proto sol library library Pb { enum WireType { Varint, Fixed64, LengthDelim, StartGroup, EndGroup, Fixed32 } struct Buffer { uint256 idx; // the start index of next read. when idx=b.length, we're done bytes b; // hold serialized proto msg, readonly } // create a new in-memory Buffer object from raw msg bytes function fromBytes(bytes memory raw) internal pure returns (Buffer memory buf) { buf.b = raw; buf.idx = 0; } // whether there are unread bytes function hasMore(Buffer memory buf) internal pure returns (bool) { return buf.idx < buf.b.length; } // decode current field number and wiretype function decKey(Buffer memory buf) internal pure returns (uint256 tag, WireType wiretype) { uint256 v = decVarint(buf); tag = v / 8; wiretype = WireType(v & 7); } // count tag occurrences, return an array due to no memory map support // have to create array for (maxtag+1) size. cnts[tag] = occurrences // should keep buf.idx unchanged because this is only a count function function cntTags(Buffer memory buf, uint256 maxtag) internal pure returns (uint256[] memory cnts) { uint256 originalIdx = buf.idx; cnts = new uint256[](maxtag + 1); // protobuf's tags are from 1 rather than 0 uint256 tag; WireType wire; while (hasMore(buf)) { (tag, wire) = decKey(buf); cnts[tag] += 1; skipValue(buf, wire); } buf.idx = originalIdx; } // read varint from current buf idx, move buf.idx to next read, return the int value function decVarint(Buffer memory buf) internal pure returns (uint256 v) { bytes10 tmp; // proto int is at most 10 bytes (7 bits can be used per byte) bytes memory bb = buf.b; // get buf.b mem addr to use in assembly v = buf.idx; // use v to save one additional uint variable assembly { tmp := mload(add(add(bb, 32), v)) // load 10 bytes from buf.b[buf.idx] to tmp } uint256 b; // store current byte content v = 0; // reset to 0 for return value for (uint256 i = 0; i < 10; i++) { assembly { b := byte(i, tmp) // don't use tmp[i] because it does bound check and costs extra } v |= (b & 0x7F) << (i * 7); if (b & 0x80 == 0) { buf.idx += i + 1; return v; } } revert(); // i=10, invalid varint stream } // read length delimited field and return bytes function decBytes(Buffer memory buf) internal pure returns (bytes memory b) { uint256 len = decVarint(buf); uint256 end = buf.idx + len; require(end <= buf.b.length); // avoid overflow b = new bytes(len); bytes memory bufB = buf.b; // get buf.b mem addr to use in assembly uint256 bStart; uint256 bufBStart = buf.idx; assembly { bStart := add(b, 32) bufBStart := add(add(bufB, 32), bufBStart) } for (uint256 i = 0; i < len; i += 32) { assembly { mstore(add(bStart, i), mload(add(bufBStart, i))) } } buf.idx = end; } // return packed ints function decPacked(Buffer memory buf) internal pure returns (uint256[] memory t) { uint256 len = decVarint(buf); uint256 end = buf.idx + len; require(end <= buf.b.length); // avoid overflow // array in memory must be init w/ known length // so we have to create a tmp array w/ max possible len first uint256[] memory tmp = new uint256[](len); uint256 i = 0; // count how many ints are there while (buf.idx < end) { tmp[i] = decVarint(buf); i++; } t = new uint256[](i); // init t with correct length for (uint256 j = 0; j < i; j++) { t[j] = tmp[j]; } return t; } // move idx pass current value field, to beginning of next tag or msg end function skipValue(Buffer memory buf, WireType wire) internal pure { if (wire == WireType.Varint) { decVarint(buf); } else if (wire == WireType.LengthDelim) { uint256 len = decVarint(buf); buf.idx += len; // skip len bytes value data require(buf.idx <= buf.b.length); // avoid overflow } else { revert(); } // unsupported wiretype } // type conversion help utils function _bool(uint256 x) internal pure returns (bool v) { return x != 0; } function _uint256(bytes memory b) internal pure returns (uint256 v) { require(b.length <= 32); // b's length must be smaller than or equal to 32 assembly { v := mload(add(b, 32)) } // load all 32bytes to v v = v >> (8 * (32 - b.length)); // only first b.length is valid } function _address(bytes memory b) internal pure returns (address v) { v = _addressPayable(b); } function _addressPayable(bytes memory b) internal pure returns (address payable v) { require(b.length == 20); //load 32bytes then shift right 12 bytes assembly { v := div(mload(add(b, 32)), 0x1000000000000000000000000) } } function _bytes32(bytes memory b) internal pure returns (bytes32 v) { require(b.length == 32); assembly { v := mload(add(b, 32)) } } // uint[] to uint8[] function uint8s(uint256[] memory arr) internal pure returns (uint8[] memory t) { t = new uint8[](arr.length); for (uint256 i = 0; i < t.length; i++) { t[i] = uint8(arr[i]); } } function uint32s(uint256[] memory arr) internal pure returns (uint32[] memory t) { t = new uint32[](arr.length); for (uint256 i = 0; i < t.length; i++) { t[i] = uint32(arr[i]); } } function uint64s(uint256[] memory arr) internal pure returns (uint64[] memory t) { t = new uint64[](arr.length); for (uint256 i = 0; i < t.length; i++) { t[i] = uint64(arr[i]); } } function bools(uint256[] memory arr) internal pure returns (bool[] memory t) { t = new bool[](arr.length); for (uint256 i = 0; i < t.length; i++) { t[i] = arr[i] != 0; } } }
// SPDX-License-Identifier: GPL-3.0-only // Code generated by protoc-gen-sol. DO NOT EDIT. // source: contracts/libraries/proto/pool.proto pragma solidity 0.8.17; import "./Pb.sol"; library PbPool { using Pb for Pb.Buffer; // so we can call Pb funcs on Buffer obj struct WithdrawMsg { uint64 chainid; // tag: 1 uint64 seqnum; // tag: 2 address receiver; // tag: 3 address token; // tag: 4 uint256 amount; // tag: 5 bytes32 refid; // tag: 6 } // end struct WithdrawMsg function decWithdrawMsg(bytes memory raw) internal pure returns (WithdrawMsg memory m) { Pb.Buffer memory buf = Pb.fromBytes(raw); uint256 tag; Pb.WireType wire; while (buf.hasMore()) { (tag, wire) = buf.decKey(); if (false) {} // solidity has no switch/case else if (tag == 1) { m.chainid = uint64(buf.decVarint()); } else if (tag == 2) { m.seqnum = uint64(buf.decVarint()); } else if (tag == 3) { m.receiver = Pb._address(buf.decBytes()); } else if (tag == 4) { m.token = Pb._address(buf.decBytes()); } else if (tag == 5) { m.amount = Pb._uint256(buf.decBytes()); } else if (tag == 6) { m.refid = Pb._bytes32(buf.decBytes()); } else { buf.skipValue(wire); } // skip value of unknown tag } } // end decoder WithdrawMsg }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../interfaces/IERC20.sol"; import "./Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.17; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "../interfaces/ISigsVerifier.sol"; contract Signers is Ownable, ISigsVerifier { using ECDSA for bytes32; bytes32 public ssHash; uint256 public triggerTime; // timestamp when last update was triggered // reset can be called by the owner address for emergency recovery uint256 public resetTime; uint256 public noticePeriod; // advance notice period as seconds for reset uint256 constant MAX_INT = 2**256 - 1; event SignersUpdated(address[] _signers, uint256[] _powers); event ResetNotification(uint256 resetTime); /** * @notice Verifies that a message is signed by a quorum among the signers * The sigs must be sorted by signer addresses in ascending order. * @param _msg signed message * @param _sigs list of signatures sorted by signer addresses * @param _signers sorted list of current signers * @param _powers powers of current signers */ function verifySigs( bytes memory _msg, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) public view override { bytes32 h = keccak256(abi.encodePacked(_signers, _powers)); // require(ssHash == h, "Mismatch current signers"); _verifySignedPowers(keccak256(_msg).toEthSignedMessageHash(), _sigs, _signers, _powers); } /** * @notice Update new signers. * @param _newSigners sorted list of new signers * @param _curPowers powers of new signers * @param _sigs list of signatures sorted by signer addresses * @param _curSigners sorted list of current signers * @param _curPowers powers of current signers */ function updateSigners( uint256 _triggerTime, address[] calldata _newSigners, uint256[] calldata _newPowers, bytes[] calldata _sigs, address[] calldata _curSigners, uint256[] calldata _curPowers ) external { // use trigger time for nonce protection, must be ascending require(_triggerTime > triggerTime, "Trigger time is not increasing"); // make sure triggerTime is not too large, as it cannot be decreased once set require(_triggerTime < block.timestamp + 3600, "Trigger time is too large"); bytes32 domain = keccak256(abi.encodePacked(block.chainid, address(this), "UpdateSigners")); verifySigs(abi.encodePacked(domain, _triggerTime, _newSigners, _newPowers), _sigs, _curSigners, _curPowers); _updateSigners(_newSigners, _newPowers); triggerTime = _triggerTime; } /** * @notice reset signers, only used for init setup and emergency recovery */ function resetSigners(address[] calldata _signers, uint256[] calldata _powers) external onlyOwner { require(block.timestamp > resetTime, "not reach reset time"); resetTime = MAX_INT; _updateSigners(_signers, _powers); } function notifyResetSigners() external onlyOwner { resetTime = block.timestamp + noticePeriod; emit ResetNotification(resetTime); } function increaseNoticePeriod(uint256 period) external onlyOwner { require(period > noticePeriod, "notice period can only be increased"); noticePeriod = period; } // separate from verifySigs func to avoid "stack too deep" issue function _verifySignedPowers( bytes32 _hash, bytes[] calldata _sigs, address[] calldata _signers, uint256[] calldata _powers ) private pure { require(_signers.length == _powers.length, "signers and powers length not match"); uint256 totalPower; // sum of all signer.power for (uint256 i = 0; i < _signers.length; i++) { totalPower += _powers[i]; } uint256 quorum = (totalPower * 2) / 3 + 1; uint256 signedPower; // sum of signer powers who are in sigs address prev = address(0); uint256 index = 0; for (uint256 i = 0; i < _sigs.length; i++) { address signer = _hash.recover(_sigs[i]); require(signer > prev, "signers not in ascending order"); prev = signer; // now find match signer add its power while (signer > _signers[index]) { index += 1; require(index < _signers.length, "signer not found"); } if (signer == _signers[index]) { signedPower += _powers[index]; } if (signedPower >= quorum) { // return early to save gas return; } } revert("quorum not reached"); } function _updateSigners(address[] calldata _signers, uint256[] calldata _powers) private { require(_signers.length == _powers.length, "signers and powers length not match"); address prev = address(0); for (uint256 i = 0; i < _signers.length; i++) { require(_signers[i] > prev, "New signers not in ascending order"); prev = _signers[i]; } ssHash = keccak256(abi.encodePacked(_signers, _powers)); emit SignersUpdated(_signers, _powers); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract VerifySigEIP712 is EIP712("Plexus", "1"), Ownable { address[] public ownerList; struct Input { address fromTokenAddress; address toTokenAddress; uint256 amount; // ToChain넘어와서 브릿지가 볼트로 보내줄때 그 수량. ( 수루료 빠지기 전 ) uint256 gasFee; // 가스비를 확인해서 그만큼의 token수량 address userAddress; bytes32 txHash; } bytes32 private constant SWAP_TYPEHASH = keccak256("Input(address fromTokenAddress,address toTokenAddress,uint256 amount,uint256 gasFee,address userAddress,bytes32 txHash)"); function setSigner(address[] memory _owner) public onlyOwner { for (uint256 i = 0; i < _owner.length; i++) { ownerList.push(_owner[i]); } } function relaySig(Input memory _swapData, bytes[] memory signature) public view returns (bool) { uint256 CheckCount; Input memory inputData = _swapData; for (uint256 i = 0; i < signature.length; i++) { bytes32 digest = _hashTypedDataV4( keccak256( abi.encode( SWAP_TYPEHASH, inputData.fromTokenAddress, inputData.toTokenAddress, inputData.amount, inputData.gasFee, inputData.userAddress, inputData.txHash ) ) ); (bytes32 r, bytes32 s, uint8 v) = splitSignature(signature[i]); address signer = ECDSA.recover(digest, v, r, s); if (signer == ownerList[i]) { CheckCount++; } } if (CheckCount == signature.length) return true; else { revert("not match"); } } // 시그니쳐 넣으면 r s v 찢어주는 함수 function splitSignature(bytes memory sig) public pure returns ( bytes32 r, bytes32 s, uint8 v ) { require(sig.length == 65, "invalid signature length"); assembly { // first 32 bytes, after the length prefix r := mload(add(sig, 32)) // second 32 bytes s := mload(add(sig, 64)) // final byte (first byte of the next 32 bytes) v := byte(0, mload(add(sig, 96))) } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"cbridge","type":"address"},{"internalType":"address","name":"poly","type":"address"},{"internalType":"address","name":"portal","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint64","name":"chainId","type":"uint64"},{"indexed":false,"internalType":"address","name":"srcToken","type":"address"},{"indexed":false,"internalType":"address","name":"toDstToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"fromAmount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"transferId","type":"bytes32"},{"indexed":false,"internalType":"string","name":"bridge","type":"string"}],"name":"Bridge","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":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"toToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"returnAmount","type":"uint256"}],"name":"Relayswap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"resetTime","type":"uint256"}],"name":"ResetNotification","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"_signers","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"SignersUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"srcToken","type":"address"},{"indexed":false,"internalType":"address","name":"toToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"returnAmount","type":"uint256"}],"name":"Swap","type":"event"},{"inputs":[],"name":"CBRIDGE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"POLYBRIDGE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PORTAL","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint16","name":"recipientChain","type":"uint16"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint256","name":"arbiterFee","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"address","name":"toDstToken","type":"address"}],"internalType":"struct PortalBridgeDescription","name":"_Pdesc","type":"tuple"}],"name":"PortalBridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"ROUTER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"allowedRouter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"anyTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"uint32","name":"maxSlippage","type":"uint32"},{"internalType":"address","name":"toDstToken","type":"address"}],"internalType":"struct CBridgeDescription","name":"bDesc","type":"tuple"}],"name":"cBridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"period","type":"uint256"}],"name":"increaseNoticePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"routers","type":"address[]"}],"name":"initMultichain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"toDstToken","type":"address"}],"internalType":"struct MultiChainDescription","name":"mDesc","type":"tuple"}],"name":"multiChainBridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"noticePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"notifyResetSigners","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ownerList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"fromAsset","type":"address"},{"internalType":"uint64","name":"toChainId","type":"uint64"},{"internalType":"bytes","name":"toAddress","type":"bytes"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"toDstToken","type":"address"}],"internalType":"struct PolyBridgeDescription","name":"pDesc","type":"tuple"}],"name":"polyBridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodeVm","type":"bytes"},{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct SwapData","name":"_swap","type":"tuple"},{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"gasFee","type":"uint256"},{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes32","name":"txHash","type":"bytes32"}],"internalType":"struct VerifySigEIP712.Input","name":"_sigCollect","type":"tuple"},{"internalType":"bytes[]","name":"signature","type":"bytes[]"}],"name":"portalComplete","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"gasFee","type":"uint256"},{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes32","name":"txHash","type":"bytes32"}],"internalType":"struct VerifySigEIP712.Input","name":"_swapData","type":"tuple"},{"internalType":"bytes[]","name":"signature","type":"bytes[]"}],"name":"relaySig","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct SwapData","name":"_swap","type":"tuple"},{"components":[{"internalType":"address","name":"fromTokenAddress","type":"address"},{"internalType":"address","name":"toTokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"gasFee","type":"uint256"},{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes32","name":"txHash","type":"bytes32"}],"internalType":"struct VerifySigEIP712.Input","name":"_sigCollect","type":"tuple"},{"internalType":"bytes[]","name":"signature","type":"bytes[]"}],"name":"relaySwapRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_signers","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"resetSigners","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resetTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"percent","type":"uint256"}],"name":"setFeePercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_router","type":"address"},{"internalType":"address","name":"_cbridge","type":"address"},{"internalType":"address","name":"poly","type":"address"},{"internalType":"address","name":"portal","type":"address"}],"name":"setRouterBridge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_owner","type":"address[]"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_wdmsg","type":"bytes"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"},{"internalType":"address[]","name":"_signers","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"sigWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"splitSignature","outputs":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"ssHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct SwapData","name":"_swap","type":"tuple"},{"components":[{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"uint32","name":"maxSlippage","type":"uint32"},{"internalType":"address","name":"toDstToken","type":"address"}],"internalType":"struct CBridgeDescription","name":"bDesc","type":"tuple"}],"name":"swapCBridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct SwapData","name":"_swap","type":"tuple"},{"components":[{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint64","name":"dstChainId","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"toDstToken","type":"address"}],"internalType":"struct MultiChainDescription","name":"mDesc","type":"tuple"}],"name":"swapMultichain","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct SwapData","name":"_swap","type":"tuple"},{"components":[{"internalType":"address","name":"fromAsset","type":"address"},{"internalType":"uint64","name":"toChainId","type":"uint64"},{"internalType":"bytes","name":"toAddress","type":"bytes"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"address","name":"toDstToken","type":"address"}],"internalType":"struct PolyBridgeDescription","name":"pdesc","type":"tuple"}],"name":"swapPolyBridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct SwapData","name":"_swap","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint16","name":"recipientChain","type":"uint16"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint256","name":"arbiterFee","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"address","name":"toDstToken","type":"address"}],"internalType":"struct PortalBridgeDescription","name":"pDesc","type":"tuple"}],"name":"swapPortalBridge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"srcToken","type":"address"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct SwapData","name":"_swap","type":"tuple"}],"name":"swapRouter","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"transferInfo","outputs":[{"internalType":"string","name":"bridge","type":"string"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"transfers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"triggerTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"anyTokenAddress","type":"address"}],"internalType":"struct AnyMapping[]","name":"mappings","type":"tuple[]"}],"name":"updateAddressMapping","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_triggerTime","type":"uint256"},{"internalType":"address[]","name":"_newSigners","type":"address[]"},{"internalType":"uint256[]","name":"_newPowers","type":"uint256[]"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"},{"internalType":"address[]","name":"_curSigners","type":"address[]"},{"internalType":"uint256[]","name":"_curPowers","type":"uint256[]"}],"name":"updateSigners","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"userBridgeInfo","outputs":[{"internalType":"string","name":"bridge","type":"string"},{"internalType":"address","name":"dstToken","type":"address"},{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_msg","type":"bytes"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"},{"internalType":"address[]","name":"_signers","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"verifySigs","outputs":[],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6101406040526000600b553480156200001757600080fd5b5060405162005dd238038062005dd28339810160408190526200003a91620001fa565b6040805180820182526006815265506c6578757360d01b6020808301918252835180850190945260018452603160f81b908401528151902060e08190527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66101008190524660a0529192917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620001168184846040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b6080523060c0526101205250620001399250620001339150503390565b6200018d565b600680546001600160a01b039586166001600160a01b031991821617909155600780549486169482169490941790935560088054928516928416929092179091556009805491909316911617905562000257565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b0381168114620001f557600080fd5b919050565b600080600080608085870312156200021157600080fd5b6200021c85620001dd565b93506200022c60208601620001dd565b92506200023c60408601620001dd565b91506200024c60608601620001dd565b905092959194509250565b60805160a05160c05160e0516101005161012051615b2b620002a7600039600061401c0152600061406b0152600061404601526000613f9f01526000613fc901526000613ff30152615b2b6000f3fe6080604052600436106102555760003560e01c80637b25503a11610139578063c93341ec116100b6578063da4cf3a21161007a578063da4cf3a2146106e9578063def79ab5146106fc578063e2d7ddbb1461071c578063eda82b4b1461073c578063f20c922a1461074f578063f2fde38b1461076f57600080fd5b8063c93341ec1461063d578063cc818ad11461065d578063cebaf8a91461067d578063d0790da91461069d578063d1f906d1146106b357600080fd5b8063a3142fae116100fd578063a3142fae1461057a578063a7bb58031461058d578063a7bdf45a146105cb578063acf64c43146105eb578063ba2cb25c1461061d57600080fd5b80637b25503a146104f35780637ce3489b146105135780638da5cb5b146105335780639b14d4c6146105515780639f37a0cb1461056757600080fd5b8063370fb47b116101d2578063682dbc2211610196578063682dbc221461046557806369773796146104855780636e65796614610498578063715018a6146104ab5780637a79a608146104c05780637ae86aca146104e057600080fd5b8063370fb47b146103c85780633c64f04b146103ec5780634d178cad1461041c5780635fafa99d1461042f57806365a114f11461044f57600080fd5b806325c38b9f1161021957806325c38b9f1461032057806329f8de45146103355780632e11f5c41461035557806330ca07d51461036857806332fe7b26146103a857600080fd5b80630be34ad1146102615780630ff754ea14610283578063129017f2146102c0578063223796f7146102e057806322ee82db1461030057600080fd5b3661025c57005b600080fd5b34801561026d57600080fd5b5061028161027c3660046144c8565b61078f565b005b34801561028f57600080fd5b506009546102a3906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102cc57600080fd5b506102816102db3660046146df565b61080b565b3480156102ec57600080fd5b506102816102fb36600461477a565b610b2e565b34801561030c57600080fd5b5061028161031b3660046147ef565b610d94565b34801561032c57600080fd5b50610281610e0d565b34801561034157600080fd5b506008546102a3906001600160a01b031681565b61028161036336600461488d565b610e5c565b34801561037457600080fd5b506103986103833660046148dc565b60106020526000908152604090205460ff1681565b60405190151581526020016102b7565b3480156103b457600080fd5b506006546102a3906001600160a01b031681565b3480156103d457600080fd5b506103de60025481565b6040519081526020016102b7565b3480156103f857600080fd5b506103986104073660046148f7565b600e6020526000908152604090205460ff1681565b61028161042a366004614923565b610e98565b34801561043b57600080fd5b5061028161044a366004614957565b610ee9565b34801561045b57600080fd5b506103de60035481565b34801561047157600080fd5b506102816104803660046149c5565b610f4b565b610281610493366004614923565b610ff2565b6102816104a636600461488d565b611031565b3480156104b757600080fd5b50610281611097565b3480156104cc57600080fd5b506102816104db366004614a83565b6110ab565b6102816104ee366004614b71565b611367565b3480156104ff57600080fd5b5061028161050e366004614b8d565b6113a6565b34801561051f57600080fd5b5061028161052e3660046148f7565b611491565b34801561053f57600080fd5b506000546001600160a01b03166102a3565b34801561055d57600080fd5b506103de60045481565b610281610575366004614c01565b6114c2565b610281610588366004614c64565b6114ee565b34801561059957600080fd5b506105ad6105a8366004614c98565b61150b565b60408051938452602084019290925260ff16908201526060016102b7565b3480156105d757600080fd5b506102816105e6366004614ccc565b61157f565b3480156105f757600080fd5b5061060b6106063660046148f7565b6115e1565b6040516102b796959493929190614d87565b34801561062957600080fd5b50610281610638366004614dde565b6116b8565b34801561064957600080fd5b50610398610658366004614f69565b6117f9565b34801561066957600080fd5b50610281610678366004614fad565b611998565b34801561068957600080fd5b5061060b610698366004615005565b611a69565b3480156106a957600080fd5b506103de60015481565b3480156106bf57600080fd5b506102a36106ce3660046148dc565b600f602052600090815260409020546001600160a01b031681565b6102816106f7366004614b71565b611a8f565b34801561070857600080fd5b506102a36107173660046148f7565b611ace565b34801561072857600080fd5b506007546102a3906001600160a01b031681565b61028161074a366004614c01565b611af8565b34801561075b57600080fd5b5061028161076a3660046148f7565b611b24565b34801561077b57600080fd5b5061028161078a3660046148dc565b611b8e565b600a546001600160a01b03163314806107b257506000546001600160a01b031633145b6107bb57600080fd5b600680546001600160a01b039586166001600160a01b0319918216179091556007805494861694821694909417909355600880549285169284169290921790915560098054919093169116179055565b610813611c07565b82600061082e61082960408401602085016148dc565b611c61565b1590508361083f60208401846148dc565b6001600160a01b031661085860a08301608084016148dc565b6001600160a01b031614801561088457508260600135816060013582604001356108829190615045565b145b80156108bf575061089b60608401604085016148dc565b6001600160a01b03166108b460408301602084016148dc565b6001600160a01b0316145b6108c857600080fd5b6108e06108da36839003830183615058565b856117f9565b5060a08101356000908152600e602052604090205460ff161561090257600080fd5b600061091660608301356040840135615045565b90508215610a0a5760095460405163c3f511c160e01b81526001600160a01b039091169063c3f511c19061094e908b90600401615074565b6000604051808303816000875af115801561096d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109959190810190615087565b506006546109c4906001600160a01b0316826109b460208601866148dc565b6001600160a01b03169190611c83565b606082013515610a0557610a056109e36000546001600160a01b031690565b60608401356109f560208601866148dc565b6001600160a01b03169190611dcb565b610aab565b6009546040516307211d7960e21b81526001600160a01b0390911690631c8475e490610a3a908b90600401615074565b6000604051808303816000875af1158015610a59573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a819190810190615087565b50606082013515610aab57610aab610aa16000546001600160a01b031690565b8360600135611dfb565b6000610ab685611e97565b90507fdef08483254d44ac41909d1188fb7c523c398e22edeab0e1d9c941a98629b5d3610ae960a08501608086016148dc565b610af960408601602087016148dc565b604080516001600160a01b039384168152929091166020830152810183905260600160405180910390a1505050505050505050565b610b36611c07565b8282610b4560208301836148dc565b6001600160a01b0316610b5e60a08301608084016148dc565b6001600160a01b0316148015610b8a5750816060013581606001358260400135610b889190615045565b145b8015610bc55750610ba160608301604084016148dc565b6001600160a01b0316610bba60408301602084016148dc565b6001600160a01b0316145b610bce57600080fd5b610be6610be036839003830183615058565b846117f9565b5060a08101356000908152600e602052604090205460ff1615610c465760405162461bcd60e51b8152602060048201526013602482015272736166655472616e736665722065786973747360681b60448201526064015b60405180910390fd5b60a08101356000908152600e602090815260408220805460ff19166001179055610c7690610829908401846148dc565b1590506000610c8d60608401356040850135615045565b90508115610ce957600654610cb3906001600160a01b0316826109b460208701876148dc565b606083013515610ce457610ce4610cd26000546001600160a01b031690565b60608501356109f560208701876148dc565b610d12565b606083013515610d1257610d12610d086000546001600160a01b031690565b8460600135611dfb565b6000610d1d85611e97565b90507fdef08483254d44ac41909d1188fb7c523c398e22edeab0e1d9c941a98629b5d3610d5060a08601608087016148dc565b610d6060408701602088016148dc565b604080516001600160a01b039384168152929091166020830152810183905260600160405180910390a15050505050505050565b610d9c611c07565b60005b8151811015610e09576005828281518110610dbc57610dbc6150fd565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b0390921691909117905580610e0181615113565b915050610d9f565b5050565b610e15611c07565b600454610e22904261512c565b60038190556040519081527f68e825132f7d4bc837dea2d64ac9fc19912bf0224b67f9317d8f1a917f5304a19060200160405180910390a1565b81610e7a610e7060408301602084016148dc565b8260600135612032565b506000610e8682612075565b9050610e928184612148565b50505050565b6000610eaa61082960208401846148dc565b1590508015610edb57610edb33306060850135610eca60208701876148dc565b6001600160a01b03169291906125ab565b610e098260600135836125e3565b610ef1611c07565b6000610efc83611c61565b1590508015610f3057610f2b610f1a6000546001600160a01b031690565b6001600160a01b0385169084611dcb565b505050565b610f2b610f456000546001600160a01b031690565b83611dfb565b600084848484604051602001610f6494939291906151a7565b604051602081830303815290604052805190602001209050610fe8610fdd89805190602001206040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b8888888888886129ec565b5050505050505050565b600061100461082960208401846148dc565b159050801561102357611023333060208501803590610eca90876148dc565b610e09826020013583612ccd565b81611045610e7060408301602084016148dc565b50600061105182612075565b90506010600061106760c0860160a087016148dc565b6001600160a01b0316815260208101919091526040016000205460ff1661108d57600080fd5b610e92818461313f565b61109f611c07565b6110a96000613716565b565b600754604051630144352560e71b81526001600160a01b039091169063a21a9280906110e9908b908b908b908b908b908b908b908b9060040161526a565b600060405180830381600087803b15801561110357600080fd5b505af1158015611117573d6000803e3d6000fd5b505060075460405160009350611166925046916001600160a01b03169060200191825260601b6001600160601b03191660208201526a57697468647261774d736760a81b6034820152603f0190565b6040516020818303038152906040528051906020012090506111b0818a8a60405160200161119693929190615347565b604051602081830303815290604052888888888888610f4b565b60006111f18a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061376692505050565b90506000600d60008360a0015181526020019081526020016000206040518060c001604052908160008201805461122790615361565b80601f016020809104026020016040519081016040528092919081815260200182805461125390615361565b80156112a05780601f10611275576101008083540402835291602001916112a0565b820191906000526020600020905b81548152906001019060200180831161128357829003601f168201915b505050918352505060018201546001600160a01b038082166020808501919091526001600160401b03600160a01b938490048116604086015260028601546060860152600390950154918216608085015291900490921660a09091015281015190915060009061130f90611c61565b1590508015611347576113428260800151836060015184602001516001600160a01b0316611dcb9092919063ffffffff16565b611359565b61135982608001518360600151611dfb565b505050505050505050505050565b600061137961082960208401846148dc565b159050801561139857611398333060208501803590610eca90876148dc565b610e0982602001358361313f565b600a546001600160a01b03163314806113c957506000546001600160a01b031633145b6113d257600080fd5b60005b6001600160401b038116821115610f2b578282826001600160401b0316818110611401576114016150fd565b905060400201602001602081019061141991906148dc565b600f60008585856001600160401b0316818110611438576114386150fd565b61144e92602060409092020190810191506148dc565b6001600160a01b039081168252602082019290925260400160002080546001600160a01b031916929091169190911790558061148981615395565b9150506113d5565b600a546001600160a01b03163314806114b457506000546001600160a01b031633145b6114bd57600080fd5b600b55565b816114d6610e7060408301602084016148dc565b5060006114e282612075565b9050610e9281846125e3565b611501610e7060408301602084016148dc565b50610e0981611e97565b600080600083516041146115615760405162461bcd60e51b815260206004820152601860248201527f696e76616c6964207369676e6174757265206c656e67746800000000000000006044820152606401610c3d565b50505060208101516040820151606090920151909260009190911a90565b611587611c07565b60035442116115cf5760405162461bcd60e51b81526020600482015260146024820152736e6f742072656163682072657365742074696d6560601b6044820152606401610c3d565b600019600355610e92848484846138be565b600d602052600090815260409020805481906115fc90615361565b80601f016020809104026020016040519081016040528092919081815260200182805461162890615361565b80156116755780601f1061164a57610100808354040283529160200191611675565b820191906000526020600020905b81548152906001019060200180831161165857829003601f168201915b5050506001840154600285015460039095015493946001600160a01b03808316956001600160401b03600160a01b94859004811696509294509081169290041686565b6002548b116117095760405162461bcd60e51b815260206004820152601e60248201527f547269676765722074696d65206973206e6f7420696e6372656173696e6700006044820152606401610c3d565b61171542610e1061512c565b8b106117635760405162461bcd60e51b815260206004820152601960248201527f547269676765722074696d6520697320746f6f206c61726765000000000000006044820152606401610c3d565b600046306040516020016117a492919091825260601b6001600160601b03191660208201526c5570646174655369676e65727360981b603482015260410190565b6040516020818303038152906040528051906020012090506117da818d8d8d8d8d604051602001611196969594939291906153bb565b6117e68b8b8b8b6138be565b5050506002989098555050505050505050565b60008083815b845181101561194a5760006118b37f23708f9a7a9c68b1a6cd4e9244f4b17e38b50b4448142b6ba580ab9052fe7d1e846000015185602001518660400151876060015188608001518960a0015160405160200161189897969594939291909687526001600160a01b03958616602088015293851660408701526060860192909252608085015290911660a083015260c082015260e00190565b60405160208183030381529060405280519060200120613a1d565b905060008060006118dc8986815181106118cf576118cf6150fd565b602002602001015161150b565b92509250925060006118f085838686613a6b565b905060058681548110611905576119056150fd565b6000918252602090912001546001600160a01b0390811690821603611932578761192e81615113565b9850505b5050505050808061194290615113565b9150506117ff565b508351820361195e57600192505050611992565b60405162461bcd60e51b81526020600482015260096024820152680dcdee840dac2e8c6d60bb1b6044820152606401610c3d565b92915050565b600a546001600160a01b03163314806119bb57506000546001600160a01b031633145b6119c457600080fd5b8060005b81811015610e925760008484838181106119e4576119e46150fd565b90506020020160208101906119f991906148dc565b6001600160a01b031603611a0c57600080fd5b600160106000868685818110611a2457611a246150fd565b9050602002016020810190611a3991906148dc565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790556001016119c8565b600c6020908152600092835260408084209091529082529020805481906115fc90615361565b6000611aa161082960208401846148dc565b1590508015611ac057611ac0333060208501803590610eca90876148dc565b610e09826020013583612148565b60058181548110611ade57600080fd5b6000918252602090912001546001600160a01b0316905081565b81611b0c610e7060408301602084016148dc565b506000611b1882612075565b9050610e928184612ccd565b611b2c611c07565b6004548111611b895760405162461bcd60e51b815260206004820152602360248201527f6e6f7469636520706572696f642063616e206f6e6c7920626520696e637265616044820152621cd95960ea1b6064820152608401610c3d565b600455565b611b96611c07565b6001600160a01b038116611bfb5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c3d565b611c0481613716565b50565b6000546001600160a01b031633146110a95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c3d565b6001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1490565b801580611cfd5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611cd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cfb91906153e3565b155b611d685760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610c3d565b6040516001600160a01b038316602482015260448101829052610f2b90849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613a93565b6040516001600160a01b038316602482015260448101829052610f2b90849063a9059cbb60e01b90606401611d94565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611e48576040519150601f19603f3d011682016040523d82523d6000602084013e611e4d565b606091505b5050905080610f2b5760405162461bcd60e51b815260206004820152601660248201527514d85999481cd85999551c985b9cd9995c8819985a5b60521b6044820152606401610c3d565b60008181611eae61082960408401602085016148dc565b90506000611ed7611ec260208501856148dc565b611ed260608601604087016148dc565b613b65565b6006549091506000906001600160a01b031683611ef5576000611efb565b84606001355b611f0860808701876153fc565b604051611f16929190615442565b60006040518083038185875af1925050503d8060008114611f53576040519150601f19603f3d011682016040523d82523d6000602084013e611f58565b606091505b50509050801561025c576000611f84611f7460208701876148dc565b611ed260608801604089016148dc565b9050828111611f935780611f9d565b611f9d8382615045565b95507fcd3829a3813dc3cdd188fd3d01dcf3268c16be2fdd2dd21d0665418816e46062611fcd60208701876148dc565b611fdd60408801602089016148dc565b611fed6060890160408a016148dc565b604080516001600160a01b0394851681529284166020840152921681830152606088810135908201526080810189905290519081900360a00190a15050505050919050565b600061203d83611c61565b15905080156119925761205b6001600160a01b0384163330856125ab565b600654611992906001600160a01b03858116911684611c83565b6000818161208c61082960408401602085016148dc565b905060006120a86120a360608501604086016148dc565b613c0d565b6006549091506000906001600160a01b0316836120c65760006120cc565b84606001355b6120d960808701876153fc565b6040516120e7929190615442565b60006040518083038185875af1925050503d8060008114612124576040519150601f19603f3d011682016040523d82523d6000602084013e612129565b606091505b50509050801561025c576000611f846120a360608701604088016148dc565b600061215936839003830183615466565b9050612169816000015184613ca7565b9250600061217a8260000151611c61565b159050801561224b57600754825161219f916001600160a01b03918216911686611c83565b60075460408381015184516060860151608087015160a0880151945163a5977fbb60e01b81526001600160a01b0394851660048201529284166024840152604483018a90526001600160401b03918216606484015216608482015263ffffffff90921660a48301529091169063a5977fbb9060c401600060405180830381600087803b15801561222e57600080fd5b505af1158015612242573d6000803e3d6000fd5b50505050612303565b6007546040838101516060850151608086015160a08701519351633f2e5fc360e01b81526001600160a01b039384166004820152602481018a90526001600160401b0392831660448201529116606482015263ffffffff909216608483015290911690633f2e5fc390869060a4016000604051808303818588803b1580156122d257600080fd5b505af11580156122e6573d6000803e3d6000fd5b505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc285525050505b60003083604001518460000151878660600151876080015146604051602001612332979695949392919061550e565b6040516020818303038152906040528051906020012090506000600d60008381526020019081526020016000206040518060c001604052908160008201805461237a90615361565b80601f01602080910402602001604051908101604052809291908181526020018280546123a690615361565b80156123f35780601f106123c8576101008083540402835291602001916123f3565b820191906000526020600020905b8154815290600101906020018083116123d657829003601f168201915b505050918352505060018201546001600160a01b0380821660208401526001600160401b03600160a01b928390048116604085015260028501546060850152600390940154908116608084015204821660a091820152820151919250161561246d5760405162461bcd60e51b8152600401610c3d9061556d565b83516001600160a01b03166020808301919091526060808601516001600160401b03908116604080860191909152918401899052336080808601919091528701511660a08401528051808201825260078152664342726964676560c81b8184015283526000848152600d9092529020815182919081906124ed908261560f565b506020828101516001830180546040808701516001600160401b03908116600160a01b9081026001600160e01b03199485166001600160a01b039788161717909455606088015160028801556080808901516003909801805460a0909a01519092169094029790921695909316949094179490941790925591830151838201519284015160c088015185519351600080516020615ad68339815191529561259b95909392918d918a916156ce565b60405180910390a1505050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052610e929085906323b872dd60e01b90608401611d94565b60006125ee8261572c565b905060006125ff8260000151611c61565b905061260f826000015185613ca7565b9350806126b7576008548251612632916001600160a01b03918216911686611c83565b60085460808301518351602085015160408087015160a088015191516360de1a9b60e01b81526001600160a01b03909616956360de1a9b95946126809490939092918c9187916004016157d4565b6000604051808303818588803b15801561269957600080fd5b505af11580156126ad573d6000803e3d6000fd5b5050505050612752565b600080835260808301516126cc90869061512c565b60085484516020860151604080880151608089015160a08a015192516360de1a9b60e01b81529697506001600160a01b03909516956360de1a9b95889561271e9590949093928e9291906004016157d4565b6000604051808303818588803b15801561273757600080fd5b505af115801561274b573d6000803e3d6000fd5b5050505050505b600030836040015184600001518786602001518760c00151466040516020016127819796959493929190615825565b6040516020818303038152906040528051906020012090506000600d60008381526020019081526020016000206040518060c00160405290816000820180546127c990615361565b80601f01602080910402602001604051908101604052809291908181526020018280546127f590615361565b80156128425780601f1061281757610100808354040283529160200191612842565b820191906000526020600020905b81548152906001019060200180831161282557829003601f168201915b505050918352505060018201546001600160a01b0380821660208401526001600160401b03600160a01b928390048116604085015260028501546060850152600390940154908116608084015204821660a09182015282015191925016156128bc5760405162461bcd60e51b8152600401610c3d9061556d565b83516001600160a01b0316602080830191909152808501516001600160401b039081166040808501919091526060840189905233608085015260c087015190911660a084015280518082018252600a815269506f6c7942726964676560b01b8184015283526000848152600d90925290208151829190819061293e908261560f565b506020828101516001830180546040808701516001600160401b03908116600160a01b9081026001600160e01b03199485166001600160a01b039788161717909455606088015160028801556080808901516003909801805460a0909a01519092169094029790921695909316949094179490941790925591830151838201519284015160e088015185519351600080516020615ad68339815191529561259b95909392918d918a916156ce565b828114612a0b5760405162461bcd60e51b8152600401610c3d9061589b565b6000805b84811015612a4f57838382818110612a2957612a296150fd565b9050602002013582612a3b919061512c565b915080612a4781615113565b915050612a0f565b5060006003612a5f8360026158de565b612a6991906158f5565b612a7490600161512c565b905060008080805b8a811015612c86576000612aff8d8d84818110612a9b57612a9b6150fd565b9050602002810190612aad91906153fc565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508f613d3390919063ffffffff16565b9050836001600160a01b0316816001600160a01b031611612b625760405162461bcd60e51b815260206004820152601e60248201527f7369676e657273206e6f7420696e20617363656e64696e67206f7264657200006044820152606401610c3d565b8093505b8a8a84818110612b7857612b786150fd565b9050602002016020810190612b8d91906148dc565b6001600160a01b0316816001600160a01b03161115612bfa57612bb160018461512c565b9250898310612bf55760405162461bcd60e51b815260206004820152601060248201526f1cda59db995c881b9bdd08199bdd5b9960821b6044820152606401610c3d565b612b66565b8a8a84818110612c0c57612c0c6150fd565b9050602002016020810190612c2191906148dc565b6001600160a01b0316816001600160a01b031603612c6057888884818110612c4b57612c4b6150fd565b9050602002013585612c5d919061512c565b94505b858510612c735750505050505050612cc4565b5080612c7e81615113565b915050612a7c565b5060405162461bcd60e51b81526020600482015260126024820152711c5d5bdc9d5b481b9bdd081c995858da195960721b6044820152606401610c3d565b50505050505050565b6000612cd882615929565b9050612ce8816000015184613ca7565b92506000612cf98260000151611c61565b6060830151901591506001600160a01b03168115612dc9576009548351612d2e916001600160a01b0391821691166000611c83565b6009548351612d4a916001600160a01b03918216911687611c83565b6009548351604080860151608087015160c088015192516362d2f5ed60e11b81526001600160a01b039095169463c5a5ebda94612d929490938c9390928992906004016159cd565b600060405180830381600087803b158015612dac57600080fd5b505af1158015612dc0573d6000803e3d6000fd5b50505050612e40565b600954604080850151608086015160c08701519251632fba737f60e21b81526001600160a01b039094169363bee9cdfc938a93612e0d939092889290600401615a10565b6000604051808303818588803b158015612e2657600080fd5b505af1158015612e3a573d6000803e3d6000fd5b50505050505b60608381015184516040808701516080880151915130861b6001600160601b0319908116602083015294861b851660348201529290941b9092166048820152605c810188905260f09290921b6001600160f01b031916607c83015260e01b6001600160e01b031916607e8201524660c01b6001600160c01b0319166082820152600090608a016040516020818303038152906040528051906020012090506000600d60008381526020019081526020016000206040518060c0016040529081600082018054612f0e90615361565b80601f0160208091040260200160405190810160405280929190818152602001828054612f3a90615361565b8015612f875780601f10612f5c57610100808354040283529160200191612f87565b820191906000526020600020905b815481529060010190602001808311612f6a57829003601f168201915b505050918352505060018201546001600160a01b0380821660208401526001600160401b03600160a01b928390048116604085015260028501546060850152600390940154908116608084015204821660a09182015282015191925016156130015760405162461bcd60e51b8152600401610c3d9061556d565b84516001600160a01b031660208083019190915260408087015161ffff1681840152606083018990523360808085019190915287015163ffffffff1660a084015280518082018252600c81526b506f7274616c42726964676560a01b8184015283526000848152600d909252902081518291908190613080908261560f565b506020828101516001830180546040808701516001600160401b03908116600160a01b9081026001600160e01b03199485166001600160a01b039788161717909455606088015160028801556080808901516003909801805460a0909a01519092169094029790921695909316949094179490941790925591830151838201519284015160e089015185519351600080516020615ad68339815191529561312e95909392918e918a916156ce565b60405180910390a150505050505050565b6000600f8161315160208501856148dc565b6001600160a01b03908116825260208083019390935260409091016000205416915061318990613183908401846148dc565b84613ca7565b92506001600160a01b0381166131a560c0840160a085016148dc565b6001600160a01b031603613249576001600160a01b03811663628d6cba846131d360608601604087016148dc565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af115801561321f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132439190615a3f565b50613407565b61325961082960208401846148dc565b156133135761326e60c0830160a084016148dc565b6001600160a01b031663a5e56571848361328e60608701604088016148dc565b61329e6080880160608901615a61565b6040516001600160e01b031960e087901b1681526001600160a01b0393841660048201529290911660248301526001600160401b031660448201526064016000604051808303818588803b1580156132f557600080fd5b505af1158015613309573d6000803e3d6000fd5b5050505050613407565b61333461332660c0840160a085016148dc565b846109b460208601866148dc565b61334460c0830160a084016148dc565b6001600160a01b039081169063edbdf5e290831661336e5761336960208501856148dc565b613370565b825b61338060608601604087016148dc565b866133916080880160608901615a61565b6040516001600160e01b031960e087901b1681526001600160a01b03948516600482015293909216602484015260448301526001600160401b03166064820152608401600060405180830381600087803b1580156133ee57600080fd5b505af1158015613402573d6000803e3d6000fd5b505050505b60003061341a60608501604086016148dc565b61342760208601866148dc565b866134386080880160608901615a61565b61344860a0890160808a01615a61565b4660405160200161345f979695949392919061550e565b6040516020818303038152906040528051906020012090506000600d60008381526020019081526020016000206040518060c00160405290816000820180546134a790615361565b80601f01602080910402602001604051908101604052809291908181526020018280546134d390615361565b80156135205780601f106134f557610100808354040283529160200191613520565b820191906000526020600020905b81548152906001019060200180831161350357829003601f168201915b505050918352505060018201546001600160a01b0380821660208401526001600160401b03600160a01b928390048116604085015260028501546060850152600390940154908116608084015204821660a091820152820151919250161561359a5760405162461bcd60e51b8152600401610c3d9061556d565b6135a760208501856148dc565b6001600160a01b031660208201526135c56080850160608601615a61565b6001600160401b0316604082015260608101859052336080808301919091526135f49060a08601908601615a61565b6001600160401b031660a0820152604080518082018252601081526f4d756c7469436861696e42726964676560801b6020808301919091529083526000848152600d909152208151829190819061364b908261560f565b506020828101516001830180546040808701516001600160401b03908116600160a01b9081026001600160e01b03199485166001600160a01b039788161717909455606088015160028801556080808901516003909801805460a0909a015190921690940297909216959093169490941794909417909255918301519083015191830151600080516020615ad683398151915292906136f060e0890160c08a016148dc565b855160405161370795949392918c918a91906156ce565b60405180910390a15050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040805160c08101825260008082526020808301829052828401829052606083018290526080830182905260a0830182905283518085019094528184528301849052909190805b602083015151835110156138b6576137c483613d57565b9092509050816001036137ea576137da83613d91565b6001600160401b031684526137ad565b8160020361380e576137fb83613d91565b6001600160401b031660208501526137ad565b8160030361383a5761382761382284613e0c565b613ec8565b6001600160a01b031660408501526137ad565b816004036138615761384e61382284613e0c565b6001600160a01b031660608501526137ad565b816005036138845761387a61387584613e0c565b613ed3565b60808501526137ad565b816006036138a75761389d61389884613e0c565b613f0a565b60a08501526137ad565b6138b18382613f22565b6137ad565b505050919050565b8281146138dd5760405162461bcd60e51b8152600401610c3d9061589b565b6000805b848110156139b657816001600160a01b0316868683818110613905576139056150fd565b905060200201602081019061391a91906148dc565b6001600160a01b03161161397b5760405162461bcd60e51b815260206004820152602260248201527f4e6577207369676e657273206e6f7420696e20617363656e64696e67206f726460448201526132b960f11b6064820152608401610c3d565b85858281811061398d5761398d6150fd565b90506020020160208101906139a291906148dc565b9150806139ae81615113565b9150506138e1565b50848484846040516020016139ce94939291906151a7565b60408051601f198184030181529082905280516020909101206001557ff126123539a68393c55697f617e7d1148e371988daed246c2f41da99965a23f890613707908790879087908790615a7c565b6000611992613a2a613f92565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000613a7c878787876140b9565b91509150613a898161417d565b5095945050505050565b6000613ae8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166142c79092919063ffffffff16565b805190915015610f2b5780806020019051810190613b069190615a3f565b610f2b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610c3d565b60006001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14613bfa576040516370a0823160e01b81526001600160a01b0384811660048301528316906370a0823190602401602060405180830381865afa158015613bd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bf591906153e3565b613c06565b826001600160a01b0316315b9392505050565b60006001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14613ca0576040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015613c77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c9b91906153e3565b611992565b4792915050565b600080612710600b5484613cbb91906158de565b613cc591906158f5565b9050613cd18184615045565b91508015613d2c57613ce284611c61565b613d1157613d0c613cfb6000546001600160a01b031690565b6001600160a01b0386169083611dcb565b613d2c565b613d2c613d266000546001600160a01b031690565b82611dfb565b5092915050565b6000806000613d4285856142de565b91509150613d4f8161417d565b509392505050565b6000806000613d6584613d91565b9050613d726008826158f5565b9250806007166005811115613d8957613d89615aa3565b915050915091565b602080820151825181019091015160009182805b600a81101561025c5783811a9150613dbe8160076158de565b82607f16901b8517945081608016600003613dfa57613dde81600161512c565b86518790613ded90839061512c565b9052509395945050505050565b80613e0481615113565b915050613da5565b60606000613e1983613d91565b90506000818460000151613e2d919061512c565b9050836020015151811115613e4157600080fd5b816001600160401b03811115613e5957613e5961451c565b6040519080825280601f01601f191660200182016040528015613e83576020820181803683370190505b50602080860151865192955091818601919083010160005b85811015613ebd578181015183820152613eb660208261512c565b9050613e9b565b505050935250919050565b600061199282614323565b6000602082511115613ee457600080fd5b6020820151905081516020613ef99190615045565b613f049060086158de565b1c919050565b60008151602014613f1a57600080fd5b506020015190565b6000816005811115613f3657613f36615aa3565b03613f4457610f2b82613d91565b6002816005811115613f5857613f58615aa3565b0361025c576000613f6883613d91565b90508083600001818151613f7c919061512c565b90525060208301515183511115610f2b57600080fd5b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015613feb57507f000000000000000000000000000000000000000000000000000000000000000046145b1561401557507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156140f05750600090506003614174565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614144573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661416d57600060019250925050614174565b9150600090505b94509492505050565b600081600481111561419157614191615aa3565b036141995750565b60018160048111156141ad576141ad615aa3565b036141fa5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610c3d565b600281600481111561420e5761420e615aa3565b0361425b5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610c3d565b600381600481111561426f5761426f615aa3565b03611c045760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610c3d565b60606142d68484600085614342565b949350505050565b60008082516041036143145760208301516040840151606085015160001a614308878285856140b9565b9450945050505061431c565b506000905060025b9250929050565b6000815160141461433357600080fd5b5060200151600160601b900490565b6060824710156143a35760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610c3d565b6001600160a01b0385163b6143fa5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c3d565b600080866001600160a01b031685876040516144169190615ab9565b60006040518083038185875af1925050503d8060008114614453576040519150601f19603f3d011682016040523d82523d6000602084013e614458565b606091505b5091509150614468828286614473565b979650505050505050565b60608315614482575081613c06565b8251156144925782518084602001fd5b8160405162461bcd60e51b8152600401610c3d9190615074565b80356001600160a01b03811681146144c357600080fd5b919050565b600080600080608085870312156144de57600080fd5b6144e7856144ac565b93506144f5602086016144ac565b9250614503604086016144ac565b9150614511606086016144ac565b905092959194509250565b634e487b7160e01b600052604160045260246000fd5b60405161010081016001600160401b03811182821017156145555761455561451c565b60405290565b604051601f8201601f191681016001600160401b03811182821017156145835761458361451c565b604052919050565b60006001600160401b038211156145a4576145a461451c565b50601f01601f191660200190565b600082601f8301126145c357600080fd5b81356145d66145d18261458b565b61455b565b8181528460208386010111156145eb57600080fd5b816020850160208301376000918101602001919091529392505050565b600060a0828403121561461a57600080fd5b50919050565b600060c0828403121561461a57600080fd5b60006001600160401b0382111561464b5761464b61451c565b5060051b60200190565b600082601f83011261466657600080fd5b813560206146766145d183614632565b82815260059290921b8401810191818101908684111561469557600080fd5b8286015b848110156146d45780356001600160401b038111156146b85760008081fd5b6146c68986838b01016145b2565b845250918301918301614699565b509695505050505050565b60008060008061012085870312156146f657600080fd5b84356001600160401b038082111561470d57600080fd5b614719888389016145b2565b9550602087013591508082111561472f57600080fd5b61473b88838901614608565b945061474a8860408901614620565b935061010087013591508082111561476157600080fd5b5061476e87828801614655565b91505092959194509250565b6000806000610100848603121561479057600080fd5b83356001600160401b03808211156147a757600080fd5b6147b387838801614608565b94506147c28760208801614620565b935060e08601359150808211156147d857600080fd5b506147e586828701614655565b9150509250925092565b6000602080838503121561480257600080fd5b82356001600160401b0381111561481857600080fd5b8301601f8101851361482957600080fd5b80356148376145d182614632565b81815260059190911b8201830190838101908783111561485657600080fd5b928401925b828410156144685761486c846144ac565b8252928401929084019061485b565b600060e0828403121561461a57600080fd5b60008061010083850312156148a157600080fd5b82356001600160401b038111156148b757600080fd5b6148c385828601614608565b9250506148d3846020850161487b565b90509250929050565b6000602082840312156148ee57600080fd5b613c06826144ac565b60006020828403121561490957600080fd5b5035919050565b6000610100828403121561461a57600080fd5b60006020828403121561493557600080fd5b81356001600160401b0381111561494b57600080fd5b6142d684828501614910565b6000806040838503121561496a57600080fd5b614973836144ac565b946020939093013593505050565b60008083601f84011261499357600080fd5b5081356001600160401b038111156149aa57600080fd5b6020830191508360208260051b850101111561431c57600080fd5b60008060008060008060006080888a0312156149e057600080fd5b87356001600160401b03808211156149f757600080fd5b614a038b838c016145b2565b985060208a0135915080821115614a1957600080fd5b614a258b838c01614981565b909850965060408a0135915080821115614a3e57600080fd5b614a4a8b838c01614981565b909650945060608a0135915080821115614a6357600080fd5b50614a708a828b01614981565b989b979a50959850939692959293505050565b6000806000806000806000806080898b031215614a9f57600080fd5b88356001600160401b0380821115614ab657600080fd5b818b0191508b601f830112614aca57600080fd5b813581811115614ad957600080fd5b8c6020828501011115614aeb57600080fd5b60209283019a509850908a01359080821115614b0657600080fd5b614b128c838d01614981565b909850965060408b0135915080821115614b2b57600080fd5b614b378c838d01614981565b909650945060608b0135915080821115614b5057600080fd5b50614b5d8b828c01614981565b999c989b5096995094979396929594505050565b600060e08284031215614b8357600080fd5b613c06838361487b565b60008060208385031215614ba057600080fd5b82356001600160401b0380821115614bb757600080fd5b818501915085601f830112614bcb57600080fd5b813581811115614bda57600080fd5b8660208260061b8501011115614bef57600080fd5b60209290920196919550909350505050565b60008060408385031215614c1457600080fd5b82356001600160401b0380821115614c2b57600080fd5b614c3786838701614608565b93506020850135915080821115614c4d57600080fd5b50614c5a85828601614910565b9150509250929050565b600060208284031215614c7657600080fd5b81356001600160401b03811115614c8c57600080fd5b6142d684828501614608565b600060208284031215614caa57600080fd5b81356001600160401b03811115614cc057600080fd5b6142d6848285016145b2565b60008060008060408587031215614ce257600080fd5b84356001600160401b0380821115614cf957600080fd5b614d0588838901614981565b90965094506020870135915080821115614d1e57600080fd5b50614d2b87828801614981565b95989497509550505050565b60005b83811015614d52578181015183820152602001614d3a565b50506000910152565b60008151808452614d73816020860160208601614d37565b601f01601f19169290920160200192915050565b60c081526000614d9a60c0830189614d5b565b6001600160a01b0397881660208401526001600160401b0396871660408401526060830195909552509190941660808201529290911660a090920191909152919050565b600080600080600080600080600080600060c08c8e031215614dff57600080fd5b8b359a506001600160401b038060208e01351115614e1c57600080fd5b614e2c8e60208f01358f01614981565b909b50995060408d0135811015614e4257600080fd5b614e528e60408f01358f01614981565b909950975060608d0135811015614e6857600080fd5b614e788e60608f01358f01614981565b909750955060808d0135811015614e8e57600080fd5b614e9e8e60808f01358f01614981565b909550935060a08d0135811015614eb457600080fd5b50614ec58d60a08e01358e01614981565b81935080925050509295989b509295989b9093969950565b600060c08284031215614eef57600080fd5b60405160c081018181106001600160401b0382111715614f1157614f1161451c565b604052905080614f20836144ac565b8152614f2e602084016144ac565b60208201526040830135604082015260608301356060820152614f53608084016144ac565b608082015260a083013560a08201525092915050565b60008060e08385031215614f7c57600080fd5b614f868484614edd565b915060c08301356001600160401b03811115614fa157600080fd5b614c5a85828601614655565b60008060208385031215614fc057600080fd5b82356001600160401b03811115614fd657600080fd5b614fe285828601614981565b90969095509350505050565b80356001600160401b03811681146144c357600080fd5b6000806040838503121561501857600080fd5b615021836144ac565b91506148d360208401614fee565b634e487b7160e01b600052601160045260246000fd5b818103818111156119925761199261502f565b600060c0828403121561506a57600080fd5b613c068383614edd565b602081526000613c066020830184614d5b565b60006020828403121561509957600080fd5b81516001600160401b038111156150af57600080fd5b8201601f810184136150c057600080fd5b80516150ce6145d18261458b565b8181528560208385010111156150e357600080fd5b6150f4826020830160208601614d37565b95945050505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016151255761512561502f565b5060010190565b808201808211156119925761199261502f565b60008160005b84811015615174576001600160a01b0361515e836144ac565b1686526020958601959190910190600101615145565b5093949350505050565b60006001600160fb1b0383111561519457600080fd5b8260051b80838637939093019392505050565b60006151be6151b783878961513f565b848661517e565b9695505050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8183526000602080850194508260005b8581101561522d576001600160a01b0361521a836144ac565b1687529582019590820190600101615201565b509495945050505050565b81835260006001600160fb1b0383111561525157600080fd5b8260051b80836020870137939093016020019392505050565b60808152600061527e608083018a8c6151c8565b602083820381850152818983528183019050818a60051b8401018b60005b8c81101561530b57858303601f190184528135368f9003601e190181126152c257600080fd5b8e0185810190356001600160401b038111156152dd57600080fd5b8036038213156152ec57600080fd5b6152f78582846151c8565b95870195945050509084019060010161529c565b50508581036040870152615320818a8c6151f1565b93505050508281036060840152615338818587615238565b9b9a5050505050505050505050565b838152818360208301376000910160200190815292915050565b600181811c9082168061537557607f821691505b60208210810361461a57634e487b7160e01b600052602260045260246000fd5b60006001600160401b038083168181036153b1576153b161502f565b6001019392505050565b86815285602082015260006153d76151b760408401878961513f565b98975050505050505050565b6000602082840312156153f557600080fd5b5051919050565b6000808335601e1984360301811261541357600080fd5b8301803591506001600160401b0382111561542d57600080fd5b60200191503681900382131561431c57600080fd5b8183823760009101908152919050565b803563ffffffff811681146144c357600080fd5b600060e0828403121561547857600080fd5b60405160e081018181106001600160401b038211171561549a5761549a61451c565b6040526154a6836144ac565b8152602083013560208201526154be604084016144ac565b60408201526154cf60608401614fee565b60608201526154e060808401614fee565b60808201526154f160a08401615452565b60a082015261550260c084016144ac565b60c08201529392505050565b6001600160601b0319606098891b8116825296881b871660148201529490961b9094166028840152603c8301919091526001600160c01b031960c091821b8116605c84015292811b831660648301529290921b16606c82015260740190565b60208082526034908201527f20504c455855533a207472616e73666572496420616c726561647920657869736040820152733a39971021b432b1b5903a3432903737b731b29760611b606082015260800190565b601f821115610f2b57600081815260208120601f850160051c810160208610156155e85750805b601f850160051c820191505b81811015615607578281556001016155f4565b505050505050565b81516001600160401b038111156156285761562861451c565b61563c816156368454615361565b846155c1565b602080601f83116001811461567157600084156156595750858301515b600019600386901b1c1916600185901b178555615607565b600085815260208120601f198616915b828110156156a057888601518255948401946001909101908401615681565b50858210156156be5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b0388811682526001600160401b03881660208301528681166040830152851660608201526080810184905260a0810183905260e060c0820181905260009061571f90830184614d5b565b9998505050505050505050565b6000610100823603121561573f57600080fd5b615747614532565b615750836144ac565b815261575e60208401614fee565b602082015260408301356001600160401b0381111561577c57600080fd5b615788368286016145b2565b604083015250606083013560608201526080830135608082015260a083013560a08201526157b860c08401614fee565b60c08201526157c960e084016144ac565b60e082015292915050565b6001600160a01b03871681526001600160401b038616602082015260c06040820181905260009061580790830187614d5b565b606083019590955250608081019290925260a0909101529392505050565b60006bffffffffffffffffffffffff19808a60601b1683528851615850816014860160208d01614d37565b606098891b9091166014939091019283015250602881019490945260c092831b6001600160c01b0319908116604886015291831b8216605085015290911b1660588201520192915050565b60208082526023908201527f7369676e65727320616e6420706f77657273206c656e677468206e6f74206d616040820152620e8c6d60eb1b606082015260800190565b80820281158282048414176119925761199261502f565b60008261591257634e487b7160e01b600052601260045260246000fd5b500490565b803561ffff811681146144c357600080fd5b6000610100823603121561593c57600080fd5b615944614532565b61594d836144ac565b81526020830135602082015261596560408401615917565b6040820152615976606084016144ac565b606082015261598760808401615452565b608082015260a083013560a082015260c08301356001600160401b038111156159af57600080fd5b6159bb368286016145b2565b60c0830152506157c960e084016144ac565b60018060a01b038716815285602082015261ffff8516604082015283606082015263ffffffff8316608082015260c060a082015260006153d760c0830184614d5b565b61ffff8516815283602082015263ffffffff831660408201526080606082015260006151be6080830184614d5b565b600060208284031215615a5157600080fd5b81518015158114613c0657600080fd5b600060208284031215615a7357600080fd5b613c0682614fee565b604081526000615a906040830186886151f1565b8281036020840152614468818587615238565b634e487b7160e01b600052602160045260246000fd5b60008251615acb818460208701614d37565b919091019291505056feba46c7ec9a8551ced55787e1e5883df75add3284e2e55e9bdacfed24483c2809a26469706673582212202f18e336d943a607731e17a0acca58c806f5095f0ae043163f09ad6f2956f77264736f6c634300081100330000000000000000000000001111111254eeb25477b68fb85ed929f73a9605820000000000000000000000005427fefa711eff984124bfbb1ab6fbf5e3da182000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ee18b2214aff97000d974cf647e7c347e8fa585
Deployed Bytecode
0x6080604052600436106102555760003560e01c80637b25503a11610139578063c93341ec116100b6578063da4cf3a21161007a578063da4cf3a2146106e9578063def79ab5146106fc578063e2d7ddbb1461071c578063eda82b4b1461073c578063f20c922a1461074f578063f2fde38b1461076f57600080fd5b8063c93341ec1461063d578063cc818ad11461065d578063cebaf8a91461067d578063d0790da91461069d578063d1f906d1146106b357600080fd5b8063a3142fae116100fd578063a3142fae1461057a578063a7bb58031461058d578063a7bdf45a146105cb578063acf64c43146105eb578063ba2cb25c1461061d57600080fd5b80637b25503a146104f35780637ce3489b146105135780638da5cb5b146105335780639b14d4c6146105515780639f37a0cb1461056757600080fd5b8063370fb47b116101d2578063682dbc2211610196578063682dbc221461046557806369773796146104855780636e65796614610498578063715018a6146104ab5780637a79a608146104c05780637ae86aca146104e057600080fd5b8063370fb47b146103c85780633c64f04b146103ec5780634d178cad1461041c5780635fafa99d1461042f57806365a114f11461044f57600080fd5b806325c38b9f1161021957806325c38b9f1461032057806329f8de45146103355780632e11f5c41461035557806330ca07d51461036857806332fe7b26146103a857600080fd5b80630be34ad1146102615780630ff754ea14610283578063129017f2146102c0578063223796f7146102e057806322ee82db1461030057600080fd5b3661025c57005b600080fd5b34801561026d57600080fd5b5061028161027c3660046144c8565b61078f565b005b34801561028f57600080fd5b506009546102a3906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102cc57600080fd5b506102816102db3660046146df565b61080b565b3480156102ec57600080fd5b506102816102fb36600461477a565b610b2e565b34801561030c57600080fd5b5061028161031b3660046147ef565b610d94565b34801561032c57600080fd5b50610281610e0d565b34801561034157600080fd5b506008546102a3906001600160a01b031681565b61028161036336600461488d565b610e5c565b34801561037457600080fd5b506103986103833660046148dc565b60106020526000908152604090205460ff1681565b60405190151581526020016102b7565b3480156103b457600080fd5b506006546102a3906001600160a01b031681565b3480156103d457600080fd5b506103de60025481565b6040519081526020016102b7565b3480156103f857600080fd5b506103986104073660046148f7565b600e6020526000908152604090205460ff1681565b61028161042a366004614923565b610e98565b34801561043b57600080fd5b5061028161044a366004614957565b610ee9565b34801561045b57600080fd5b506103de60035481565b34801561047157600080fd5b506102816104803660046149c5565b610f4b565b610281610493366004614923565b610ff2565b6102816104a636600461488d565b611031565b3480156104b757600080fd5b50610281611097565b3480156104cc57600080fd5b506102816104db366004614a83565b6110ab565b6102816104ee366004614b71565b611367565b3480156104ff57600080fd5b5061028161050e366004614b8d565b6113a6565b34801561051f57600080fd5b5061028161052e3660046148f7565b611491565b34801561053f57600080fd5b506000546001600160a01b03166102a3565b34801561055d57600080fd5b506103de60045481565b610281610575366004614c01565b6114c2565b610281610588366004614c64565b6114ee565b34801561059957600080fd5b506105ad6105a8366004614c98565b61150b565b60408051938452602084019290925260ff16908201526060016102b7565b3480156105d757600080fd5b506102816105e6366004614ccc565b61157f565b3480156105f757600080fd5b5061060b6106063660046148f7565b6115e1565b6040516102b796959493929190614d87565b34801561062957600080fd5b50610281610638366004614dde565b6116b8565b34801561064957600080fd5b50610398610658366004614f69565b6117f9565b34801561066957600080fd5b50610281610678366004614fad565b611998565b34801561068957600080fd5b5061060b610698366004615005565b611a69565b3480156106a957600080fd5b506103de60015481565b3480156106bf57600080fd5b506102a36106ce3660046148dc565b600f602052600090815260409020546001600160a01b031681565b6102816106f7366004614b71565b611a8f565b34801561070857600080fd5b506102a36107173660046148f7565b611ace565b34801561072857600080fd5b506007546102a3906001600160a01b031681565b61028161074a366004614c01565b611af8565b34801561075b57600080fd5b5061028161076a3660046148f7565b611b24565b34801561077b57600080fd5b5061028161078a3660046148dc565b611b8e565b600a546001600160a01b03163314806107b257506000546001600160a01b031633145b6107bb57600080fd5b600680546001600160a01b039586166001600160a01b0319918216179091556007805494861694821694909417909355600880549285169284169290921790915560098054919093169116179055565b610813611c07565b82600061082e61082960408401602085016148dc565b611c61565b1590508361083f60208401846148dc565b6001600160a01b031661085860a08301608084016148dc565b6001600160a01b031614801561088457508260600135816060013582604001356108829190615045565b145b80156108bf575061089b60608401604085016148dc565b6001600160a01b03166108b460408301602084016148dc565b6001600160a01b0316145b6108c857600080fd5b6108e06108da36839003830183615058565b856117f9565b5060a08101356000908152600e602052604090205460ff161561090257600080fd5b600061091660608301356040840135615045565b90508215610a0a5760095460405163c3f511c160e01b81526001600160a01b039091169063c3f511c19061094e908b90600401615074565b6000604051808303816000875af115801561096d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109959190810190615087565b506006546109c4906001600160a01b0316826109b460208601866148dc565b6001600160a01b03169190611c83565b606082013515610a0557610a056109e36000546001600160a01b031690565b60608401356109f560208601866148dc565b6001600160a01b03169190611dcb565b610aab565b6009546040516307211d7960e21b81526001600160a01b0390911690631c8475e490610a3a908b90600401615074565b6000604051808303816000875af1158015610a59573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a819190810190615087565b50606082013515610aab57610aab610aa16000546001600160a01b031690565b8360600135611dfb565b6000610ab685611e97565b90507fdef08483254d44ac41909d1188fb7c523c398e22edeab0e1d9c941a98629b5d3610ae960a08501608086016148dc565b610af960408601602087016148dc565b604080516001600160a01b039384168152929091166020830152810183905260600160405180910390a1505050505050505050565b610b36611c07565b8282610b4560208301836148dc565b6001600160a01b0316610b5e60a08301608084016148dc565b6001600160a01b0316148015610b8a5750816060013581606001358260400135610b889190615045565b145b8015610bc55750610ba160608301604084016148dc565b6001600160a01b0316610bba60408301602084016148dc565b6001600160a01b0316145b610bce57600080fd5b610be6610be036839003830183615058565b846117f9565b5060a08101356000908152600e602052604090205460ff1615610c465760405162461bcd60e51b8152602060048201526013602482015272736166655472616e736665722065786973747360681b60448201526064015b60405180910390fd5b60a08101356000908152600e602090815260408220805460ff19166001179055610c7690610829908401846148dc565b1590506000610c8d60608401356040850135615045565b90508115610ce957600654610cb3906001600160a01b0316826109b460208701876148dc565b606083013515610ce457610ce4610cd26000546001600160a01b031690565b60608501356109f560208701876148dc565b610d12565b606083013515610d1257610d12610d086000546001600160a01b031690565b8460600135611dfb565b6000610d1d85611e97565b90507fdef08483254d44ac41909d1188fb7c523c398e22edeab0e1d9c941a98629b5d3610d5060a08601608087016148dc565b610d6060408701602088016148dc565b604080516001600160a01b039384168152929091166020830152810183905260600160405180910390a15050505050505050565b610d9c611c07565b60005b8151811015610e09576005828281518110610dbc57610dbc6150fd565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b0390921691909117905580610e0181615113565b915050610d9f565b5050565b610e15611c07565b600454610e22904261512c565b60038190556040519081527f68e825132f7d4bc837dea2d64ac9fc19912bf0224b67f9317d8f1a917f5304a19060200160405180910390a1565b81610e7a610e7060408301602084016148dc565b8260600135612032565b506000610e8682612075565b9050610e928184612148565b50505050565b6000610eaa61082960208401846148dc565b1590508015610edb57610edb33306060850135610eca60208701876148dc565b6001600160a01b03169291906125ab565b610e098260600135836125e3565b610ef1611c07565b6000610efc83611c61565b1590508015610f3057610f2b610f1a6000546001600160a01b031690565b6001600160a01b0385169084611dcb565b505050565b610f2b610f456000546001600160a01b031690565b83611dfb565b600084848484604051602001610f6494939291906151a7565b604051602081830303815290604052805190602001209050610fe8610fdd89805190602001206040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b8888888888886129ec565b5050505050505050565b600061100461082960208401846148dc565b159050801561102357611023333060208501803590610eca90876148dc565b610e09826020013583612ccd565b81611045610e7060408301602084016148dc565b50600061105182612075565b90506010600061106760c0860160a087016148dc565b6001600160a01b0316815260208101919091526040016000205460ff1661108d57600080fd5b610e92818461313f565b61109f611c07565b6110a96000613716565b565b600754604051630144352560e71b81526001600160a01b039091169063a21a9280906110e9908b908b908b908b908b908b908b908b9060040161526a565b600060405180830381600087803b15801561110357600080fd5b505af1158015611117573d6000803e3d6000fd5b505060075460405160009350611166925046916001600160a01b03169060200191825260601b6001600160601b03191660208201526a57697468647261774d736760a81b6034820152603f0190565b6040516020818303038152906040528051906020012090506111b0818a8a60405160200161119693929190615347565b604051602081830303815290604052888888888888610f4b565b60006111f18a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061376692505050565b90506000600d60008360a0015181526020019081526020016000206040518060c001604052908160008201805461122790615361565b80601f016020809104026020016040519081016040528092919081815260200182805461125390615361565b80156112a05780601f10611275576101008083540402835291602001916112a0565b820191906000526020600020905b81548152906001019060200180831161128357829003601f168201915b505050918352505060018201546001600160a01b038082166020808501919091526001600160401b03600160a01b938490048116604086015260028601546060860152600390950154918216608085015291900490921660a09091015281015190915060009061130f90611c61565b1590508015611347576113428260800151836060015184602001516001600160a01b0316611dcb9092919063ffffffff16565b611359565b61135982608001518360600151611dfb565b505050505050505050505050565b600061137961082960208401846148dc565b159050801561139857611398333060208501803590610eca90876148dc565b610e0982602001358361313f565b600a546001600160a01b03163314806113c957506000546001600160a01b031633145b6113d257600080fd5b60005b6001600160401b038116821115610f2b578282826001600160401b0316818110611401576114016150fd565b905060400201602001602081019061141991906148dc565b600f60008585856001600160401b0316818110611438576114386150fd565b61144e92602060409092020190810191506148dc565b6001600160a01b039081168252602082019290925260400160002080546001600160a01b031916929091169190911790558061148981615395565b9150506113d5565b600a546001600160a01b03163314806114b457506000546001600160a01b031633145b6114bd57600080fd5b600b55565b816114d6610e7060408301602084016148dc565b5060006114e282612075565b9050610e9281846125e3565b611501610e7060408301602084016148dc565b50610e0981611e97565b600080600083516041146115615760405162461bcd60e51b815260206004820152601860248201527f696e76616c6964207369676e6174757265206c656e67746800000000000000006044820152606401610c3d565b50505060208101516040820151606090920151909260009190911a90565b611587611c07565b60035442116115cf5760405162461bcd60e51b81526020600482015260146024820152736e6f742072656163682072657365742074696d6560601b6044820152606401610c3d565b600019600355610e92848484846138be565b600d602052600090815260409020805481906115fc90615361565b80601f016020809104026020016040519081016040528092919081815260200182805461162890615361565b80156116755780601f1061164a57610100808354040283529160200191611675565b820191906000526020600020905b81548152906001019060200180831161165857829003601f168201915b5050506001840154600285015460039095015493946001600160a01b03808316956001600160401b03600160a01b94859004811696509294509081169290041686565b6002548b116117095760405162461bcd60e51b815260206004820152601e60248201527f547269676765722074696d65206973206e6f7420696e6372656173696e6700006044820152606401610c3d565b61171542610e1061512c565b8b106117635760405162461bcd60e51b815260206004820152601960248201527f547269676765722074696d6520697320746f6f206c61726765000000000000006044820152606401610c3d565b600046306040516020016117a492919091825260601b6001600160601b03191660208201526c5570646174655369676e65727360981b603482015260410190565b6040516020818303038152906040528051906020012090506117da818d8d8d8d8d604051602001611196969594939291906153bb565b6117e68b8b8b8b6138be565b5050506002989098555050505050505050565b60008083815b845181101561194a5760006118b37f23708f9a7a9c68b1a6cd4e9244f4b17e38b50b4448142b6ba580ab9052fe7d1e846000015185602001518660400151876060015188608001518960a0015160405160200161189897969594939291909687526001600160a01b03958616602088015293851660408701526060860192909252608085015290911660a083015260c082015260e00190565b60405160208183030381529060405280519060200120613a1d565b905060008060006118dc8986815181106118cf576118cf6150fd565b602002602001015161150b565b92509250925060006118f085838686613a6b565b905060058681548110611905576119056150fd565b6000918252602090912001546001600160a01b0390811690821603611932578761192e81615113565b9850505b5050505050808061194290615113565b9150506117ff565b508351820361195e57600192505050611992565b60405162461bcd60e51b81526020600482015260096024820152680dcdee840dac2e8c6d60bb1b6044820152606401610c3d565b92915050565b600a546001600160a01b03163314806119bb57506000546001600160a01b031633145b6119c457600080fd5b8060005b81811015610e925760008484838181106119e4576119e46150fd565b90506020020160208101906119f991906148dc565b6001600160a01b031603611a0c57600080fd5b600160106000868685818110611a2457611a246150fd565b9050602002016020810190611a3991906148dc565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790556001016119c8565b600c6020908152600092835260408084209091529082529020805481906115fc90615361565b6000611aa161082960208401846148dc565b1590508015611ac057611ac0333060208501803590610eca90876148dc565b610e09826020013583612148565b60058181548110611ade57600080fd5b6000918252602090912001546001600160a01b0316905081565b81611b0c610e7060408301602084016148dc565b506000611b1882612075565b9050610e928184612ccd565b611b2c611c07565b6004548111611b895760405162461bcd60e51b815260206004820152602360248201527f6e6f7469636520706572696f642063616e206f6e6c7920626520696e637265616044820152621cd95960ea1b6064820152608401610c3d565b600455565b611b96611c07565b6001600160a01b038116611bfb5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c3d565b611c0481613716565b50565b6000546001600160a01b031633146110a95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c3d565b6001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1490565b801580611cfd5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611cd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cfb91906153e3565b155b611d685760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610c3d565b6040516001600160a01b038316602482015260448101829052610f2b90849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613a93565b6040516001600160a01b038316602482015260448101829052610f2b90849063a9059cbb60e01b90606401611d94565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611e48576040519150601f19603f3d011682016040523d82523d6000602084013e611e4d565b606091505b5050905080610f2b5760405162461bcd60e51b815260206004820152601660248201527514d85999481cd85999551c985b9cd9995c8819985a5b60521b6044820152606401610c3d565b60008181611eae61082960408401602085016148dc565b90506000611ed7611ec260208501856148dc565b611ed260608601604087016148dc565b613b65565b6006549091506000906001600160a01b031683611ef5576000611efb565b84606001355b611f0860808701876153fc565b604051611f16929190615442565b60006040518083038185875af1925050503d8060008114611f53576040519150601f19603f3d011682016040523d82523d6000602084013e611f58565b606091505b50509050801561025c576000611f84611f7460208701876148dc565b611ed260608801604089016148dc565b9050828111611f935780611f9d565b611f9d8382615045565b95507fcd3829a3813dc3cdd188fd3d01dcf3268c16be2fdd2dd21d0665418816e46062611fcd60208701876148dc565b611fdd60408801602089016148dc565b611fed6060890160408a016148dc565b604080516001600160a01b0394851681529284166020840152921681830152606088810135908201526080810189905290519081900360a00190a15050505050919050565b600061203d83611c61565b15905080156119925761205b6001600160a01b0384163330856125ab565b600654611992906001600160a01b03858116911684611c83565b6000818161208c61082960408401602085016148dc565b905060006120a86120a360608501604086016148dc565b613c0d565b6006549091506000906001600160a01b0316836120c65760006120cc565b84606001355b6120d960808701876153fc565b6040516120e7929190615442565b60006040518083038185875af1925050503d8060008114612124576040519150601f19603f3d011682016040523d82523d6000602084013e612129565b606091505b50509050801561025c576000611f846120a360608701604088016148dc565b600061215936839003830183615466565b9050612169816000015184613ca7565b9250600061217a8260000151611c61565b159050801561224b57600754825161219f916001600160a01b03918216911686611c83565b60075460408381015184516060860151608087015160a0880151945163a5977fbb60e01b81526001600160a01b0394851660048201529284166024840152604483018a90526001600160401b03918216606484015216608482015263ffffffff90921660a48301529091169063a5977fbb9060c401600060405180830381600087803b15801561222e57600080fd5b505af1158015612242573d6000803e3d6000fd5b50505050612303565b6007546040838101516060850151608086015160a08701519351633f2e5fc360e01b81526001600160a01b039384166004820152602481018a90526001600160401b0392831660448201529116606482015263ffffffff909216608483015290911690633f2e5fc390869060a4016000604051808303818588803b1580156122d257600080fd5b505af11580156122e6573d6000803e3d6000fd5b505073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc285525050505b60003083604001518460000151878660600151876080015146604051602001612332979695949392919061550e565b6040516020818303038152906040528051906020012090506000600d60008381526020019081526020016000206040518060c001604052908160008201805461237a90615361565b80601f01602080910402602001604051908101604052809291908181526020018280546123a690615361565b80156123f35780601f106123c8576101008083540402835291602001916123f3565b820191906000526020600020905b8154815290600101906020018083116123d657829003601f168201915b505050918352505060018201546001600160a01b0380821660208401526001600160401b03600160a01b928390048116604085015260028501546060850152600390940154908116608084015204821660a091820152820151919250161561246d5760405162461bcd60e51b8152600401610c3d9061556d565b83516001600160a01b03166020808301919091526060808601516001600160401b03908116604080860191909152918401899052336080808601919091528701511660a08401528051808201825260078152664342726964676560c81b8184015283526000848152600d9092529020815182919081906124ed908261560f565b506020828101516001830180546040808701516001600160401b03908116600160a01b9081026001600160e01b03199485166001600160a01b039788161717909455606088015160028801556080808901516003909801805460a0909a01519092169094029790921695909316949094179490941790925591830151838201519284015160c088015185519351600080516020615ad68339815191529561259b95909392918d918a916156ce565b60405180910390a1505050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052610e929085906323b872dd60e01b90608401611d94565b60006125ee8261572c565b905060006125ff8260000151611c61565b905061260f826000015185613ca7565b9350806126b7576008548251612632916001600160a01b03918216911686611c83565b60085460808301518351602085015160408087015160a088015191516360de1a9b60e01b81526001600160a01b03909616956360de1a9b95946126809490939092918c9187916004016157d4565b6000604051808303818588803b15801561269957600080fd5b505af11580156126ad573d6000803e3d6000fd5b5050505050612752565b600080835260808301516126cc90869061512c565b60085484516020860151604080880151608089015160a08a015192516360de1a9b60e01b81529697506001600160a01b03909516956360de1a9b95889561271e9590949093928e9291906004016157d4565b6000604051808303818588803b15801561273757600080fd5b505af115801561274b573d6000803e3d6000fd5b5050505050505b600030836040015184600001518786602001518760c00151466040516020016127819796959493929190615825565b6040516020818303038152906040528051906020012090506000600d60008381526020019081526020016000206040518060c00160405290816000820180546127c990615361565b80601f01602080910402602001604051908101604052809291908181526020018280546127f590615361565b80156128425780601f1061281757610100808354040283529160200191612842565b820191906000526020600020905b81548152906001019060200180831161282557829003601f168201915b505050918352505060018201546001600160a01b0380821660208401526001600160401b03600160a01b928390048116604085015260028501546060850152600390940154908116608084015204821660a09182015282015191925016156128bc5760405162461bcd60e51b8152600401610c3d9061556d565b83516001600160a01b0316602080830191909152808501516001600160401b039081166040808501919091526060840189905233608085015260c087015190911660a084015280518082018252600a815269506f6c7942726964676560b01b8184015283526000848152600d90925290208151829190819061293e908261560f565b506020828101516001830180546040808701516001600160401b03908116600160a01b9081026001600160e01b03199485166001600160a01b039788161717909455606088015160028801556080808901516003909801805460a0909a01519092169094029790921695909316949094179490941790925591830151838201519284015160e088015185519351600080516020615ad68339815191529561259b95909392918d918a916156ce565b828114612a0b5760405162461bcd60e51b8152600401610c3d9061589b565b6000805b84811015612a4f57838382818110612a2957612a296150fd565b9050602002013582612a3b919061512c565b915080612a4781615113565b915050612a0f565b5060006003612a5f8360026158de565b612a6991906158f5565b612a7490600161512c565b905060008080805b8a811015612c86576000612aff8d8d84818110612a9b57612a9b6150fd565b9050602002810190612aad91906153fc565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508f613d3390919063ffffffff16565b9050836001600160a01b0316816001600160a01b031611612b625760405162461bcd60e51b815260206004820152601e60248201527f7369676e657273206e6f7420696e20617363656e64696e67206f7264657200006044820152606401610c3d565b8093505b8a8a84818110612b7857612b786150fd565b9050602002016020810190612b8d91906148dc565b6001600160a01b0316816001600160a01b03161115612bfa57612bb160018461512c565b9250898310612bf55760405162461bcd60e51b815260206004820152601060248201526f1cda59db995c881b9bdd08199bdd5b9960821b6044820152606401610c3d565b612b66565b8a8a84818110612c0c57612c0c6150fd565b9050602002016020810190612c2191906148dc565b6001600160a01b0316816001600160a01b031603612c6057888884818110612c4b57612c4b6150fd565b9050602002013585612c5d919061512c565b94505b858510612c735750505050505050612cc4565b5080612c7e81615113565b915050612a7c565b5060405162461bcd60e51b81526020600482015260126024820152711c5d5bdc9d5b481b9bdd081c995858da195960721b6044820152606401610c3d565b50505050505050565b6000612cd882615929565b9050612ce8816000015184613ca7565b92506000612cf98260000151611c61565b6060830151901591506001600160a01b03168115612dc9576009548351612d2e916001600160a01b0391821691166000611c83565b6009548351612d4a916001600160a01b03918216911687611c83565b6009548351604080860151608087015160c088015192516362d2f5ed60e11b81526001600160a01b039095169463c5a5ebda94612d929490938c9390928992906004016159cd565b600060405180830381600087803b158015612dac57600080fd5b505af1158015612dc0573d6000803e3d6000fd5b50505050612e40565b600954604080850151608086015160c08701519251632fba737f60e21b81526001600160a01b039094169363bee9cdfc938a93612e0d939092889290600401615a10565b6000604051808303818588803b158015612e2657600080fd5b505af1158015612e3a573d6000803e3d6000fd5b50505050505b60608381015184516040808701516080880151915130861b6001600160601b0319908116602083015294861b851660348201529290941b9092166048820152605c810188905260f09290921b6001600160f01b031916607c83015260e01b6001600160e01b031916607e8201524660c01b6001600160c01b0319166082820152600090608a016040516020818303038152906040528051906020012090506000600d60008381526020019081526020016000206040518060c0016040529081600082018054612f0e90615361565b80601f0160208091040260200160405190810160405280929190818152602001828054612f3a90615361565b8015612f875780601f10612f5c57610100808354040283529160200191612f87565b820191906000526020600020905b815481529060010190602001808311612f6a57829003601f168201915b505050918352505060018201546001600160a01b0380821660208401526001600160401b03600160a01b928390048116604085015260028501546060850152600390940154908116608084015204821660a09182015282015191925016156130015760405162461bcd60e51b8152600401610c3d9061556d565b84516001600160a01b031660208083019190915260408087015161ffff1681840152606083018990523360808085019190915287015163ffffffff1660a084015280518082018252600c81526b506f7274616c42726964676560a01b8184015283526000848152600d909252902081518291908190613080908261560f565b506020828101516001830180546040808701516001600160401b03908116600160a01b9081026001600160e01b03199485166001600160a01b039788161717909455606088015160028801556080808901516003909801805460a0909a01519092169094029790921695909316949094179490941790925591830151838201519284015160e089015185519351600080516020615ad68339815191529561312e95909392918e918a916156ce565b60405180910390a150505050505050565b6000600f8161315160208501856148dc565b6001600160a01b03908116825260208083019390935260409091016000205416915061318990613183908401846148dc565b84613ca7565b92506001600160a01b0381166131a560c0840160a085016148dc565b6001600160a01b031603613249576001600160a01b03811663628d6cba846131d360608601604087016148dc565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af115801561321f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132439190615a3f565b50613407565b61325961082960208401846148dc565b156133135761326e60c0830160a084016148dc565b6001600160a01b031663a5e56571848361328e60608701604088016148dc565b61329e6080880160608901615a61565b6040516001600160e01b031960e087901b1681526001600160a01b0393841660048201529290911660248301526001600160401b031660448201526064016000604051808303818588803b1580156132f557600080fd5b505af1158015613309573d6000803e3d6000fd5b5050505050613407565b61333461332660c0840160a085016148dc565b846109b460208601866148dc565b61334460c0830160a084016148dc565b6001600160a01b039081169063edbdf5e290831661336e5761336960208501856148dc565b613370565b825b61338060608601604087016148dc565b866133916080880160608901615a61565b6040516001600160e01b031960e087901b1681526001600160a01b03948516600482015293909216602484015260448301526001600160401b03166064820152608401600060405180830381600087803b1580156133ee57600080fd5b505af1158015613402573d6000803e3d6000fd5b505050505b60003061341a60608501604086016148dc565b61342760208601866148dc565b866134386080880160608901615a61565b61344860a0890160808a01615a61565b4660405160200161345f979695949392919061550e565b6040516020818303038152906040528051906020012090506000600d60008381526020019081526020016000206040518060c00160405290816000820180546134a790615361565b80601f01602080910402602001604051908101604052809291908181526020018280546134d390615361565b80156135205780601f106134f557610100808354040283529160200191613520565b820191906000526020600020905b81548152906001019060200180831161350357829003601f168201915b505050918352505060018201546001600160a01b0380821660208401526001600160401b03600160a01b928390048116604085015260028501546060850152600390940154908116608084015204821660a091820152820151919250161561359a5760405162461bcd60e51b8152600401610c3d9061556d565b6135a760208501856148dc565b6001600160a01b031660208201526135c56080850160608601615a61565b6001600160401b0316604082015260608101859052336080808301919091526135f49060a08601908601615a61565b6001600160401b031660a0820152604080518082018252601081526f4d756c7469436861696e42726964676560801b6020808301919091529083526000848152600d909152208151829190819061364b908261560f565b506020828101516001830180546040808701516001600160401b03908116600160a01b9081026001600160e01b03199485166001600160a01b039788161717909455606088015160028801556080808901516003909801805460a0909a015190921690940297909216959093169490941794909417909255918301519083015191830151600080516020615ad683398151915292906136f060e0890160c08a016148dc565b855160405161370795949392918c918a91906156ce565b60405180910390a15050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040805160c08101825260008082526020808301829052828401829052606083018290526080830182905260a0830182905283518085019094528184528301849052909190805b602083015151835110156138b6576137c483613d57565b9092509050816001036137ea576137da83613d91565b6001600160401b031684526137ad565b8160020361380e576137fb83613d91565b6001600160401b031660208501526137ad565b8160030361383a5761382761382284613e0c565b613ec8565b6001600160a01b031660408501526137ad565b816004036138615761384e61382284613e0c565b6001600160a01b031660608501526137ad565b816005036138845761387a61387584613e0c565b613ed3565b60808501526137ad565b816006036138a75761389d61389884613e0c565b613f0a565b60a08501526137ad565b6138b18382613f22565b6137ad565b505050919050565b8281146138dd5760405162461bcd60e51b8152600401610c3d9061589b565b6000805b848110156139b657816001600160a01b0316868683818110613905576139056150fd565b905060200201602081019061391a91906148dc565b6001600160a01b03161161397b5760405162461bcd60e51b815260206004820152602260248201527f4e6577207369676e657273206e6f7420696e20617363656e64696e67206f726460448201526132b960f11b6064820152608401610c3d565b85858281811061398d5761398d6150fd565b90506020020160208101906139a291906148dc565b9150806139ae81615113565b9150506138e1565b50848484846040516020016139ce94939291906151a7565b60408051601f198184030181529082905280516020909101206001557ff126123539a68393c55697f617e7d1148e371988daed246c2f41da99965a23f890613707908790879087908790615a7c565b6000611992613a2a613f92565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000613a7c878787876140b9565b91509150613a898161417d565b5095945050505050565b6000613ae8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166142c79092919063ffffffff16565b805190915015610f2b5780806020019051810190613b069190615a3f565b610f2b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610c3d565b60006001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14613bfa576040516370a0823160e01b81526001600160a01b0384811660048301528316906370a0823190602401602060405180830381865afa158015613bd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bf591906153e3565b613c06565b826001600160a01b0316315b9392505050565b60006001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14613ca0576040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015613c77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c9b91906153e3565b611992565b4792915050565b600080612710600b5484613cbb91906158de565b613cc591906158f5565b9050613cd18184615045565b91508015613d2c57613ce284611c61565b613d1157613d0c613cfb6000546001600160a01b031690565b6001600160a01b0386169083611dcb565b613d2c565b613d2c613d266000546001600160a01b031690565b82611dfb565b5092915050565b6000806000613d4285856142de565b91509150613d4f8161417d565b509392505050565b6000806000613d6584613d91565b9050613d726008826158f5565b9250806007166005811115613d8957613d89615aa3565b915050915091565b602080820151825181019091015160009182805b600a81101561025c5783811a9150613dbe8160076158de565b82607f16901b8517945081608016600003613dfa57613dde81600161512c565b86518790613ded90839061512c565b9052509395945050505050565b80613e0481615113565b915050613da5565b60606000613e1983613d91565b90506000818460000151613e2d919061512c565b9050836020015151811115613e4157600080fd5b816001600160401b03811115613e5957613e5961451c565b6040519080825280601f01601f191660200182016040528015613e83576020820181803683370190505b50602080860151865192955091818601919083010160005b85811015613ebd578181015183820152613eb660208261512c565b9050613e9b565b505050935250919050565b600061199282614323565b6000602082511115613ee457600080fd5b6020820151905081516020613ef99190615045565b613f049060086158de565b1c919050565b60008151602014613f1a57600080fd5b506020015190565b6000816005811115613f3657613f36615aa3565b03613f4457610f2b82613d91565b6002816005811115613f5857613f58615aa3565b0361025c576000613f6883613d91565b90508083600001818151613f7c919061512c565b90525060208301515183511115610f2b57600080fd5b6000306001600160a01b037f000000000000000000000000cfa43890eb4108c2ed731b52b2434b53929073e816148015613feb57507f000000000000000000000000000000000000000000000000000000000000000146145b1561401557507f7809af6a26d8c13ca1334c93a638c71f3a3794068d54a732d5e8e8a9f04481a790565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f85a5870097e0caf1c11288cf95e1ac56717f89f3d797d8558ba22e7b50869bba828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156140f05750600090506003614174565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614144573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661416d57600060019250925050614174565b9150600090505b94509492505050565b600081600481111561419157614191615aa3565b036141995750565b60018160048111156141ad576141ad615aa3565b036141fa5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610c3d565b600281600481111561420e5761420e615aa3565b0361425b5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610c3d565b600381600481111561426f5761426f615aa3565b03611c045760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610c3d565b60606142d68484600085614342565b949350505050565b60008082516041036143145760208301516040840151606085015160001a614308878285856140b9565b9450945050505061431c565b506000905060025b9250929050565b6000815160141461433357600080fd5b5060200151600160601b900490565b6060824710156143a35760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610c3d565b6001600160a01b0385163b6143fa5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c3d565b600080866001600160a01b031685876040516144169190615ab9565b60006040518083038185875af1925050503d8060008114614453576040519150601f19603f3d011682016040523d82523d6000602084013e614458565b606091505b5091509150614468828286614473565b979650505050505050565b60608315614482575081613c06565b8251156144925782518084602001fd5b8160405162461bcd60e51b8152600401610c3d9190615074565b80356001600160a01b03811681146144c357600080fd5b919050565b600080600080608085870312156144de57600080fd5b6144e7856144ac565b93506144f5602086016144ac565b9250614503604086016144ac565b9150614511606086016144ac565b905092959194509250565b634e487b7160e01b600052604160045260246000fd5b60405161010081016001600160401b03811182821017156145555761455561451c565b60405290565b604051601f8201601f191681016001600160401b03811182821017156145835761458361451c565b604052919050565b60006001600160401b038211156145a4576145a461451c565b50601f01601f191660200190565b600082601f8301126145c357600080fd5b81356145d66145d18261458b565b61455b565b8181528460208386010111156145eb57600080fd5b816020850160208301376000918101602001919091529392505050565b600060a0828403121561461a57600080fd5b50919050565b600060c0828403121561461a57600080fd5b60006001600160401b0382111561464b5761464b61451c565b5060051b60200190565b600082601f83011261466657600080fd5b813560206146766145d183614632565b82815260059290921b8401810191818101908684111561469557600080fd5b8286015b848110156146d45780356001600160401b038111156146b85760008081fd5b6146c68986838b01016145b2565b845250918301918301614699565b509695505050505050565b60008060008061012085870312156146f657600080fd5b84356001600160401b038082111561470d57600080fd5b614719888389016145b2565b9550602087013591508082111561472f57600080fd5b61473b88838901614608565b945061474a8860408901614620565b935061010087013591508082111561476157600080fd5b5061476e87828801614655565b91505092959194509250565b6000806000610100848603121561479057600080fd5b83356001600160401b03808211156147a757600080fd5b6147b387838801614608565b94506147c28760208801614620565b935060e08601359150808211156147d857600080fd5b506147e586828701614655565b9150509250925092565b6000602080838503121561480257600080fd5b82356001600160401b0381111561481857600080fd5b8301601f8101851361482957600080fd5b80356148376145d182614632565b81815260059190911b8201830190838101908783111561485657600080fd5b928401925b828410156144685761486c846144ac565b8252928401929084019061485b565b600060e0828403121561461a57600080fd5b60008061010083850312156148a157600080fd5b82356001600160401b038111156148b757600080fd5b6148c385828601614608565b9250506148d3846020850161487b565b90509250929050565b6000602082840312156148ee57600080fd5b613c06826144ac565b60006020828403121561490957600080fd5b5035919050565b6000610100828403121561461a57600080fd5b60006020828403121561493557600080fd5b81356001600160401b0381111561494b57600080fd5b6142d684828501614910565b6000806040838503121561496a57600080fd5b614973836144ac565b946020939093013593505050565b60008083601f84011261499357600080fd5b5081356001600160401b038111156149aa57600080fd5b6020830191508360208260051b850101111561431c57600080fd5b60008060008060008060006080888a0312156149e057600080fd5b87356001600160401b03808211156149f757600080fd5b614a038b838c016145b2565b985060208a0135915080821115614a1957600080fd5b614a258b838c01614981565b909850965060408a0135915080821115614a3e57600080fd5b614a4a8b838c01614981565b909650945060608a0135915080821115614a6357600080fd5b50614a708a828b01614981565b989b979a50959850939692959293505050565b6000806000806000806000806080898b031215614a9f57600080fd5b88356001600160401b0380821115614ab657600080fd5b818b0191508b601f830112614aca57600080fd5b813581811115614ad957600080fd5b8c6020828501011115614aeb57600080fd5b60209283019a509850908a01359080821115614b0657600080fd5b614b128c838d01614981565b909850965060408b0135915080821115614b2b57600080fd5b614b378c838d01614981565b909650945060608b0135915080821115614b5057600080fd5b50614b5d8b828c01614981565b999c989b5096995094979396929594505050565b600060e08284031215614b8357600080fd5b613c06838361487b565b60008060208385031215614ba057600080fd5b82356001600160401b0380821115614bb757600080fd5b818501915085601f830112614bcb57600080fd5b813581811115614bda57600080fd5b8660208260061b8501011115614bef57600080fd5b60209290920196919550909350505050565b60008060408385031215614c1457600080fd5b82356001600160401b0380821115614c2b57600080fd5b614c3786838701614608565b93506020850135915080821115614c4d57600080fd5b50614c5a85828601614910565b9150509250929050565b600060208284031215614c7657600080fd5b81356001600160401b03811115614c8c57600080fd5b6142d684828501614608565b600060208284031215614caa57600080fd5b81356001600160401b03811115614cc057600080fd5b6142d6848285016145b2565b60008060008060408587031215614ce257600080fd5b84356001600160401b0380821115614cf957600080fd5b614d0588838901614981565b90965094506020870135915080821115614d1e57600080fd5b50614d2b87828801614981565b95989497509550505050565b60005b83811015614d52578181015183820152602001614d3a565b50506000910152565b60008151808452614d73816020860160208601614d37565b601f01601f19169290920160200192915050565b60c081526000614d9a60c0830189614d5b565b6001600160a01b0397881660208401526001600160401b0396871660408401526060830195909552509190941660808201529290911660a090920191909152919050565b600080600080600080600080600080600060c08c8e031215614dff57600080fd5b8b359a506001600160401b038060208e01351115614e1c57600080fd5b614e2c8e60208f01358f01614981565b909b50995060408d0135811015614e4257600080fd5b614e528e60408f01358f01614981565b909950975060608d0135811015614e6857600080fd5b614e788e60608f01358f01614981565b909750955060808d0135811015614e8e57600080fd5b614e9e8e60808f01358f01614981565b909550935060a08d0135811015614eb457600080fd5b50614ec58d60a08e01358e01614981565b81935080925050509295989b509295989b9093969950565b600060c08284031215614eef57600080fd5b60405160c081018181106001600160401b0382111715614f1157614f1161451c565b604052905080614f20836144ac565b8152614f2e602084016144ac565b60208201526040830135604082015260608301356060820152614f53608084016144ac565b608082015260a083013560a08201525092915050565b60008060e08385031215614f7c57600080fd5b614f868484614edd565b915060c08301356001600160401b03811115614fa157600080fd5b614c5a85828601614655565b60008060208385031215614fc057600080fd5b82356001600160401b03811115614fd657600080fd5b614fe285828601614981565b90969095509350505050565b80356001600160401b03811681146144c357600080fd5b6000806040838503121561501857600080fd5b615021836144ac565b91506148d360208401614fee565b634e487b7160e01b600052601160045260246000fd5b818103818111156119925761199261502f565b600060c0828403121561506a57600080fd5b613c068383614edd565b602081526000613c066020830184614d5b565b60006020828403121561509957600080fd5b81516001600160401b038111156150af57600080fd5b8201601f810184136150c057600080fd5b80516150ce6145d18261458b565b8181528560208385010111156150e357600080fd5b6150f4826020830160208601614d37565b95945050505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016151255761512561502f565b5060010190565b808201808211156119925761199261502f565b60008160005b84811015615174576001600160a01b0361515e836144ac565b1686526020958601959190910190600101615145565b5093949350505050565b60006001600160fb1b0383111561519457600080fd5b8260051b80838637939093019392505050565b60006151be6151b783878961513f565b848661517e565b9695505050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8183526000602080850194508260005b8581101561522d576001600160a01b0361521a836144ac565b1687529582019590820190600101615201565b509495945050505050565b81835260006001600160fb1b0383111561525157600080fd5b8260051b80836020870137939093016020019392505050565b60808152600061527e608083018a8c6151c8565b602083820381850152818983528183019050818a60051b8401018b60005b8c81101561530b57858303601f190184528135368f9003601e190181126152c257600080fd5b8e0185810190356001600160401b038111156152dd57600080fd5b8036038213156152ec57600080fd5b6152f78582846151c8565b95870195945050509084019060010161529c565b50508581036040870152615320818a8c6151f1565b93505050508281036060840152615338818587615238565b9b9a5050505050505050505050565b838152818360208301376000910160200190815292915050565b600181811c9082168061537557607f821691505b60208210810361461a57634e487b7160e01b600052602260045260246000fd5b60006001600160401b038083168181036153b1576153b161502f565b6001019392505050565b86815285602082015260006153d76151b760408401878961513f565b98975050505050505050565b6000602082840312156153f557600080fd5b5051919050565b6000808335601e1984360301811261541357600080fd5b8301803591506001600160401b0382111561542d57600080fd5b60200191503681900382131561431c57600080fd5b8183823760009101908152919050565b803563ffffffff811681146144c357600080fd5b600060e0828403121561547857600080fd5b60405160e081018181106001600160401b038211171561549a5761549a61451c565b6040526154a6836144ac565b8152602083013560208201526154be604084016144ac565b60408201526154cf60608401614fee565b60608201526154e060808401614fee565b60808201526154f160a08401615452565b60a082015261550260c084016144ac565b60c08201529392505050565b6001600160601b0319606098891b8116825296881b871660148201529490961b9094166028840152603c8301919091526001600160c01b031960c091821b8116605c84015292811b831660648301529290921b16606c82015260740190565b60208082526034908201527f20504c455855533a207472616e73666572496420616c726561647920657869736040820152733a39971021b432b1b5903a3432903737b731b29760611b606082015260800190565b601f821115610f2b57600081815260208120601f850160051c810160208610156155e85750805b601f850160051c820191505b81811015615607578281556001016155f4565b505050505050565b81516001600160401b038111156156285761562861451c565b61563c816156368454615361565b846155c1565b602080601f83116001811461567157600084156156595750858301515b600019600386901b1c1916600185901b178555615607565b600085815260208120601f198616915b828110156156a057888601518255948401946001909101908401615681565b50858210156156be5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b0388811682526001600160401b03881660208301528681166040830152851660608201526080810184905260a0810183905260e060c0820181905260009061571f90830184614d5b565b9998505050505050505050565b6000610100823603121561573f57600080fd5b615747614532565b615750836144ac565b815261575e60208401614fee565b602082015260408301356001600160401b0381111561577c57600080fd5b615788368286016145b2565b604083015250606083013560608201526080830135608082015260a083013560a08201526157b860c08401614fee565b60c08201526157c960e084016144ac565b60e082015292915050565b6001600160a01b03871681526001600160401b038616602082015260c06040820181905260009061580790830187614d5b565b606083019590955250608081019290925260a0909101529392505050565b60006bffffffffffffffffffffffff19808a60601b1683528851615850816014860160208d01614d37565b606098891b9091166014939091019283015250602881019490945260c092831b6001600160c01b0319908116604886015291831b8216605085015290911b1660588201520192915050565b60208082526023908201527f7369676e65727320616e6420706f77657273206c656e677468206e6f74206d616040820152620e8c6d60eb1b606082015260800190565b80820281158282048414176119925761199261502f565b60008261591257634e487b7160e01b600052601260045260246000fd5b500490565b803561ffff811681146144c357600080fd5b6000610100823603121561593c57600080fd5b615944614532565b61594d836144ac565b81526020830135602082015261596560408401615917565b6040820152615976606084016144ac565b606082015261598760808401615452565b608082015260a083013560a082015260c08301356001600160401b038111156159af57600080fd5b6159bb368286016145b2565b60c0830152506157c960e084016144ac565b60018060a01b038716815285602082015261ffff8516604082015283606082015263ffffffff8316608082015260c060a082015260006153d760c0830184614d5b565b61ffff8516815283602082015263ffffffff831660408201526080606082015260006151be6080830184614d5b565b600060208284031215615a5157600080fd5b81518015158114613c0657600080fd5b600060208284031215615a7357600080fd5b613c0682614fee565b604081526000615a906040830186886151f1565b8281036020840152614468818587615238565b634e487b7160e01b600052602160045260246000fd5b60008251615acb818460208701614d37565b919091019291505056feba46c7ec9a8551ced55787e1e5883df75add3284e2e55e9bdacfed24483c2809a26469706673582212202f18e336d943a607731e17a0acca58c806f5095f0ae043163f09ad6f2956f77264736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001111111254eeb25477b68fb85ed929f73a9605820000000000000000000000005427fefa711eff984124bfbb1ab6fbf5e3da182000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ee18b2214aff97000d974cf647e7c347e8fa585
-----Decoded View---------------
Arg [0] : router (address): 0x1111111254EEB25477B68fb85Ed929f73A960582
Arg [1] : cbridge (address): 0x5427FEFA711Eff984124bFBB1AB6fbf5E3DA1820
Arg [2] : poly (address): 0x0000000000000000000000000000000000000000
Arg [3] : portal (address): 0x3ee18B2214AFF97000D974cf647E7C347E8fa585
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000001111111254eeb25477b68fb85ed929f73a960582
Arg [1] : 0000000000000000000000005427fefa711eff984124bfbb1ab6fbf5e3da1820
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [3] : 0000000000000000000000003ee18b2214aff97000d974cf647e7c347e8fa585
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.