Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 31,333 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Redeem With Lock... | 22311088 | 19 hrs ago | IN | 0 ETH | 0.00036044 | ||||
Redeem With Lock... | 22310695 | 20 hrs ago | IN | 0 ETH | 0.00033414 | ||||
Fulfill Order | 22309455 | 24 hrs ago | IN | 0 ETH | 0.00163506 | ||||
Fulfill Order | 22303915 | 43 hrs ago | IN | 0 ETH | 0.00153991 | ||||
Fulfill Order | 22303879 | 43 hrs ago | IN | 0 ETH | 0.00117693 | ||||
Fulfill Order | 22303847 | 43 hrs ago | IN | 0 ETH | 0.00086886 | ||||
Fulfill Order | 22298627 | 2 days ago | IN | 0 ETH | 0.00172804 | ||||
Fulfill Order | 22291604 | 3 days ago | IN | 0 ETH | 0.00143618 | ||||
Redeem With Lock... | 22288904 | 3 days ago | IN | 0 ETH | 0.00033984 | ||||
Redeem With Lock... | 22288888 | 3 days ago | IN | 0 ETH | 0.00034065 | ||||
Redeem With Lock... | 22288866 | 3 days ago | IN | 0 ETH | 0.00037676 | ||||
Redeem With Lock... | 22284412 | 4 days ago | IN | 0 ETH | 0.00035123 | ||||
Fulfill Order | 22284396 | 4 days ago | IN | 0 ETH | 0.00092027 | ||||
Redeem With Lock... | 22284360 | 4 days ago | IN | 0 ETH | 0.00034606 | ||||
Fulfill Order | 22284040 | 4 days ago | IN | 0 ETH | 0.00108157 | ||||
Fulfill Order | 22283999 | 4 days ago | IN | 0 ETH | 0.00101293 | ||||
Fulfill Order | 22282448 | 4 days ago | IN | 0 ETH | 0.00281737 | ||||
Redeem With Lock... | 22280106 | 5 days ago | IN | 0 ETH | 0.00037797 | ||||
Redeem With Lock... | 22279955 | 5 days ago | IN | 0 ETH | 0.00036964 | ||||
Redeem With Lock... | 22278467 | 5 days ago | IN | 0 ETH | 0.00037337 | ||||
Fulfill Order | 22271172 | 6 days ago | IN | 0 ETH | 0.00112632 | ||||
Redeem With Lock... | 22269487 | 6 days ago | IN | 0 ETH | 0.00042218 | ||||
Fulfill Order | 22268924 | 6 days ago | IN | 0 ETH | 0.00180686 | ||||
Redeem With Lock... | 22267689 | 6 days ago | IN | 0 ETH | 0.00098249 | ||||
Fulfill Order | 22262252 | 7 days ago | IN | 0 ETH | 0.00165647 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Method | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|---|
Transfer | 22309455 | 24 hrs ago | 10.47650226 ETH | ||||
Transfer | 22309455 | 24 hrs ago | 0.01048698 ETH | ||||
Transfer | 22309455 | 24 hrs ago | 10.48698925 ETH | ||||
Transfer | 22303915 | 43 hrs ago | 4.55985239 ETH | ||||
Transfer | 22303915 | 43 hrs ago | 0.00456441 ETH | ||||
Transfer | 22303915 | 43 hrs ago | 4.56441681 ETH | ||||
Transfer | 22303879 | 43 hrs ago | 8.1299782 ETH | ||||
Transfer | 22303879 | 43 hrs ago | 0.00813811 ETH | ||||
Transfer | 22303879 | 43 hrs ago | 8.13811632 ETH | ||||
Transfer | 22303847 | 43 hrs ago | 6.16169454 ETH | ||||
Transfer | 22303847 | 43 hrs ago | 0.00616786 ETH | ||||
Transfer | 22303847 | 43 hrs ago | 6.1678624 ETH | ||||
Transfer | 22291604 | 3 days ago | 11.7426298 ETH | ||||
Transfer | 22291604 | 3 days ago | 0.01175438 ETH | ||||
Transfer | 22291604 | 3 days ago | 11.75438419 ETH | ||||
Transfer | 22284396 | 4 days ago | 3.88496236 ETH | ||||
Transfer | 22284396 | 4 days ago | 0.00388885 ETH | ||||
Transfer | 22284396 | 4 days ago | 3.88885121 ETH | ||||
Transfer | 22284040 | 4 days ago | 5.71543917 ETH | ||||
Transfer | 22284040 | 4 days ago | 5.71543917 ETH | ||||
Transfer | 22282448 | 4 days ago | 2.96204957 ETH | ||||
Transfer | 22282448 | 4 days ago | 0.00296501 ETH | ||||
Transfer | 22282448 | 4 days ago | 2.96501459 ETH | ||||
Transfer | 22271172 | 6 days ago | 12.08741892 ETH | ||||
Transfer | 22271172 | 6 days ago | 0.01209951 ETH |
Loading...
Loading
Contract Name:
MayanCircle
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "./libs/BytesLib.sol"; import "./interfaces/CCTP/IReceiver.sol"; import "./interfaces/CCTP/ITokenMessenger.sol"; import "./interfaces/IWormhole.sol"; import "./interfaces/ITokenBridge.sol"; import "./interfaces/IFeeManager.sol"; contract MayanCircle is ReentrancyGuard { using SafeERC20 for IERC20; using BytesLib for bytes; IWormhole public immutable wormhole; ITokenMessenger public immutable cctpTokenMessenger; IFeeManager public feeManager; uint32 public immutable localDomain; uint16 public immutable auctionChainId; bytes32 public immutable auctionAddr; bytes32 public immutable solanaEmitter; uint8 public consistencyLevel; address public guardian; address nextGuardian; bool public paused; mapping(uint64 => FeeLock) public feeStorage; uint8 constant ETH_DECIMALS = 18; uint32 constant SOLANA_DOMAIN = 5; uint16 constant SOLANA_CHAIN_ID = 1; event OrderFulfilled(uint32 sourceDomain, uint64 sourceNonce, uint256 amount); event OrderRefunded(uint32 sourceDomain, uint64 sourceNonce, uint256 amount); error Paused(); error Unauthorized(); error InvalidDomain(); error InvalidNonce(); error InvalidOrder(); error CctpReceiveFailed(); error InvalidGasDrop(); error InvalidAction(); error InvalidEmitter(); enum Action { NONE, SWAP, FULFILL, BRIDGE_WITH_FEE, UNLOCK_FEE, UNLOCK_FEE_REFINE } struct Order { bytes32 trader; uint16 sourceChain; bytes32 tokenIn; uint64 amountIn; bytes32 destAddr; uint16 destChain; bytes32 tokenOut; uint64 minAmountOut; uint64 gasDrop; uint64 redeemFee; uint64 deadline; bytes32 referrerAddr; uint8 referrerBps; uint8 protocolBps; } struct OrderParams { address tokenIn; uint256 amountIn; uint64 gasDrop; bytes32 destAddr; uint16 destChain; bytes32 tokenOut; uint64 minAmountOut; uint64 deadline; uint64 redeemFee; bytes32 referrerAddr; uint8 referrerBps; } struct ExtraParams { bytes32 trader; uint16 sourceChainId; uint8 protocolBps; } struct OrderMsg { uint8 action; uint8 payloadId; bytes32 orderHash; } struct FeeLock { bytes32 destAddr; uint64 gasDrop; address token; uint256 redeemFee; } struct CctpRecipient { uint32 destDomain; bytes32 mintRecipient; bytes32 callerAddr; } struct BridgeWithFeeMsg { uint8 action; uint8 payloadId; uint64 cctpNonce; uint32 cctpDomain; bytes32 destAddr; uint64 gasDrop; uint64 redeemFee; } struct UnlockFeeMsg { uint8 action; uint8 payloadId; uint64 cctpNonce; uint32 cctpDomain; bytes32 unlockerAddr; uint64 gasDrop; } struct UnlockRefinedFeeMsg { uint8 action; uint8 payloadId; uint64 cctpNonce; uint32 cctpDomain; bytes32 unlockerAddr; uint64 gasDrop; bytes32 destAddr; } struct FulfillMsg { uint8 action; uint8 payloadId; uint16 destChainId; bytes32 destAddr; bytes32 driver; bytes32 tokenOut; uint64 promisedAmount; uint64 gasDrop; bytes32 referrerAddr; uint8 referrerBps; uint8 protocolBps; uint64 deadline; uint64 redeemFee; uint32 cctpDomain; uint64 cctpNonce; } constructor( address _cctpTokenMessenger, address _wormhole, address _feeManager, uint16 _auctionChainId, bytes32 _auctionAddr, bytes32 _solanaEmitter, uint8 _consistencyLevel ) { cctpTokenMessenger = ITokenMessenger(_cctpTokenMessenger); wormhole = IWormhole(_wormhole); feeManager = IFeeManager(_feeManager); auctionChainId = _auctionChainId; auctionAddr = _auctionAddr; solanaEmitter = _solanaEmitter; consistencyLevel = _consistencyLevel; localDomain = ITokenMessenger(_cctpTokenMessenger).localMessageTransmitter().localDomain(); guardian = msg.sender; } function bridgeWithFee( address tokenIn, uint256 amountIn, uint64 redeemFee, uint64 gasDrop, bytes32 destAddr, CctpRecipient memory recipient ) external payable nonReentrant returns (uint64 sequence) { if (paused) { revert Paused(); } uint256 burnAmount = IERC20(tokenIn).balanceOf(address(this)); IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn); burnAmount = IERC20(tokenIn).balanceOf(address(this)) - burnAmount; maxApproveIfNeeded(tokenIn, address(cctpTokenMessenger), burnAmount); uint64 ccptNonce = cctpTokenMessenger.depositForBurnWithCaller(burnAmount, recipient.destDomain, recipient.mintRecipient, tokenIn, recipient.callerAddr); BridgeWithFeeMsg memory bridgeMsg = BridgeWithFeeMsg({ action: uint8(Action.BRIDGE_WITH_FEE), payloadId: 1, cctpNonce: ccptNonce, cctpDomain: localDomain, destAddr: destAddr, gasDrop: gasDrop, redeemFee: redeemFee }); bytes memory encoded = encodeBridgeWithFee(bridgeMsg); sequence = wormhole.publishMessage{ value : msg.value }(0, encoded, consistencyLevel); } function bridgeWithLockedFee( address tokenIn, uint256 amountIn, uint64 gasDrop, uint256 redeemFee, CctpRecipient memory recipient ) external nonReentrant returns (uint64 cctpNonce) { if (paused) { revert Paused(); } if (recipient.destDomain == SOLANA_DOMAIN) { revert InvalidDomain(); } require(redeemFee > 0, 'zero redeem fee'); uint256 burnAmount = IERC20(tokenIn).balanceOf(address(this)); IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn); burnAmount = IERC20(tokenIn).balanceOf(address(this)) - burnAmount; maxApproveIfNeeded(tokenIn, address(cctpTokenMessenger), burnAmount - redeemFee); cctpNonce = cctpTokenMessenger.depositForBurnWithCaller(burnAmount - redeemFee, recipient.destDomain, recipient.mintRecipient, tokenIn, recipient.callerAddr); feeStorage[cctpNonce] = FeeLock({ destAddr: recipient.mintRecipient, gasDrop: gasDrop, token: tokenIn, redeemFee: redeemFee }); } function createOrder( OrderParams memory params, CctpRecipient memory recipient ) external payable nonReentrant { if (paused) { revert Paused(); } if (params.tokenOut == bytes32(0) && params.gasDrop > 0) { revert InvalidGasDrop(); } IERC20(params.tokenIn).safeTransferFrom(msg.sender, address(this), params.amountIn); maxApproveIfNeeded(params.tokenIn, address(cctpTokenMessenger), params.amountIn); uint64 ccptNonce = cctpTokenMessenger.depositForBurnWithCaller(params.amountIn, recipient.destDomain, recipient.mintRecipient, params.tokenIn, recipient.callerAddr); require(params.referrerBps <= 50, 'invalid referrer bps'); uint8 protocolBps = feeManager.calcProtocolBps(uint64(params.amountIn), params.tokenIn, params.tokenOut, params.destChain, params.referrerBps); require(protocolBps <= 50, 'invalid protocol bps'); Order memory order = Order({ trader: bytes32(uint256(uint160(msg.sender))), sourceChain: wormhole.chainId(), tokenIn: bytes32(uint256(uint160(params.tokenIn))), amountIn: uint64(params.amountIn), destAddr: params.destAddr, destChain: params.destChain, tokenOut: params.tokenOut, minAmountOut: params.minAmountOut, gasDrop: params.gasDrop, redeemFee: params.redeemFee, deadline: params.deadline, referrerAddr: params.referrerAddr, referrerBps: params.referrerBps, protocolBps: protocolBps }); bytes memory encodedOrder = encodeOrder(order); encodedOrder = encodedOrder.concat(abi.encodePacked(ccptNonce, cctpTokenMessenger.localMessageTransmitter().localDomain())); bytes32 orderHash = keccak256(encodedOrder); OrderMsg memory orderMsg = OrderMsg({ action: uint8(Action.SWAP), payloadId: 1, orderHash: orderHash }); bytes memory encodedMsg = encodeOrderMsg(orderMsg); wormhole.publishMessage{ value : msg.value }(0, encodedMsg, consistencyLevel); } function redeemWithFee(bytes memory cctpMsg, bytes memory cctpSigs, bytes memory encodedVm) external nonReentrant payable { (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole.parseAndVerifyVM(encodedVm); require(valid, reason); if (vm.emitterAddress != solanaEmitter && truncateAddress(vm.emitterAddress) != address(this)) { revert InvalidEmitter(); } BridgeWithFeeMsg memory redeemMsg = parseBridgeWithFee(vm.payload); if (redeemMsg.action != uint8(Action.BRIDGE_WITH_FEE)) { revert InvalidAction(); } uint256 denormalizedGasDrop = deNormalizeAmount(redeemMsg.gasDrop, ETH_DECIMALS); if (msg.value != denormalizedGasDrop) { revert InvalidGasDrop(); } uint32 cctpSourceDomain = cctpMsg.toUint32(4); uint64 cctpNonce = cctpMsg.toUint64(12); bytes32 cctpSourceToken = cctpMsg.toBytes32(120); if (cctpSourceDomain != redeemMsg.cctpDomain) { revert InvalidDomain(); } if (cctpNonce != redeemMsg.cctpNonce) { revert InvalidNonce(); } address localToken = cctpTokenMessenger.localMinter().getLocalToken(cctpSourceDomain, cctpSourceToken); uint256 amount = IERC20(localToken).balanceOf(address(this)); bool success = cctpTokenMessenger.localMessageTransmitter().receiveMessage(cctpMsg, cctpSigs); if (!success) { revert CctpReceiveFailed(); } amount = IERC20(localToken).balanceOf(address(this)) - amount; IERC20(localToken).safeTransfer(msg.sender, uint256(redeemMsg.redeemFee)); address recipient = truncateAddress(redeemMsg.destAddr); IERC20(localToken).safeTransfer(recipient, amount - uint256(redeemMsg.redeemFee)); payable(recipient).transfer(denormalizedGasDrop); } function redeemWithLockedFee(bytes memory cctpMsg, bytes memory cctpSigs, bytes32 unlockerAddr) external nonReentrant payable returns (uint64 sequence) { uint32 cctpSourceDomain = cctpMsg.toUint32(4); uint64 cctpNonce = cctpMsg.toUint64(12); address caller = truncateAddress(cctpMsg.toBytes32(84)); require(caller == address(this), 'invalid caller'); address mintRecipient = truncateAddress(cctpMsg.toBytes32(152)); require(mintRecipient != address(this), 'invalid mint recipient'); bool success = cctpTokenMessenger.localMessageTransmitter().receiveMessage(cctpMsg, cctpSigs); if (!success) { revert CctpReceiveFailed(); } uint256 wormholeFee = wormhole.messageFee(); payable(mintRecipient).transfer(msg.value - wormholeFee); UnlockFeeMsg memory unlockMsg = UnlockFeeMsg({ action: uint8(Action.UNLOCK_FEE), payloadId: 1, cctpDomain: cctpSourceDomain, cctpNonce: cctpNonce, unlockerAddr: unlockerAddr, gasDrop: uint64(normalizeAmount(msg.value - wormholeFee, ETH_DECIMALS)) }); bytes memory encodedMsg = encodeUnlockFeeMsg(unlockMsg); sequence = wormhole.publishMessage{ value : wormholeFee }(0, encodedMsg, consistencyLevel); } function refineFee(uint32 cctpNonce, uint32 cctpDomain, bytes32 destAddr, bytes32 unlockerAddr) external nonReentrant payable returns (uint64 sequence) { uint256 wormholeFee = wormhole.messageFee(); payable(truncateAddress(destAddr)).transfer(msg.value - wormholeFee); UnlockRefinedFeeMsg memory unlockMsg = UnlockRefinedFeeMsg({ action: uint8(Action.UNLOCK_FEE_REFINE), payloadId: 1, cctpDomain: cctpDomain, cctpNonce: cctpNonce, unlockerAddr: unlockerAddr, gasDrop: uint64(normalizeAmount(msg.value - wormholeFee, ETH_DECIMALS)), destAddr: destAddr }); bytes memory encodedMsg = encodeUnlockRefinedFeeMsg(unlockMsg); sequence = wormhole.publishMessage{ value : wormholeFee }(0, encodedMsg, consistencyLevel); } function unlockFee(bytes memory encodedVm) public nonReentrant { (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole.parseAndVerifyVM(encodedVm); require(valid, reason); if (vm.emitterChainId == SOLANA_CHAIN_ID) { require(vm.emitterAddress == solanaEmitter, 'invalid solana emitter'); } else { require(truncateAddress(vm.emitterAddress) == address(this), 'invalid evm emitter'); } UnlockFeeMsg memory unlockMsg = parseUnlockFeeMsg(vm.payload); if (unlockMsg.action != uint8(Action.UNLOCK_FEE)) { revert InvalidAction(); } if (unlockMsg.cctpDomain != localDomain) { revert InvalidDomain(); } FeeLock memory feeLock = feeStorage[unlockMsg.cctpNonce]; require(feeLock.redeemFee > 0, 'fee not locked'); if (unlockMsg.gasDrop < feeLock.gasDrop) { revert InvalidGasDrop(); } IERC20(feeLock.token).safeTransfer(truncateAddress(unlockMsg.unlockerAddr), feeLock.redeemFee); delete feeStorage[unlockMsg.cctpNonce]; } function unlockFeeRefined(bytes memory encodedVm1, bytes memory encodedVm2) public nonReentrant { (IWormhole.VM memory vm1, bool valid1, string memory reason1) = wormhole.parseAndVerifyVM(encodedVm1); require(valid1, reason1); if (vm1.emitterAddress != solanaEmitter && truncateAddress(vm1.emitterAddress) != address(this)) { revert InvalidEmitter(); } UnlockFeeMsg memory unlockMsg = parseUnlockFeeMsg(vm1.payload); if (unlockMsg.action != uint8(Action.UNLOCK_FEE_REFINE)) { revert InvalidAction(); } if (unlockMsg.cctpDomain != localDomain) { revert InvalidDomain(); } FeeLock memory feeLock = feeStorage[unlockMsg.cctpNonce]; require(feeLock.redeemFee > 0, 'fee not locked'); require(unlockMsg.gasDrop < feeLock.gasDrop, 'gas was sufficient'); (IWormhole.VM memory vm2, bool valid2, string memory reason2) = wormhole.parseAndVerifyVM(encodedVm2); require(valid2, reason2); if (vm2.emitterAddress != solanaEmitter && truncateAddress(vm2.emitterAddress) != address(this)) { revert InvalidEmitter(); } UnlockRefinedFeeMsg memory refinedMsg = parseUnlockRefinedFee(vm1.payload); require(refinedMsg.destAddr == feeLock.destAddr, 'invalid dest addr'); if (refinedMsg.cctpNonce != unlockMsg.cctpNonce) { revert InvalidNonce(); } if (refinedMsg.cctpDomain != unlockMsg.cctpDomain) { revert InvalidDomain(); } if (refinedMsg.gasDrop + unlockMsg.gasDrop < feeLock.gasDrop) { revert InvalidGasDrop(); } IERC20(feeLock.token).safeTransfer(truncateAddress(refinedMsg.unlockerAddr), feeLock.redeemFee); delete feeStorage[unlockMsg.cctpNonce]; } function fulfillOrder( bytes memory cctpMsg, bytes memory cctpSigs, bytes memory encodedVm, address swapProtocol, bytes memory swapData ) public nonReentrant payable { (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole.parseAndVerifyVM(encodedVm); require(valid, reason); require(vm.emitterChainId == SOLANA_CHAIN_ID, 'invalid emitter chain'); require(vm.emitterAddress == auctionAddr, 'invalid solana emitter'); FulfillMsg memory fulfillMsg = parseFulfillMsg(vm.payload); require(fulfillMsg.deadline >= block.timestamp, 'deadline passed'); require(msg.sender == truncateAddress(fulfillMsg.driver), 'invalid driver'); uint32 cctpSourceDomain = cctpMsg.toUint32(4); uint64 cctpSourceNonce = cctpMsg.toUint64(12); bytes32 cctpSourceToken = cctpMsg.toBytes32(120); require(cctpSourceDomain == fulfillMsg.cctpDomain, 'invalid cctp domain'); require(cctpSourceNonce == fulfillMsg.cctpNonce, 'invalid cctp nonce'); (address localToken, uint256 cctpAmount) = receiveCctp(cctpMsg, cctpSigs, cctpSourceDomain, cctpSourceToken); if (fulfillMsg.redeemFee > 0) { IERC20(localToken).transfer(msg.sender, fulfillMsg.redeemFee); } address tokenOut = truncateAddress(fulfillMsg.tokenOut); maxApproveIfNeeded(localToken, swapProtocol, cctpAmount - uint256(fulfillMsg.redeemFee)); uint256 amountOut; if (tokenOut == address(0)) { amountOut = address(this).balance; } else { amountOut = IERC20(tokenOut).balanceOf(address(this)); } (bool swapSuccess, bytes memory swapReturn) = swapProtocol.call{value: 0}(swapData); require(swapSuccess, string(swapReturn)); if (tokenOut == address(0)) { amountOut = address(this).balance - amountOut; } else { amountOut = IERC20(tokenOut).balanceOf(address(this)) - amountOut; } uint8 decimals; if (tokenOut == address(0)) { decimals = ETH_DECIMALS; } else { decimals = decimalsOf(tokenOut); } uint256 promisedAmount = deNormalizeAmount(fulfillMsg.promisedAmount, decimals); require(amountOut >= promisedAmount, 'insufficient amount out'); makePayments( fulfillMsg, tokenOut, amountOut ); emit OrderFulfilled(cctpSourceDomain, cctpSourceNonce, amountOut); } function refund( bytes memory encodedVm, bytes memory cctpMsg, bytes memory cctpSigs, OrderParams memory orderParams, ExtraParams memory extraParams ) public nonReentrant payable { (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole.parseAndVerifyVM(encodedVm); require(valid, reason); if (vm.emitterAddress != solanaEmitter && truncateAddress(vm.emitterAddress) != address(this)) { revert InvalidEmitter(); } uint32 cctpSourceDomain = cctpMsg.toUint32(4); uint64 cctpSourceNonce = cctpMsg.toUint64(12); bytes32 cctpSourceToken = cctpMsg.toBytes32(120); (address localToken, uint256 amount) = receiveCctp(cctpMsg, cctpSigs, cctpSourceDomain, cctpSourceToken); Order memory order = recreateOrder(cctpSourceToken, uint64(amount), orderParams, extraParams); bytes memory encodedOrder = encodeOrder(order); encodedOrder = encodedOrder.concat(abi.encodePacked(cctpSourceNonce, cctpSourceDomain)); bytes32 calculatedHash = keccak256(encodedOrder); OrderMsg memory orderMsg = parseOrderMsg(vm.payload); if (orderMsg.action != uint8(Action.SWAP)) { revert InvalidAction(); } if (calculatedHash != orderMsg.orderHash) { revert InvalidOrder(); } require(order.deadline < block.timestamp, 'deadline not passed'); uint256 gasDrop = deNormalizeAmount(order.gasDrop, ETH_DECIMALS); if (msg.value != gasDrop) { revert InvalidGasDrop(); } address destAddr = truncateAddress(order.destAddr); if (gasDrop > 0) { payable(destAddr).transfer(gasDrop); } IERC20(localToken).safeTransfer(msg.sender, order.redeemFee); IERC20(localToken).safeTransfer(destAddr, amount - order.redeemFee); emit OrderRefunded(cctpSourceDomain, cctpSourceNonce, amount); } function receiveCctp(bytes memory cctpMsg, bytes memory cctpSigs, uint32 cctpSourceDomain, bytes32 cctpSourceToken) internal returns (address, uint256) { address localToken = cctpTokenMessenger.localMinter().getLocalToken(cctpSourceDomain, cctpSourceToken); uint256 amount = IERC20(localToken).balanceOf(address(this)); bool success = cctpTokenMessenger.localMessageTransmitter().receiveMessage(cctpMsg, cctpSigs); if (!success) { revert CctpReceiveFailed(); } amount = IERC20(localToken).balanceOf(address(this)) - amount; return (localToken, amount); } function makePayments( FulfillMsg memory fulfillMsg, address tokenOut, uint256 amount ) internal { address referrerAddr = truncateAddress(fulfillMsg.referrerAddr); uint256 referrerAmount = 0; if (referrerAddr != address(0) && fulfillMsg.referrerBps != 0) { referrerAmount = amount * fulfillMsg.referrerBps / 10000; } uint256 protocolAmount = 0; if (fulfillMsg.protocolBps != 0) { protocolAmount = amount * fulfillMsg.protocolBps / 10000; } address destAddr = truncateAddress(fulfillMsg.destAddr); if (tokenOut == address(0)) { if (referrerAmount > 0) { payable(referrerAddr).transfer(referrerAmount); } if (protocolAmount > 0) { payable(feeManager.feeCollector()).transfer(protocolAmount); } payable(destAddr).transfer(amount - referrerAmount - protocolAmount); } else { if (fulfillMsg.gasDrop > 0) { uint256 gasDrop = deNormalizeAmount(fulfillMsg.gasDrop, ETH_DECIMALS); if (msg.value != gasDrop) { revert InvalidGasDrop(); } payable(destAddr).transfer(gasDrop); } if (referrerAmount > 0) { IERC20(tokenOut).safeTransfer(referrerAddr, referrerAmount); } if (protocolAmount > 0) { IERC20(tokenOut).safeTransfer(feeManager.feeCollector(), protocolAmount); } IERC20(tokenOut).safeTransfer(destAddr, amount - referrerAmount - protocolAmount); } } function recreateOrder( bytes32 cctpSourceToken, uint64 amountIn, OrderParams memory params, ExtraParams memory extraParams ) internal pure returns (Order memory) { return Order({ trader: extraParams.trader, sourceChain: extraParams.sourceChainId, tokenIn: cctpSourceToken, amountIn: amountIn, destAddr: params.destAddr, destChain: params.destChain, tokenOut: params.tokenOut, minAmountOut: params.minAmountOut, gasDrop: params.gasDrop, redeemFee: params.redeemFee, deadline: params.deadline, referrerAddr: params.referrerAddr, referrerBps: params.referrerBps, protocolBps: extraParams.protocolBps }); } function encodeBridgeWithFee(BridgeWithFeeMsg memory bridgeMsg) internal pure returns (bytes memory) { return abi.encodePacked( bridgeMsg.action, bridgeMsg.payloadId, bridgeMsg.cctpNonce, bridgeMsg.cctpDomain, bridgeMsg.destAddr, bridgeMsg.gasDrop, bridgeMsg.redeemFee ); } function parseBridgeWithFee(bytes memory payload) internal pure returns (BridgeWithFeeMsg memory) { return BridgeWithFeeMsg({ action: payload.toUint8(0), payloadId: payload.toUint8(1), cctpNonce: payload.toUint64(2), cctpDomain: payload.toUint32(10), destAddr: payload.toBytes32(14), gasDrop: payload.toUint64(46), redeemFee: payload.toUint64(54) }); } function encodeUnlockFeeMsg(UnlockFeeMsg memory unlockMsg) internal pure returns (bytes memory) { return abi.encodePacked( unlockMsg.action, unlockMsg.payloadId, unlockMsg.cctpNonce, unlockMsg.cctpDomain, unlockMsg.unlockerAddr, unlockMsg.gasDrop ); } function encodeUnlockRefinedFeeMsg(UnlockRefinedFeeMsg memory unlockMsg) internal pure returns (bytes memory) { return abi.encodePacked( unlockMsg.action, unlockMsg.payloadId, unlockMsg.cctpNonce, unlockMsg.cctpDomain, unlockMsg.unlockerAddr, unlockMsg.gasDrop, unlockMsg.destAddr ); } function parseFulfillMsg(bytes memory encoded) public pure returns (FulfillMsg memory fulfillMsg) { uint index = 0; fulfillMsg.action = encoded.toUint8(index); index += 1; if (fulfillMsg.action != uint8(Action.FULFILL)) { revert InvalidAction(); } fulfillMsg.payloadId = encoded.toUint8(index); index += 1; fulfillMsg.destChainId = encoded.toUint16(index); index += 2; fulfillMsg.destAddr = encoded.toBytes32(index); index += 32; fulfillMsg.driver = encoded.toBytes32(index); index += 32; fulfillMsg.tokenOut = encoded.toBytes32(index); index += 32; fulfillMsg.promisedAmount = encoded.toUint64(index); index += 8; fulfillMsg.gasDrop = encoded.toUint64(index); index += 8; fulfillMsg.referrerAddr = encoded.toBytes32(index); index += 32; fulfillMsg.referrerBps = encoded.toUint8(index); index += 1; fulfillMsg.protocolBps = encoded.toUint8(index); index += 1; fulfillMsg.deadline = encoded.toUint64(index); index += 8; fulfillMsg.redeemFee = encoded.toUint64(index); index += 8; fulfillMsg.cctpDomain = encoded.toUint32(index); index += 4; fulfillMsg.cctpNonce = encoded.toUint64(index); index += 8; } function parseOrderMsg(bytes memory payload) internal pure returns (OrderMsg memory) { return OrderMsg({ action: payload.toUint8(0), payloadId: payload.toUint8(1), orderHash: payload.toBytes32(2) }); } function parseUnlockFeeMsg(bytes memory payload) internal pure returns (UnlockFeeMsg memory) { return UnlockFeeMsg({ action: payload.toUint8(0), payloadId: payload.toUint8(1), cctpNonce: payload.toUint64(2), cctpDomain: payload.toUint32(10), unlockerAddr: payload.toBytes32(14), gasDrop: payload.toUint64(46) }); } function parseUnlockRefinedFee(bytes memory payload) internal pure returns (UnlockRefinedFeeMsg memory) { return UnlockRefinedFeeMsg({ action: payload.toUint8(0), payloadId: payload.toUint8(1), cctpNonce: payload.toUint64(2), cctpDomain: payload.toUint32(10), unlockerAddr: payload.toBytes32(14), gasDrop: payload.toUint64(46), destAddr: payload.toBytes32(54) }); } function encodeOrder(Order memory order) internal pure returns (bytes memory) { return abi.encodePacked( order.trader, order.sourceChain, order.tokenIn, order.amountIn, order.destAddr, order.destChain, order.tokenOut, order.minAmountOut, order.gasDrop, order.redeemFee, order.deadline, order.referrerAddr, order.referrerBps, order.protocolBps ); } function encodeOrderMsg(OrderMsg memory orderMsg) internal pure returns (bytes memory) { return abi.encodePacked( orderMsg.action, orderMsg.payloadId, orderMsg.orderHash ); } function maxApproveIfNeeded(address tokenAddr, address spender, uint256 amount) internal { IERC20 token = IERC20(tokenAddr); uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < amount) { token.safeApprove(spender, 0); token.safeApprove(spender, type(uint256).max); } } function decimalsOf(address token) internal view returns(uint8) { (,bytes memory queriedDecimals) = token.staticcall(abi.encodeWithSignature('decimals()')); return abi.decode(queriedDecimals, (uint8)); } function normalizeAmount(uint256 amount, uint8 decimals) internal pure returns(uint256) { if (decimals > 8) { amount /= 10 ** (decimals - 8); } return amount; } function deNormalizeAmount(uint256 amount, uint8 decimals) internal pure returns(uint256) { if (decimals > 8) { amount *= 10 ** (decimals - 8); } return amount; } function truncateAddress(bytes32 b) internal pure returns (address) { require(bytes12(b) == 0, 'invalid EVM address'); return address(uint160(uint256(b))); } function setFeeManager(address _feeManager) public { if (msg.sender != guardian) { revert Unauthorized(); } feeManager = IFeeManager(_feeManager); } function setConsistencyLevel(uint8 _consistencyLevel) public { if (msg.sender != guardian) { revert Unauthorized(); } consistencyLevel = _consistencyLevel; } function setPause(bool _pause) public { if (msg.sender != guardian) { revert Unauthorized(); } paused = _pause; } function isPaused() public view returns(bool) { return paused; } function rescueToken(address token, uint256 amount, address to) public { if (msg.sender != guardian) { revert Unauthorized(); } IERC20(token).safeTransfer(to, amount); } function rescueEth(uint256 amount, address payable to) public { if (msg.sender != guardian) { revert Unauthorized(); } require(to != address(0), 'transfer to the zero address'); to.transfer(amount); } function changeGuardian(address newGuardian) public { if (msg.sender != guardian) { revert Unauthorized(); } nextGuardian = newGuardian; } function claimGuardian() public { if (msg.sender != nextGuardian) { revert Unauthorized(); } guardian = nextGuardian; } receive() external payable {} }
// SPDX-License-Identifier: Unlicense /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.8.0 <0.9.0; library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore(0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. )) } return tempBytes; } function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes.slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { require(_bytes.length >= _start + 1 , "toUint8_outOfBounds"); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } }
// SPDX-License-Identifier: Apache 2 pragma solidity ^0.8.0; import "./IWETH.sol"; import "./IWormhole.sol"; interface ITokenBridge { struct Transfer { uint8 payloadID; uint256 amount; bytes32 tokenAddress; uint16 tokenChain; bytes32 to; uint16 toChain; uint256 fee; } struct TransferWithPayload { uint8 payloadID; uint256 amount; bytes32 tokenAddress; uint16 tokenChain; bytes32 to; uint16 toChain; bytes32 fromAddress; bytes payload; } struct AssetMeta { uint8 payloadID; bytes32 tokenAddress; uint16 tokenChain; uint8 decimals; bytes32 symbol; bytes32 name; } struct RegisterChain { bytes32 module; uint8 action; uint16 chainId; uint16 emitterChainID; bytes32 emitterAddress; } struct UpgradeContract { bytes32 module; uint8 action; uint16 chainId; bytes32 newContract; } struct RecoverChainId { bytes32 module; uint8 action; uint256 evmChainId; uint16 newChainId; } event ContractUpgraded(address indexed oldContract, address indexed newContract); function _parseTransferCommon(bytes memory encoded) external pure returns (Transfer memory transfer); function attestToken(address tokenAddress, uint32 nonce) external payable returns (uint64 sequence); function wrapAndTransferETH(uint16 recipientChain, bytes32 recipient, uint256 arbiterFee, uint32 nonce) external payable returns (uint64 sequence); function wrapAndTransferETHWithPayload(uint16 recipientChain, bytes32 recipient, uint32 nonce, bytes memory payload) external payable returns (uint64 sequence); function transferTokens(address token, uint256 amount, uint16 recipientChain, bytes32 recipient, uint256 arbiterFee, uint32 nonce) external payable returns (uint64 sequence); function transferTokensWithPayload(address token, uint256 amount, uint16 recipientChain, bytes32 recipient, uint32 nonce, bytes memory payload) external payable returns (uint64 sequence); function updateWrapped(bytes memory encodedVm) external returns (address token); function createWrapped(bytes memory encodedVm) external returns (address token); function completeTransferWithPayload(bytes memory encodedVm) external returns (bytes memory); function completeTransferAndUnwrapETHWithPayload(bytes memory encodedVm) external returns (bytes memory); function completeTransfer(bytes memory encodedVm) external; function completeTransferAndUnwrapETH(bytes memory encodedVm) external; function encodeAssetMeta(AssetMeta memory meta) external pure returns (bytes memory encoded); function encodeTransfer(Transfer memory transfer) external pure returns (bytes memory encoded); function encodeTransferWithPayload(TransferWithPayload memory transfer) external pure returns (bytes memory encoded); function parsePayloadID(bytes memory encoded) external pure returns (uint8 payloadID); function parseAssetMeta(bytes memory encoded) external pure returns (AssetMeta memory meta); function parseTransfer(bytes memory encoded) external pure returns (Transfer memory transfer); function parseTransferWithPayload(bytes memory encoded) external pure returns (TransferWithPayload memory transfer); function governanceActionIsConsumed(bytes32 hash) external view returns (bool); function isInitialized(address impl) external view returns (bool); function isTransferCompleted(bytes32 hash) external view returns (bool); function wormhole() external view returns (IWormhole); function chainId() external view returns (uint16); function evmChainId() external view returns (uint256); function isFork() external view returns (bool); function governanceChainId() external view returns (uint16); function governanceContract() external view returns (bytes32); function wrappedAsset(uint16 tokenChainId, bytes32 tokenAddress) external view returns (address); function bridgeContracts(uint16 chainId_) external view returns (bytes32); function tokenImplementation() external view returns (address); function WETH() external view returns (IWETH); function outstandingBridged(address token) external view returns (uint256); function isWrappedAsset(address token) external view returns (bool); function finality() external view returns (uint8); function implementation() external view returns (address); function initialize() external; function registerChain(bytes memory encodedVM) external; function upgrade(bytes memory encodedVM) external; function submitRecoverChainId(bytes memory encodedVM) external; function parseRegisterChain(bytes memory encoded) external pure returns (RegisterChain memory chain); function parseUpgrade(bytes memory encoded) external pure returns (UpgradeContract memory chain); function parseRecoverChainId(bytes memory encodedRecoverChainId) external pure returns (RecoverChainId memory rci); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IFeeManager { function calcProtocolBps( uint64 amountIn, address tokenIn, bytes32 tokenOut, uint16 destChain, uint8 referrerBps ) external view returns (uint8); function feeCollector() external view returns (address); }
// SPDX-License-Identifier: Apache 2 pragma solidity ^0.8.0; interface IWormhole { struct GuardianSet { address[] keys; uint32 expirationTime; } struct Signature { bytes32 r; bytes32 s; uint8 v; uint8 guardianIndex; } struct VM { uint8 version; uint32 timestamp; uint32 nonce; uint16 emitterChainId; bytes32 emitterAddress; uint64 sequence; uint8 consistencyLevel; bytes payload; uint32 guardianSetIndex; Signature[] signatures; bytes32 hash; } struct ContractUpgrade { bytes32 module; uint8 action; uint16 chain; address newContract; } struct GuardianSetUpgrade { bytes32 module; uint8 action; uint16 chain; GuardianSet newGuardianSet; uint32 newGuardianSetIndex; } struct SetMessageFee { bytes32 module; uint8 action; uint16 chain; uint256 messageFee; } struct TransferFees { bytes32 module; uint8 action; uint16 chain; uint256 amount; bytes32 recipient; } struct RecoverChainId { bytes32 module; uint8 action; uint256 evmChainId; uint16 newChainId; } event LogMessagePublished(address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel); event ContractUpgraded(address indexed oldContract, address indexed newContract); event GuardianSetAdded(uint32 indexed index); function publishMessage( uint32 nonce, bytes memory payload, uint8 consistencyLevel ) external payable returns (uint64 sequence); function initialize() external; function parseAndVerifyVM(bytes calldata encodedVM) external view returns (VM memory vm, bool valid, string memory reason); function verifyVM(VM memory vm) external view returns (bool valid, string memory reason); function verifySignatures(bytes32 hash, Signature[] memory signatures, GuardianSet memory guardianSet) external pure returns (bool valid, string memory reason); function parseVM(bytes memory encodedVM) external pure returns (VM memory vm); function quorum(uint numGuardians) external pure returns (uint numSignaturesRequiredForQuorum); function getGuardianSet(uint32 index) external view returns (GuardianSet memory); function getCurrentGuardianSetIndex() external view returns (uint32); function getGuardianSetExpiry() external view returns (uint32); function governanceActionIsConsumed(bytes32 hash) external view returns (bool); function isInitialized(address impl) external view returns (bool); function chainId() external view returns (uint16); function isFork() external view returns (bool); function governanceChainId() external view returns (uint16); function governanceContract() external view returns (bytes32); function messageFee() external view returns (uint256); function evmChainId() external view returns (uint256); function nextSequence(address emitter) external view returns (uint64); function parseContractUpgrade(bytes memory encodedUpgrade) external pure returns (ContractUpgrade memory cu); function parseGuardianSetUpgrade(bytes memory encodedUpgrade) external pure returns (GuardianSetUpgrade memory gsu); function parseSetMessageFee(bytes memory encodedSetMessageFee) external pure returns (SetMessageFee memory smf); function parseTransferFees(bytes memory encodedTransferFees) external pure returns (TransferFees memory tf); function parseRecoverChainId(bytes memory encodedRecoverChainId) external pure returns (RecoverChainId memory rci); function submitContractUpgrade(bytes memory _vm) external; function submitSetMessageFee(bytes memory _vm) external; function submitNewGuardianSet(bytes memory _vm) external; function submitTransferFees(bytes memory _vm) external; function submitRecoverChainId(bytes memory _vm) external; }
/* * Copyright (c) 2022, Circle Internet Financial Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.8.0; /** * @title IReceiver * @notice Receives messages on destination chain and forwards them to IMessageDestinationHandler */ interface IReceiver { /** * @notice Receives an incoming message, validating the header and passing * the body to application-specific handler. * @param message The message raw bytes * @param signature The message signature * @return success bool, true if successful */ function receiveMessage(bytes calldata message, bytes calldata signature) external returns (bool success); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IMessageTransmitter.sol"; import "./ITokenMinter.sol"; interface ITokenMessenger { function localMessageTransmitter() external view returns (IMessageTransmitter); function localMinter() external view returns (ITokenMinter); function depositForBurnWithCaller( uint256 amount, uint32 destinationDomain, bytes32 mintRecipient, address burnToken, bytes32 destinationCaller ) external returns (uint64 nonce); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @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: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.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)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ 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"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: Apache 2 pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IWETH is IERC20 { function deposit() external payable; function withdraw(uint amount) external; }
/* * Copyright (c) 2022, Circle Internet Financial Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.8.0; import "./IRelayer.sol"; import "./IReceiver.sol"; /** * @title IMessageTransmitter * @notice Interface for message transmitters, which both relay and receive messages. */ interface IMessageTransmitter is IRelayer, IReceiver { function localDomain() external view returns (uint32); }
/* * Copyright (c) 2022, Circle Internet Financial Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.8.0; /** * @title ITokenMinter * @notice interface for minter of tokens that are mintable, burnable, and interchangeable * across domains. */ interface ITokenMinter { /** * @notice Mints `amount` of local tokens corresponding to the * given (`sourceDomain`, `burnToken`) pair, to `to` address. * @dev reverts if the (`sourceDomain`, `burnToken`) pair does not * map to a nonzero local token address. This mapping can be queried using * getLocalToken(). * @param sourceDomain Source domain where `burnToken` was burned. * @param burnToken Burned token address as bytes32. * @param to Address to receive minted tokens, corresponding to `burnToken`, * on this domain. * @param amount Amount of tokens to mint. Must be less than or equal * to the minterAllowance of this TokenMinter for given `_mintToken`. * @return mintToken token minted. */ function mint( uint32 sourceDomain, bytes32 burnToken, address to, uint256 amount ) external returns (address mintToken); /** * @notice Burn tokens owned by this ITokenMinter. * @param burnToken burnable token. * @param amount amount of tokens to burn. Must be less than or equal to this ITokenMinter's * account balance of the given `_burnToken`. */ function burn(address burnToken, uint256 amount) external; /** * @notice Get the local token associated with the given remote domain and token. * @param remoteDomain Remote domain * @param remoteToken Remote token * @return local token address */ function getLocalToken(uint32 remoteDomain, bytes32 remoteToken) external view returns (address); /** * @notice Set the token controller of this ITokenMinter. Token controller * is responsible for mapping local tokens to remote tokens, and managing * token-specific limits * @param newTokenController new token controller address */ function setTokenController(address newTokenController) external; }
/* * Copyright (c) 2022, Circle Internet Financial Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.8.0; /** * @title IRelayer * @notice Sends messages from source domain to destination domain */ interface IRelayer { /** * @notice Sends an outgoing message from the source domain. * @dev Increment nonce, format the message, and emit `MessageSent` event with message information. * @param destinationDomain Domain of destination chain * @param recipient Address of message recipient on destination domain as bytes32 * @param messageBody Raw bytes content of message * @return nonce reserved by message */ function sendMessage( uint32 destinationDomain, bytes32 recipient, bytes calldata messageBody ) external returns (uint64); /** * @notice Sends an outgoing message from the source domain, with a specified caller on the * destination domain. * @dev Increment nonce, format the message, and emit `MessageSent` event with message information. * WARNING: if the `destinationCaller` does not represent a valid address as bytes32, then it will not be possible * to broadcast the message on the destination domain. This is an advanced feature, and the standard * sendMessage() should be preferred for use cases where a specific destination caller is not required. * @param destinationDomain Domain of destination chain * @param recipient Address of message recipient on destination domain as bytes32 * @param destinationCaller caller on the destination domain, as bytes32 * @param messageBody Raw bytes content of message * @return nonce reserved by message */ function sendMessageWithCaller( uint32 destinationDomain, bytes32 recipient, bytes32 destinationCaller, bytes calldata messageBody ) external returns (uint64); /** * @notice Replace a message with a new message body and/or destination caller. * @dev The `originalAttestation` must be a valid attestation of `originalMessage`. * @param originalMessage original message to replace * @param originalAttestation attestation of `originalMessage` * @param newMessageBody new message body of replaced message * @param newDestinationCaller the new destination caller */ function replaceMessage( bytes calldata originalMessage, bytes calldata originalAttestation, bytes calldata newMessageBody, bytes32 newDestinationCaller ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
{ "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
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_cctpTokenMessenger","type":"address"},{"internalType":"address","name":"_wormhole","type":"address"},{"internalType":"address","name":"_feeManager","type":"address"},{"internalType":"uint16","name":"_auctionChainId","type":"uint16"},{"internalType":"bytes32","name":"_auctionAddr","type":"bytes32"},{"internalType":"bytes32","name":"_solanaEmitter","type":"bytes32"},{"internalType":"uint8","name":"_consistencyLevel","type":"uint8"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CctpReceiveFailed","type":"error"},{"inputs":[],"name":"InvalidAction","type":"error"},{"inputs":[],"name":"InvalidDomain","type":"error"},{"inputs":[],"name":"InvalidEmitter","type":"error"},{"inputs":[],"name":"InvalidGasDrop","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidOrder","type":"error"},{"inputs":[],"name":"Paused","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"sourceDomain","type":"uint32"},{"indexed":false,"internalType":"uint64","name":"sourceNonce","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"OrderFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"sourceDomain","type":"uint32"},{"indexed":false,"internalType":"uint64","name":"sourceNonce","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"OrderRefunded","type":"event"},{"inputs":[],"name":"auctionAddr","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"auctionChainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint64","name":"redeemFee","type":"uint64"},{"internalType":"uint64","name":"gasDrop","type":"uint64"},{"internalType":"bytes32","name":"destAddr","type":"bytes32"},{"components":[{"internalType":"uint32","name":"destDomain","type":"uint32"},{"internalType":"bytes32","name":"mintRecipient","type":"bytes32"},{"internalType":"bytes32","name":"callerAddr","type":"bytes32"}],"internalType":"struct MayanCircle.CctpRecipient","name":"recipient","type":"tuple"}],"name":"bridgeWithFee","outputs":[{"internalType":"uint64","name":"sequence","type":"uint64"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint64","name":"gasDrop","type":"uint64"},{"internalType":"uint256","name":"redeemFee","type":"uint256"},{"components":[{"internalType":"uint32","name":"destDomain","type":"uint32"},{"internalType":"bytes32","name":"mintRecipient","type":"bytes32"},{"internalType":"bytes32","name":"callerAddr","type":"bytes32"}],"internalType":"struct MayanCircle.CctpRecipient","name":"recipient","type":"tuple"}],"name":"bridgeWithLockedFee","outputs":[{"internalType":"uint64","name":"cctpNonce","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cctpTokenMessenger","outputs":[{"internalType":"contract ITokenMessenger","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newGuardian","type":"address"}],"name":"changeGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"consistencyLevel","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint64","name":"gasDrop","type":"uint64"},{"internalType":"bytes32","name":"destAddr","type":"bytes32"},{"internalType":"uint16","name":"destChain","type":"uint16"},{"internalType":"bytes32","name":"tokenOut","type":"bytes32"},{"internalType":"uint64","name":"minAmountOut","type":"uint64"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"redeemFee","type":"uint64"},{"internalType":"bytes32","name":"referrerAddr","type":"bytes32"},{"internalType":"uint8","name":"referrerBps","type":"uint8"}],"internalType":"struct MayanCircle.OrderParams","name":"params","type":"tuple"},{"components":[{"internalType":"uint32","name":"destDomain","type":"uint32"},{"internalType":"bytes32","name":"mintRecipient","type":"bytes32"},{"internalType":"bytes32","name":"callerAddr","type":"bytes32"}],"internalType":"struct MayanCircle.CctpRecipient","name":"recipient","type":"tuple"}],"name":"createOrder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"feeManager","outputs":[{"internalType":"contract IFeeManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"feeStorage","outputs":[{"internalType":"bytes32","name":"destAddr","type":"bytes32"},{"internalType":"uint64","name":"gasDrop","type":"uint64"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"redeemFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"cctpMsg","type":"bytes"},{"internalType":"bytes","name":"cctpSigs","type":"bytes"},{"internalType":"bytes","name":"encodedVm","type":"bytes"},{"internalType":"address","name":"swapProtocol","type":"address"},{"internalType":"bytes","name":"swapData","type":"bytes"}],"name":"fulfillOrder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"localDomain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encoded","type":"bytes"}],"name":"parseFulfillMsg","outputs":[{"components":[{"internalType":"uint8","name":"action","type":"uint8"},{"internalType":"uint8","name":"payloadId","type":"uint8"},{"internalType":"uint16","name":"destChainId","type":"uint16"},{"internalType":"bytes32","name":"destAddr","type":"bytes32"},{"internalType":"bytes32","name":"driver","type":"bytes32"},{"internalType":"bytes32","name":"tokenOut","type":"bytes32"},{"internalType":"uint64","name":"promisedAmount","type":"uint64"},{"internalType":"uint64","name":"gasDrop","type":"uint64"},{"internalType":"bytes32","name":"referrerAddr","type":"bytes32"},{"internalType":"uint8","name":"referrerBps","type":"uint8"},{"internalType":"uint8","name":"protocolBps","type":"uint8"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"redeemFee","type":"uint64"},{"internalType":"uint32","name":"cctpDomain","type":"uint32"},{"internalType":"uint64","name":"cctpNonce","type":"uint64"}],"internalType":"struct MayanCircle.FulfillMsg","name":"fulfillMsg","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"cctpMsg","type":"bytes"},{"internalType":"bytes","name":"cctpSigs","type":"bytes"},{"internalType":"bytes","name":"encodedVm","type":"bytes"}],"name":"redeemWithFee","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"cctpMsg","type":"bytes"},{"internalType":"bytes","name":"cctpSigs","type":"bytes"},{"internalType":"bytes32","name":"unlockerAddr","type":"bytes32"}],"name":"redeemWithLockedFee","outputs":[{"internalType":"uint64","name":"sequence","type":"uint64"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"cctpNonce","type":"uint32"},{"internalType":"uint32","name":"cctpDomain","type":"uint32"},{"internalType":"bytes32","name":"destAddr","type":"bytes32"},{"internalType":"bytes32","name":"unlockerAddr","type":"bytes32"}],"name":"refineFee","outputs":[{"internalType":"uint64","name":"sequence","type":"uint64"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedVm","type":"bytes"},{"internalType":"bytes","name":"cctpMsg","type":"bytes"},{"internalType":"bytes","name":"cctpSigs","type":"bytes"},{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint64","name":"gasDrop","type":"uint64"},{"internalType":"bytes32","name":"destAddr","type":"bytes32"},{"internalType":"uint16","name":"destChain","type":"uint16"},{"internalType":"bytes32","name":"tokenOut","type":"bytes32"},{"internalType":"uint64","name":"minAmountOut","type":"uint64"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint64","name":"redeemFee","type":"uint64"},{"internalType":"bytes32","name":"referrerAddr","type":"bytes32"},{"internalType":"uint8","name":"referrerBps","type":"uint8"}],"internalType":"struct MayanCircle.OrderParams","name":"orderParams","type":"tuple"},{"components":[{"internalType":"bytes32","name":"trader","type":"bytes32"},{"internalType":"uint16","name":"sourceChainId","type":"uint16"},{"internalType":"uint8","name":"protocolBps","type":"uint8"}],"internalType":"struct MayanCircle.ExtraParams","name":"extraParams","type":"tuple"}],"name":"refund","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"to","type":"address"}],"name":"rescueEth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"rescueToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_consistencyLevel","type":"uint8"}],"name":"setConsistencyLevel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeManager","type":"address"}],"name":"setFeeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_pause","type":"bool"}],"name":"setPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"solanaEmitter","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedVm","type":"bytes"}],"name":"unlockFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedVm1","type":"bytes"},{"internalType":"bytes","name":"encodedVm2","type":"bytes"}],"name":"unlockFeeRefined","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wormhole","outputs":[{"internalType":"contract IWormhole","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6101406040523480156200001257600080fd5b50604051620063f7380380620063f78339810160408190526200003591620001bd565b60016000819055606088811b6001600160601b031990811660a0529088901b16608052805460f086901b6001600160f01b03191660e0526101008590526101208490526001600160a01b038781166001600160a81b031990921691909117600160a01b60ff8516021790915560408051632c12192160e01b8152905191891691632c12192191600480820192602092909190829003018186803b158015620000dc57600080fd5b505afa158015620000f1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000117919062000259565b6001600160a01b0316638d3638f46040518163ffffffff1660e01b815260040160206040518083038186803b1580156200015057600080fd5b505afa15801562000165573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018b91906200027f565b60e01b6001600160e01b03191660c052505060028054336001600160a01b031990911617905550620002be9350505050565b600080600080600080600060e0888a031215620001d8578283fd5b8751620001e581620002a5565b6020890151909750620001f881620002a5565b60408901519096506200020b81620002a5565b606089015190955061ffff8116811462000223578384fd5b809450506080880151925060a0880151915060c088015160ff8116811462000249578182fd5b8091505092959891949750929550565b6000602082840312156200026b578081fd5b81516200027881620002a5565b9392505050565b60006020828403121562000291578081fd5b815163ffffffff8116811462000278578182fd5b6001600160a01b0381168114620002bb57600080fd5b50565b60805160601c60a05160601c60c05160e01c60e05160f01c6101005161012051615fef620004086000396000818161057901528181610e8d0152818161181a015281816127ed015281816135ad015261386a01526000818161069c01526107ed015260006103dd01526000818161042401528181610f98015281816126000152613654015260008181610493015281816115c5015281816115f80152818161204a015281816124d4015281816124fd0152818161296501528181612afd01528181612e0601528181612e5c015281816131cb01528181613c6f0152613e07015260008181610396015281816106cd01528181610db50152818161175301528181611d4901528181611ea40152818161217c015281816122c90152818161265e015281816127260152818161306601528181613324015281816134e601526137a30152615fef6000f3fe6080604052600436106101d15760003560e01c80638d3638f4116100f7578063bedb86fb11610095578063e8dfd50811610064578063e8dfd508146105a9578063ec4cc7fb146105dc578063f8a67a621461066a578063fa6a6d361461068a57600080fd5b8063bedb86fb14610507578063d0fb020314610527578063d55ca38314610547578063d96427ff1461056757600080fd5b80639748cf7c116100d15780639748cf7c14610481578063afd9b706146104b5578063b187bd26146104c8578063b25ea8fb146104e757600080fd5b80638d3638f41461041257806394454a5d1461045b578063958c09371461046e57600080fd5b8063459656ee1161016f578063792921671161013e578063792921671461037157806384acd1bb14610384578063853d2c83146103b85780638a261c67146103cb57600080fd5b8063459656ee146102eb578063472d35b914610300578063538ee295146103205780635c975abb1461034057600080fd5b80632fcb4f04116101ab5780632fcb4f041461024857806332ad465f146102685780633f46e914146102a0578063452a9320146102b357600080fd5b8063078eab72146101dd5780631604b215146101f25780631b8789111461021257600080fd5b366101d857005b600080fd5b6101f06101eb36600461551d565b6106be565b005b3480156101fe57600080fd5b506101f061020d36600461539f565b610da6565b34801561021e57600080fd5b5061023261022d36600461539f565b61112d565b60405161023f9190615b57565b60405180910390f35b34801561025457600080fd5b506101f0610263366004615226565b6113bd565b34801561027457600080fd5b5061028861028336600461529f565b611409565b6040516001600160401b03909116815260200161023f565b6101f06102ae3660046155d9565b611744565b3480156102bf57600080fd5b506002546102d3906001600160a01b031681565b6040516001600160a01b03909116815260200161023f565b3480156102f757600080fd5b506101f0611c57565b34801561030c57600080fd5b506101f061031b366004615226565b611ca5565b34801561032c57600080fd5b506101f061033b36600461593b565b611cf1565b34801561034c57600080fd5b5060035461036190600160a01b900460ff1681565b604051901515815260200161023f565b61028861037f3660046158be565b611d3b565b34801561039057600080fd5b506102d37f000000000000000000000000000000000000000000000000000000000000000081565b6102886103c6366004615431565b611f5a565b3480156103d757600080fd5b506103ff7f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff909116815260200161023f565b34801561041e57600080fd5b506104467f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff909116815260200161023f565b6102886104693660046152fa565b612383565b6101f061047c36600461549a565b612717565b34801561048d57600080fd5b506102d37f000000000000000000000000000000000000000000000000000000000000000081565b6101f06104c33660046156c2565b612d6c565b3480156104d457600080fd5b50600354600160a01b900460ff16610361565b3480156104f357600080fd5b506101f0610502366004615873565b6133d9565b34801561051357600080fd5b506101f0610522366004615367565b61348f565b34801561053357600080fd5b506001546102d3906001600160a01b031681565b34801561055357600080fd5b506101f06105623660046153d1565b6134d7565b34801561057357600080fd5b5061059b7f000000000000000000000000000000000000000000000000000000000000000081565b60405190815260200161023f565b3480156105b557600080fd5b506001546105ca90600160a01b900460ff1681565b60405160ff909116815260200161023f565b3480156105e857600080fd5b506106346105f7366004615903565b60046020526000908152604090208054600182015460029092015490916001600160401b03811691600160401b9091046001600160a01b03169084565b604080519485526001600160401b0390931660208501526001600160a01b0390911691830191909152606082015260800161023f565b34801561067657600080fd5b506101f061068536600461525e565b613a5e565b34801561069657600080fd5b5061059b7f000000000000000000000000000000000000000000000000000000000000000081565b6106c6613a9c565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c0fd8bde876040518263ffffffff1660e01b81526004016107179190615aed565b60006040518083038186803b15801561072f57600080fd5b505afa158015610743573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261076b91908101906156f8565b92509250925081819061079a5760405162461bcd60e51b81526004016107919190615aed565b60405180910390fd5b50606083015161ffff166001146107eb5760405162461bcd60e51b815260206004820152601560248201527434b73b30b634b21032b6b4ba3a32b91031b430b4b760591b6044820152606401610791565b7f00000000000000000000000000000000000000000000000000000000000000008360800151146108575760405162461bcd60e51b815260206004820152601660248201527534b73b30b634b21039b7b630b7309032b6b4ba3a32b960511b6044820152606401610791565b60006108668460e0015161112d565b9050428161016001516001600160401b031610156108b85760405162461bcd60e51b815260206004820152600f60248201526e191958591b1a5b99481c185cdcd959608a1b6044820152606401610791565b6108c58160800151613af6565b6001600160a01b0316336001600160a01b0316146109165760405162461bcd60e51b815260206004820152600e60248201526d34b73b30b634b210323934bb32b960911b6044820152606401610791565b60006109238a6004613b4a565b905060006109328b600c613bad565b905060006109418c6078613c0a565b9050836101a0015163ffffffff168363ffffffff16146109995760405162461bcd60e51b815260206004820152601360248201527234b73b30b634b21031b1ba38103237b6b0b4b760691b6044820152606401610791565b836101c001516001600160401b0316826001600160401b0316146109f45760405162461bcd60e51b8152602060048201526012602482015271696e76616c69642063637470206e6f6e636560701b6044820152606401610791565b600080610a038e8e8786613c68565b61018088015191935091506001600160401b031615610aad5761018086015160405163a9059cbb60e01b81523360048201526001600160401b0390911660248201526001600160a01b0383169063a9059cbb90604401602060405180830381600087803b158015610a7357600080fd5b505af1158015610a87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aab9190615383565b505b6000610abc8760a00151613af6565b9050610ae2838d8961018001516001600160401b031685610add9190615ebe565b613fc8565b60006001600160a01b038216610af9575047610b73565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a082319060240160206040518083038186803b158015610b3857600080fd5b505afa158015610b4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b70919061585b565b90505b6000808e6001600160a01b031660008f604051610b909190615aa7565b60006040518083038185875af1925050503d8060008114610bcd576040519150601f19603f3d011682016040523d82523d6000602084013e610bd2565b606091505b5091509150818190610bf75760405162461bcd60e51b81526004016107919190615aed565b506001600160a01b038416610c1757610c108347615ebe565b9250610c9d565b6040516370a0823160e01b815230600482015283906001600160a01b038616906370a082319060240160206040518083038186803b158015610c5857600080fd5b505afa158015610c6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c90919061585b565b610c9a9190615ebe565b92505b60006001600160a01b038516610cb557506012610cc1565b610cbe85614081565b90505b6000610cda8c60c001516001600160401b03168361411c565b905080851015610d2c5760405162461bcd60e51b815260206004820152601760248201527f696e73756666696369656e7420616d6f756e74206f75740000000000000000006044820152606401610791565b610d378c8787614154565b6040805163ffffffff8d1681526001600160401b038c1660208201529081018690527fcc5626df3b699006387b64eca775dbdfecd5ae542e2d6ab22923082e1320dfcb9060600160405180910390a1505050505050505050505050505050610d9f6001600055565b5050505050565b610dae613a9c565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c0fd8bde856040518263ffffffff1660e01b8152600401610dff9190615aed565b60006040518083038186803b158015610e1757600080fd5b505afa158015610e2b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e5391908101906156f8565b925092509250818190610e795760405162461bcd60e51b81526004016107919190615aed565b50606083015161ffff1660011415610efc577f0000000000000000000000000000000000000000000000000000000000000000836080015114610ef75760405162461bcd60e51b815260206004820152601660248201527534b73b30b634b21039b7b630b7309032b6b4ba3a32b960511b6044820152606401610791565b610f5f565b306001600160a01b0316610f138460800151613af6565b6001600160a01b031614610f5f5760405162461bcd60e51b815260206004820152601360248201527234b73b30b634b21032bb369032b6b4ba3a32b960691b6044820152606401610791565b6000610f6e8460e001516144ca565b805190915060ff16600414610f9657604051634a7f394f60e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff16816060015163ffffffff1614610fe6576040516375893cc160e11b815260040160405180910390fd5b6040818101516001600160401b0390811660009081526004602090815290839020835160808101855281548152600182015493841692810192909252600160401b9092046001600160a01b03169281019290925260020154606082018190526110825760405162461bcd60e51b815260206004820152600e60248201526d199959481b9bdd081b1bd8dad95960921b6044820152606401610791565b80602001516001600160401b03168260a001516001600160401b031610156110bd57604051636e51edcd60e11b815260040160405180910390fd5b6110e76110cd8360800151613af6565b606083015160408401516001600160a01b03169190614592565b506040908101516001600160401b0316600090815260046020529081208181556001810180546001600160e01b0319169055600201555061112a91506144c39050565b50565b604080516101e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c08101829052906111b083826145f5565b60ff1682526111c0600182615d4e565b825190915060ff166002146111e857604051634a7f394f60e01b815260040160405180910390fd5b6111f283826145f5565b60ff166020830152611205600182615d4e565b90506112118382614651565b61ffff166040830152611225600282615d4e565b90506112318382613c0a565b6060830152611241602082615d4e565b905061124d8382613c0a565b608083015261125d602082615d4e565b90506112698382613c0a565b60a0830152611279602082615d4e565b90506112858382613bad565b6001600160401b031660c083015261129e600882615d4e565b90506112aa8382613bad565b6001600160401b031660e08301526112c3600882615d4e565b90506112cf8382613c0a565b6101008301526112e0602082615d4e565b90506112ec83826145f5565b60ff16610120830152611300600182615d4e565b905061130c83826145f5565b60ff16610140830152611320600182615d4e565b905061132c8382613bad565b6001600160401b0316610160830152611346600882615d4e565b90506113528382613bad565b6001600160401b031661018083015261136c600882615d4e565b90506113788382613b4a565b63ffffffff166101a083015261138f600482615d4e565b905061139b8382613bad565b6001600160401b03166101c08301526113b5600882615d4e565b905050919050565b6002546001600160a01b031633146113e7576040516282b42960e81b815260040160405180910390fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6000611413613a9c565b600354600160a01b900460ff161561143e576040516313d0ff5960e31b815260040160405180910390fd5b815163ffffffff1660051415611467576040516375893cc160e11b815260040160405180910390fd5b600083116114a95760405162461bcd60e51b815260206004820152600f60248201526e7a65726f2072656465656d2066656560881b6044820152606401610791565b6040516370a0823160e01b81523060048201526000906001600160a01b038816906370a082319060240160206040518083038186803b1580156114eb57600080fd5b505afa1580156114ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611523919061585b565b905061153a6001600160a01b0388163330896146ae565b6040516370a0823160e01b815230600482015281906001600160a01b038916906370a082319060240160206040518083038186803b15801561157b57600080fd5b505afa15801561158f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115b3919061585b565b6115bd9190615ebe565b90506115ee877f0000000000000000000000000000000000000000000000000000000000000000610add8785615ebe565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663f856ddb66116278684615ebe565b8551602087015160408089015190516001600160e01b031960e087901b168152611658949392918e91600401615c58565b602060405180830381600087803b15801561167257600080fd5b505af1158015611686573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116aa919061591f565b6040805160808101825260208087015182526001600160401b03808a168284019081526001600160a01b03808e16858701908152606086018c815284891660009081526004909652969094209451855590516001850180549451909216600160401b026001600160e01b03199094169216919091179190911790559051600290910155915061173b90506001600055565b95945050505050565b61174c613a9c565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c0fd8bde896040518263ffffffff1660e01b815260040161179d9190615aed565b60006040518083038186803b1580156117b557600080fd5b505afa1580156117c9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117f191908101906156f8565b9250925092508181906118175760405162461bcd60e51b81526004016107919190615aed565b507f000000000000000000000000000000000000000000000000000000000000000083608001511415801561186a5750306001600160a01b031661185e8460800151613af6565b6001600160a01b031614155b1561188857604051632c6bb35560e01b815260040160405180910390fd5b6000611895886004613b4a565b905060006118a489600c613bad565b905060006118b38a6078613c0a565b90506000806118c48c8c8786613c68565b915091506000611a1884838d8d604080516101c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a0810191909152604051806101c0016040528083600001518152602001836020015161ffff168152602001868152602001856001600160401b0316815260200184606001518152602001846080015161ffff1681526020018460a0015181526020018460c001516001600160401b0316815260200184604001516001600160401b031681526020018461010001516001600160401b031681526020018460e001516001600160401b03168152602001846101200151815260200184610140015160ff168152602001836040015160ff168152509050949350505050565b90506000611a25826146ec565b9050611a548688604051602001611a3d929190615ac3565b60408051601f19818403018152919052829061476d565b90506000818051906020012090506000611a718c60e001516147ea565b805190915060ff16600114611a9957604051634a7f394f60e01b815260040160405180910390fd5b80604001518214611abd5760405163af61069360e01b815260040160405180910390fd5b428461014001516001600160401b031610611b105760405162461bcd60e51b8152602060048201526013602482015272191958591b1a5b99481b9bdd081c185cdcd959606a1b6044820152606401610791565b6000611b2b8561010001516001600160401b0316601261411c565b9050803414611b4d57604051636e51edcd60e11b815260040160405180910390fd5b6000611b5c8660800151613af6565b90508115611b9c576040516001600160a01b0382169083156108fc029084906000818181858888f19350505050158015611b9a573d6000803e3d6000fd5b505b610120860151611bc1906001600160a01b038a169033906001600160401b0316614592565b611bf0818761012001516001600160401b031689611bdf9190615ebe565b6001600160a01b038b169190614592565b6040805163ffffffff8d1681526001600160401b038c1660208201529081018890527f4f7c61703b83b54f1af0ca9b67d73dc13cc2e91262faf81b0a4927cbce9242399060600160405180910390a15050505050505050505050505050610d9f6001600055565b6003546001600160a01b03163314611c81576040516282b42960e81b815260040160405180910390fd5b600354600280546001600160a01b0319166001600160a01b03909216919091179055565b6002546001600160a01b03163314611ccf576040516282b42960e81b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b03163314611d1b576040516282b42960e81b815260040160405180910390fd5b6001805460ff909216600160a01b0260ff60a01b19909216919091179055565b6000611d45613a9c565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631a90a2196040518163ffffffff1660e01b815260040160206040518083038186803b158015611da057600080fd5b505afa158015611db4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd8919061585b565b9050611de384613af6565b6001600160a01b03166108fc611df98334615ebe565b6040518115909202916000818181858888f19350505050158015611e21573d6000803e3d6000fd5b506040805160e0810190915260009080600560ff1681526001602082015263ffffffff808a166040830152881660608201526080810186905260a001611e71611e6a8534615ebe565b601261484c565b6001600160401b0316815260200186905290506000611e8f8261487a565b6001546040516358cd21bf60e11b81529192507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163b19a437e918691611ef1916000918791600160a01b900460ff1690600401615b25565b6020604051808303818588803b158015611f0a57600080fd5b505af1158015611f1e573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611f43919061591f565b9350505050611f526001600055565b949350505050565b6000611f64613a9c565b6000611f71856004613b4a565b90506000611f8086600c613bad565b90506000611f97611f92886054613c0a565b613af6565b90506001600160a01b0381163014611fe25760405162461bcd60e51b815260206004820152600e60248201526d34b73b30b634b21031b0b63632b960911b6044820152606401610791565b6000611ff2611f92896098613c0a565b90506001600160a01b0381163014156120465760405162461bcd60e51b81526020600482015260166024820152751a5b9d985b1a59081b5a5b9d081c9958da5c1a595b9d60521b6044820152606401610791565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632c1219216040518163ffffffff1660e01b815260040160206040518083038186803b1580156120a157600080fd5b505afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190615242565b6001600160a01b03166357ecfd288a8a6040518363ffffffff1660e01b8152600401612106929190615b00565b602060405180830381600087803b15801561212057600080fd5b505af1158015612134573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121589190615383565b9050806121785760405163605c687360e01b815260040160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631a90a2196040518163ffffffff1660e01b815260040160206040518083038186803b1580156121d357600080fd5b505afa1580156121e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220b919061585b565b90506001600160a01b0383166108fc6122248334615ebe565b6040518115909202916000818181858888f1935050505015801561224c573d6000803e3d6000fd5b506040805160c0810190915260009080600460ff168152600160208201526001600160401b038816604082015263ffffffff89166060820152608081018b905260a00161229c611e6a8534615ebe565b6001600160401b03169052905060006122b482614910565b6001546040516358cd21bf60e11b81529192507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163b19a437e918691612316916000918791600160a01b900460ff1690600401615b25565b6020604051808303818588803b15801561232f57600080fd5b505af1158015612343573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612368919061591f565b9850505050505050505061237c6001600055565b9392505050565b600061238d613a9c565b600354600160a01b900460ff16156123b8576040516313d0ff5960e31b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038916906370a082319060240160206040518083038186803b1580156123fa57600080fd5b505afa15801561240e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612432919061585b565b90506124496001600160a01b03891633308a6146ae565b6040516370a0823160e01b815230600482015281906001600160a01b038a16906370a082319060240160206040518083038186803b15801561248a57600080fd5b505afa15801561249e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124c2919061585b565b6124cc9190615ebe565b90506124f9887f000000000000000000000000000000000000000000000000000000000000000083613fc8565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f856ddb683866000015187602001518d89604001516040518663ffffffff1660e01b815260040161255b959493929190615c58565b602060405180830381600087803b15801561257557600080fd5b505af1158015612589573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ad919061591f565b905060006040518060e00160405280600360058111156125dd57634e487b7160e01b600052602160045260246000fd5b60ff168152600160208201526001600160401b03808516604083015263ffffffff7f00000000000000000000000000000000000000000000000000000000000000001660608301526080820189905289811660a08301528a1660c0909101529050600061264982614998565b6001546040516358cd21bf60e11b81529192507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163b19a437e9134916126ab916000918791600160a01b900460ff1690600401615b25565b6020604051808303818588803b1580156126c457600080fd5b505af11580156126d8573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906126fd919061591f565b94505050505061270d6001600055565b9695505050505050565b61271f613a9c565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c0fd8bde856040518263ffffffff1660e01b81526004016127709190615aed565b60006040518083038186803b15801561278857600080fd5b505afa15801561279c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526127c491908101906156f8565b9250925092508181906127ea5760405162461bcd60e51b81526004016107919190615aed565b507f000000000000000000000000000000000000000000000000000000000000000083608001511415801561283d5750306001600160a01b03166128318460800151613af6565b6001600160a01b031614155b1561285b57604051632c6bb35560e01b815260040160405180910390fd5b600061286a8460e00151614a2e565b805190915060ff1660031461289257604051634a7f394f60e01b815260040160405180910390fd5b60006128ac8260a001516001600160401b0316601261411c565b90508034146128ce57604051636e51edcd60e11b815260040160405180910390fd5b60006128db896004613b4a565b905060006128ea8a600c613bad565b905060006128f98b6078613c0a565b9050846060015163ffffffff168363ffffffff161461292b576040516375893cc160e11b815260040160405180910390fd5b84604001516001600160401b0316826001600160401b03161461296157604051633ab3447f60e11b815260040160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663cb75c11c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156129bc57600080fd5b505afa1580156129d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129f49190615242565b604051633c502b2f60e11b815263ffffffff86166004820152602481018490526001600160a01b0391909116906378a0565e9060440160206040518083038186803b158015612a4257600080fd5b505afa158015612a56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7a9190615242565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b158015612abf57600080fd5b505afa158015612ad3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612af7919061585b565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632c1219216040518163ffffffff1660e01b815260040160206040518083038186803b158015612b5457600080fd5b505afa158015612b68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b8c9190615242565b6001600160a01b03166357ecfd288f8f6040518363ffffffff1660e01b8152600401612bb9929190615b00565b602060405180830381600087803b158015612bd357600080fd5b505af1158015612be7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c0b9190615383565b905080612c2b5760405163605c687360e01b815260040160405180910390fd5b6040516370a0823160e01b815230600482015282906001600160a01b038516906370a082319060240160206040518083038186803b158015612c6c57600080fd5b505afa158015612c80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ca4919061585b565b612cae9190615ebe565b9150612cdb338960c001516001600160401b0316856001600160a01b03166145929092919063ffffffff16565b6000612cea8960800151613af6565b9050612d1a818a60c001516001600160401b031685612d099190615ebe565b6001600160a01b0387169190614592565b6040516001600160a01b0382169089156108fc02908a906000818181858888f19350505050158015612d50573d6000803e3d6000fd5b50505050505050505050505050612d676001600055565b505050565b612d74613a9c565b600354600160a01b900460ff1615612d9f576040516313d0ff5960e31b815260040160405180910390fd5b60a0820151158015612dbe5750600082604001516001600160401b0316115b15612ddc57604051636e51edcd60e11b815260040160405180910390fd5b60208201518251612dfc916001600160a01b0390911690339030906146ae565b612e2f82600001517f00000000000000000000000000000000000000000000000000000000000000008460200151613fc8565b60208083015182519183015184516040808601519051637c2b6edb60e11b81526000956001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169563f856ddb695612e969591949293909290600401615c58565b602060405180830381600087803b158015612eb057600080fd5b505af1158015612ec4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ee8919061591f565b9050603283610140015160ff161115612f3a5760405162461bcd60e51b8152602060048201526014602482015273696e76616c69642072656665727265722062707360601b6044820152606401610791565b6001546020840151845160a0860151608087015161014088015160405162bec7bb60e21b81526001600160401b0390951660048601526001600160a01b039384166024860152604485019290925261ffff16606484015260ff16608483015260009216906302fb1eec9060a40160206040518083038186803b158015612fbf57600080fd5b505afa158015612fd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ff79190615957565b905060328160ff1611156130445760405162461bcd60e51b8152602060048201526014602482015273696e76616c69642070726f746f636f6c2062707360601b6044820152606401610791565b6000604051806101c00160405280336001600160a01b031660001b81526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639a8a05926040518163ffffffff1660e01b815260040160206040518083038186803b1580156130bd57600080fd5b505afa1580156130d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130f5919061583f565b61ffff16815260200186600001516001600160a01b031660001b815260200186602001516001600160401b0316815260200186606001518152602001866080015161ffff1681526020018660a0015181526020018660c001516001600160401b0316815260200186604001516001600160401b031681526020018661010001516001600160401b031681526020018660e001516001600160401b03168152602001866101200151815260200186610140015160ff1681526020018360ff16815250905060006131c3826146ec565b90506132db847f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632c1219216040518163ffffffff1660e01b815260040160206040518083038186803b15801561322257600080fd5b505afa158015613236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061325a9190615242565b6001600160a01b0316638d3638f46040518163ffffffff1660e01b815260040160206040518083038186803b15801561329257600080fd5b505afa1580156132a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132ca91906158a2565b604051602001611a3d929190615ac3565b8051602080830191909120604080516060810182526001808252938101939093528201819052919250600061330f82614b05565b6001546040516358cd21bf60e11b81529192507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163b19a437e913491613371916000918791600160a01b900460ff1690600401615b25565b6020604051808303818588803b15801561338a57600080fd5b505af115801561339e573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906133c3919061591f565b50505050505050506133d56001600055565b5050565b6002546001600160a01b03163314613403576040516282b42960e81b815260040160405180910390fd5b6001600160a01b0381166134595760405162461bcd60e51b815260206004820152601c60248201527f7472616e7366657220746f20746865207a65726f2061646472657373000000006044820152606401610791565b6040516001600160a01b0382169083156108fc029084906000818181858888f19350505050158015612d67573d6000803e3d6000fd5b6002546001600160a01b031633146134b9576040516282b42960e81b815260040160405180910390fd5b60038054911515600160a01b0260ff60a01b19909216919091179055565b6134df613a9c565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c0fd8bde866040518263ffffffff1660e01b81526004016135309190615aed565b60006040518083038186803b15801561354857600080fd5b505afa15801561355c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261358491908101906156f8565b9250925092508181906135aa5760405162461bcd60e51b81526004016107919190615aed565b507f00000000000000000000000000000000000000000000000000000000000000008360800151141580156135fd5750306001600160a01b03166135f18460800151613af6565b6001600160a01b031614155b1561361b57604051632c6bb35560e01b815260040160405180910390fd5b600061362a8460e001516144ca565b805190915060ff1660051461365257604051634a7f394f60e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff16816060015163ffffffff16146136a2576040516375893cc160e11b815260040160405180910390fd5b6040818101516001600160401b0390811660009081526004602090815290839020835160808101855281548152600182015493841692810192909252600160401b9092046001600160a01b031692810192909252600201546060820181905261373e5760405162461bcd60e51b815260206004820152600e60248201526d199959481b9bdd081b1bd8dad95960921b6044820152606401610791565b80602001516001600160401b03168260a001516001600160401b03161061379c5760405162461bcd60e51b815260206004820152601260248201527119d85cc81dd85cc81cdd59999a58da595b9d60721b6044820152606401610791565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c0fd8bde8a6040518263ffffffff1660e01b81526004016137ed9190615aed565b60006040518083038186803b15801561380557600080fd5b505afa158015613819573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261384191908101906156f8565b9250925092508181906138675760405162461bcd60e51b81526004016107919190615aed565b507f00000000000000000000000000000000000000000000000000000000000000008360800151141580156138ba5750306001600160a01b03166138ae8460800151613af6565b6001600160a01b031614155b156138d857604051632c6bb35560e01b815260040160405180910390fd5b60006138e78960e00151614b4d565b855160c0820151919250146139325760405162461bcd60e51b815260206004820152601160248201527034b73b30b634b2103232b9ba1030b2323960791b6044820152606401610791565b85604001516001600160401b031681604001516001600160401b03161461396c57604051633ab3447f60e11b815260040160405180910390fd5b856060015163ffffffff16816060015163ffffffff16146139a0576040516375893cc160e11b815260040160405180910390fd5b84602001516001600160401b03168660a001518260a001516139c29190615d66565b6001600160401b031610156139ea57604051636e51edcd60e11b815260040160405180910390fd5b613a146139fa8260800151613af6565b606087015160408801516001600160a01b03169190614592565b5050506040928301516001600160401b0316600090815260046020529283208381556001810180546001600160e01b031916905560020192909255506133d593506144c392505050565b6002546001600160a01b03163314613a88576040516282b42960e81b815260040160405180910390fd5b612d676001600160a01b0384168284614592565b60026000541415613aef5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610791565b6002600055565b60006001600160a01b0319821615613b465760405162461bcd60e51b8152602060048201526013602482015272696e76616c69642045564d206164647265737360681b6044820152606401610791565b5090565b6000613b57826004615d4e565b83511015613b9e5760405162461bcd60e51b8152602060048201526014602482015273746f55696e7433325f6f75744f66426f756e647360601b6044820152606401610791565b50818101600401515b92915050565b6000613bba826008615d4e565b83511015613c015760405162461bcd60e51b8152602060048201526014602482015273746f55696e7436345f6f75744f66426f756e647360601b6044820152606401610791565b50016008015190565b6000613c17826020615d4e565b83511015613c5f5760405162461bcd60e51b8152602060048201526015602482015274746f427974657333325f6f75744f66426f756e647360581b6044820152606401610791565b50016020015190565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663cb75c11c6040518163ffffffff1660e01b815260040160206040518083038186803b158015613cc657600080fd5b505afa158015613cda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cfe9190615242565b604051633c502b2f60e11b815263ffffffff87166004820152602481018690526001600160a01b0391909116906378a0565e9060440160206040518083038186803b158015613d4c57600080fd5b505afa158015613d60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d849190615242565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b158015613dc957600080fd5b505afa158015613ddd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e01919061585b565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632c1219216040518163ffffffff1660e01b815260040160206040518083038186803b158015613e5e57600080fd5b505afa158015613e72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e969190615242565b6001600160a01b03166357ecfd288a8a6040518363ffffffff1660e01b8152600401613ec3929190615b00565b602060405180830381600087803b158015613edd57600080fd5b505af1158015613ef1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f159190615383565b905080613f355760405163605c687360e01b815260040160405180910390fd5b6040516370a0823160e01b815230600482015282906001600160a01b038516906370a082319060240160206040518083038186803b158015613f7657600080fd5b505afa158015613f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fae919061585b565b613fb89190615ebe565b9299929850919650505050505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152849160009183169063dd62ed3e9060440160206040518083038186803b15801561401457600080fd5b505afa158015614028573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061404c919061585b565b905082811015610d9f5761406b6001600160a01b038316856000614c24565b610d9f6001600160a01b03831685600019614c24565b60408051600481526024810182526020810180516001600160e01b031663313ce56760e01b179052905160009182916001600160a01b038516916140c491615aa7565b600060405180830381855afa9150503d80600081146140ff576040519150601f19603f3d011682016040523d82523d6000602084013e614104565b606091505b509150508080602001905181019061237c9190615957565b600060088260ff16111561414d57614135600883615ed5565b61414090600a615df4565b61414a9084615e9f565b92505b5090919050565b6000614164846101000151613af6565b905060006001600160a01b03821615801590614187575061012085015160ff1615155b156141b05761271085610120015160ff16846141a39190615e9f565b6141ad9190615d91565b90505b600085610140015160ff166000146141e65761271086610140015160ff16856141d99190615e9f565b6141e39190615d91565b90505b60006141f58760600151613af6565b90506001600160a01b038616614359578215614243576040516001600160a01b0385169084156108fc029085906000818181858888f19350505050158015614241573d6000803e3d6000fd5b505b811561430957600160009054906101000a90046001600160a01b03166001600160a01b031663c415b95c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561429757600080fd5b505afa1580156142ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142cf9190615242565b6001600160a01b03166108fc839081150290604051600060405180830381858888f19350505050158015614307573d6000803e3d6000fd5b505b6001600160a01b0381166108fc836143218689615ebe565b61432b9190615ebe565b6040518115909202916000818181858888f19350505050158015614353573d6000803e3d6000fd5b506144ba565b60e08701516001600160401b0316156143e15760006143868860e001516001600160401b0316601261411c565b90508034146143a857604051636e51edcd60e11b815260040160405180910390fd5b6040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156143de573d6000803e3d6000fd5b50505b82156143fb576143fb6001600160a01b0387168585614592565b811561449057600154604080516331056e5760e21b81529051614490926001600160a01b03169163c415b95c916004808301926020929190829003018186803b15801561444757600080fd5b505afa15801561445b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061447f9190615242565b6001600160a01b0388169084614592565b6144ba818361449f8689615ebe565b6144a99190615ebe565b6001600160a01b0389169190614592565b50505050505050565b6001600055565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091526040805160c08101909152806145138460006145f5565b60ff1681526020016145268460016145f5565b60ff168152602001614539846002613bad565b6001600160401b0316815260200161455284600a613b4a565b63ffffffff168152602001614571600e85613c0a90919063ffffffff16565b815260200161458184602e613bad565b6001600160401b0316905292915050565b6040516001600160a01b038316602482015260448101829052612d6790849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614d48565b6000614602826001615d4e565b835110156146485760405162461bcd60e51b8152602060048201526013602482015272746f55696e74385f6f75744f66426f756e647360681b6044820152606401610791565b50016001015190565b600061465e826002615d4e565b835110156146a55760405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b6044820152606401610791565b50016002015190565b6040516001600160a01b03808516602483015283166044820152606481018290526146e69085906323b872dd60e01b906084016145be565b50505050565b6060816000015182602001518360400151846060015185608001518660a001518760c001518860e001518961010001518a61012001518b61014001518c61016001518d61018001518e6101a001516040516020016147579e9d9c9b9a9998979695949392919061599f565b6040516020818303038152906040529050919050565b6060806040519050835180825260208201818101602087015b8183101561479e578051835260209283019201614786565b50855184518101855292509050808201602086015b818310156147cb5780518352602092830192016147b3565b508651929092011591909101601f01601f191660405250905092915050565b604080516060810182526000808252602082018190529181019190915260408051606081019091528061481e8460006145f5565b60ff1681526020016148318460016145f5565b60ff168152602001614844846002613c0a565b905292915050565b600060088260ff16111561414d57614865600883615ed5565b61487090600a615df4565b61414a9084615d91565b8051602080830151604080850151606086810151608088015160a089015160c0808b015196516001600160f81b031960f89b8c1b81169a82019a909a529790991b90971660218701526001600160c01b031993881b841660228701526001600160e01b031960e09290921b91909116602a860152602e8501529390941b909316604e820152605681019290925290607601614757565b8051602080830151604080850151606080870151608088015160a0890151945160f898891b6001600160f81b0319908116988201989098529590971b909516602185015260c091821b6001600160c01b0319908116602286015260e09590951b6001600160e01b031916602a850152602e8401959095521b909116604e820152605601614757565b8051602080830151604080850151606086810151608088015160a089015160c0808b015196516001600160f81b031960f89b8c1b81169a82019a909a529790991b90971660218701526001600160c01b031993881b841660228701526001600160e01b031960e09290921b91909116602a860152602e85015293851b8116604e840152931b909216605683015290605e01614757565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c08101919091526040805160e0810190915280614a7e8460006145f5565b60ff168152602001614a918460016145f5565b60ff168152602001614aa4846002613bad565b6001600160401b03168152602001614abd84600a613b4a565b63ffffffff168152602001614adc600e85613c0a90919063ffffffff16565b8152602001614aec84602e613bad565b6001600160401b03168152602001614581846036613bad565b60608160000151826020015183604001516040516020016147579392919060f893841b6001600160f81b031990811682529290931b9091166001830152600282015260220190565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c08101919091526040805160e0810190915280614b9d8460006145f5565b60ff168152602001614bb08460016145f5565b60ff168152602001614bc3846002613bad565b6001600160401b03168152602001614bdc84600a613b4a565b63ffffffff168152602001614bfb600e85613c0a90919063ffffffff16565b8152602001614c0b84602e613bad565b6001600160401b03168152602001614844846036613c0a565b801580614cad5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015614c7357600080fd5b505afa158015614c87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614cab919061585b565b155b614d185760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610791565b6040516001600160a01b038316602482015260448101829052612d6790849063095ea7b360e01b906064016145be565b6000614d9d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614e1d9092919063ffffffff16565b9050805160001480614dbe575080806020019051810190614dbe9190615383565b612d675760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610791565b6060611f52848460008585600080866001600160a01b03168587604051614e449190615aa7565b60006040518083038185875af1925050503d8060008114614e81576040519150601f19603f3d011682016040523d82523d6000602084013e614e86565b606091505b5091509150614e9787838387614ea2565b979650505050505050565b60608315614f0e578251614f07576001600160a01b0385163b614f075760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610791565b5081611f52565b611f528383815115614f235781518083602001fd5b8060405162461bcd60e51b81526004016107919190615aed565b8035614f4881615f50565b919050565b600082601f830112614f5d578081fd5b815160206001600160401b03821115614f7857614f78615f3a565b614f86818360051b01615cf7565b80838252828201915082860187848660071b8901011115614fa5578586fd5b855b8581101561500c57608080838b031215614fbf578788fd5b614fc7615c8a565b835181528684015187820152604080850151614fe281615faa565b90820152606084810151614ff581615faa565b908201528552938501939190910190600101614fa7565b5090979650505050505050565b8051614f4881615f65565b600082601f830112615034578081fd5b813561504761504282615d27565b615cf7565b81815284602083860101111561505b578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112615085578081fd5b815161509361504282615d27565b8181528460208386010111156150a7578283fd5b611f52826020830160208701615ef8565b6000606082840312156150c9578081fd5b604051606081018181106001600160401b03821117156150eb576150eb615f3a565b60405290508082356150fc81615f83565b8082525060208301356020820152604083013560408201525092915050565b6000610160828403121561512d578081fd5b615135615cb2565b905061514082614f3d565b815260208201356020820152615158604083016151fa565b604082015260608201356060820152615173608083016151d9565b608082015260a082013560a082015261518e60c083016151fa565b60c082015261519f60e083016151fa565b60e08201526101006151b28184016151fa565b9082015261012082810135908201526101406151cf818401615210565b9082015292915050565b8035614f4881615f73565b8051614f4881615f73565b8051614f4881615f83565b8035614f4881615f95565b8051614f4881615f95565b8035614f4881615faa565b8051614f4881615faa565b600060208284031215615237578081fd5b813561237c81615f50565b600060208284031215615253578081fd5b815161237c81615f50565b600080600060608486031215615272578182fd5b833561527d81615f50565b925060208401359150604084013561529481615f50565b809150509250925092565b600080600080600060e086880312156152b6578283fd5b85356152c181615f50565b94506020860135935060408601356152d881615f95565b9250606086013591506152ee87608088016150b8565b90509295509295909350565b6000806000806000806101008789031215615313578384fd5b863561531e81615f50565b955060208701359450604087013561533581615f95565b9350606087013561534581615f95565b92506080870135915061535b8860a089016150b8565b90509295509295509295565b600060208284031215615378578081fd5b813561237c81615f65565b600060208284031215615394578081fd5b815161237c81615f65565b6000602082840312156153b0578081fd5b81356001600160401b038111156153c5578182fd5b611f5284828501615024565b600080604083850312156153e3578182fd5b82356001600160401b03808211156153f9578384fd5b61540586838701615024565b9350602085013591508082111561541a578283fd5b5061542785828601615024565b9150509250929050565b600080600060608486031215615445578081fd5b83356001600160401b038082111561545b578283fd5b61546787838801615024565b9450602086013591508082111561547c578283fd5b5061548986828701615024565b925050604084013590509250925092565b6000806000606084860312156154ae578081fd5b83356001600160401b03808211156154c4578283fd5b6154d087838801615024565b945060208601359150808211156154e5578283fd5b6154f187838801615024565b93506040860135915080821115615506578283fd5b5061551386828701615024565b9150509250925092565b600080600080600060a08688031215615534578283fd5b85356001600160401b038082111561554a578485fd5b61555689838a01615024565b9650602088013591508082111561556b578485fd5b61557789838a01615024565b9550604088013591508082111561558c578485fd5b61559889838a01615024565b9450606088013591506155aa82615f50565b909250608087013590808211156155bf578283fd5b506155cc88828901615024565b9150509295509295909350565b60008060008060008587036102208112156155f2578384fd5b86356001600160401b0380821115615608578586fd5b6156148a838b01615024565b97506020890135915080821115615629578586fd5b6156358a838b01615024565b9650604089013591508082111561564a578586fd5b5061565789828a01615024565b945050615667886060890161511b565b925060606101bf198201121561567b578182fd5b50615684615cd5565b6101c087013581526101e087013561569b81615f73565b60208201526102008701356156af81615faa565b6040820152949793965091945092919050565b6000806101c083850312156156d5578182fd5b6156df848461511b565b91506156ef8461016085016150b8565b90509250929050565b60008060006060848603121561570c578081fd5b83516001600160401b0380821115615722578283fd5b908501906101608288031215615736578283fd5b61573e615cb2565b6157478361521b565b8152615755602084016151ef565b6020820152615766604084016151ef565b6040820152615777606084016151e4565b60608201526080830151608082015261579260a08401615205565b60a08201526157a360c0840161521b565b60c082015260e0830151828111156157b9578485fd5b6157c589828601615075565b60e0830152506101006157d98185016151ef565b9082015261012083810151838111156157f0578586fd5b6157fc8a828701614f4d565b91830191909152506101408381015190820152945061581d60208701615019565b93506040860151915080821115615832578283fd5b5061551386828701615075565b600060208284031215615850578081fd5b815161237c81615f73565b60006020828403121561586c578081fd5b5051919050565b60008060408385031215615885578182fd5b82359150602083013561589781615f50565b809150509250929050565b6000602082840312156158b3578081fd5b815161237c81615f83565b600080600080608085870312156158d3578182fd5b84356158de81615f83565b935060208501356158ee81615f83565b93969395505050506040820135916060013590565b600060208284031215615914578081fd5b813561237c81615f95565b600060208284031215615930578081fd5b815161237c81615f95565b60006020828403121561594c578081fd5b813561237c81615faa565b600060208284031215615968578081fd5b815161237c81615faa565b6000815180845261598b816020860160208601615ef8565b601f01601f19169290920160200192915050565b8e815261ffff60f01b8e60f01b1660208201528c60228201526159d1604282018d60c01b6001600160c01b0319169052565b8a604a8201526159f0606a82018b60f01b6001600160f01b0319169052565b88606c820152615a0f608c82018960c01b6001600160c01b0319169052565b615a28609482018860c01b6001600160c01b0319169052565b615a41609c82018760c01b6001600160c01b0319169052565b615a5a60a482018660c01b6001600160c01b0319169052565b8360ac820152615a7960cc82018460f81b6001600160f81b0319169052565b615a9260cd82018360f81b6001600160f81b0319169052565b60ce019e9d5050505050505050505050505050565b60008251615ab9818460208701615ef8565b9190910192915050565b60c09290921b6001600160c01b031916825260e01b6001600160e01b0319166008820152600c0190565b60208152600061237c6020830184615973565b604081526000615b136040830185615973565b828103602084015261173b8185615973565b63ffffffff84168152606060208201526000615b446060830185615973565b905060ff83166040830152949350505050565b815160ff1681526101e081016020830151615b77602084018260ff169052565b506040830151615b8d604084018261ffff169052565b50606083015160608301526080830151608083015260a083015160a083015260c0830151615bc660c08401826001600160401b03169052565b5060e0830151615be160e08401826001600160401b03169052565b5061010083810151908301526101208084015160ff908116918401919091526101408085015190911690830152610160808401516001600160401b0390811691840191909152610180808501518216908401526101a08085015163ffffffff16908401526101c09384015116929091019190915290565b94855263ffffffff93909316602085015260408401919091526001600160a01b03166060830152608082015260a00190565b604051608081016001600160401b0381118282101715615cac57615cac615f3a565b60405290565b60405161016081016001600160401b0381118282101715615cac57615cac615f3a565b604051606081016001600160401b0381118282101715615cac57615cac615f3a565b604051601f8201601f191681016001600160401b0381118282101715615d1f57615d1f615f3a565b604052919050565b60006001600160401b03821115615d4057615d40615f3a565b50601f01601f191660200190565b60008219821115615d6157615d61615f24565b500190565b60006001600160401b03808316818516808303821115615d8857615d88615f24565b01949350505050565b600082615dac57634e487b7160e01b81526012600452602481fd5b500490565b600181815b80851115615dec578160001904821115615dd257615dd2615f24565b80851615615ddf57918102915b93841c9390800290615db6565b509250929050565b600061237c60ff841683600082615e0d57506001613ba7565b81615e1a57506000613ba7565b8160018114615e305760028114615e3a57615e56565b6001915050613ba7565b60ff841115615e4b57615e4b615f24565b50506001821b613ba7565b5060208310610133831016604e8410600b8410161715615e79575081810a613ba7565b615e838383615db1565b8060001904821115615e9757615e97615f24565b029392505050565b6000816000190483118215151615615eb957615eb9615f24565b500290565b600082821015615ed057615ed0615f24565b500390565b600060ff821660ff841680821015615eef57615eef615f24565b90039392505050565b60005b83811015615f13578181015183820152602001615efb565b838111156146e65750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461112a57600080fd5b801515811461112a57600080fd5b61ffff8116811461112a57600080fd5b63ffffffff8116811461112a57600080fd5b6001600160401b038116811461112a57600080fd5b60ff8116811461112a57600080fdfea2646970667358221220ced90ea25f6f664189f12f8a22a39ce4d8f647ced1e1c1cb900d58b7e591535d64736f6c63430008040033000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af315500000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b000000000000000000000000d00d2a12b5f15992630c48e48d97a2b2f85713100000000000000000000000000000000000000000000000000000000000000001320a277b216ad7630fcdeec95878d2261ef01b423d48cea81ea808d7984a224675233cdd3dab6c9f3134860c2b2443e80072b0880a3405b2bd87234f024711bc0000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x6080604052600436106101d15760003560e01c80638d3638f4116100f7578063bedb86fb11610095578063e8dfd50811610064578063e8dfd508146105a9578063ec4cc7fb146105dc578063f8a67a621461066a578063fa6a6d361461068a57600080fd5b8063bedb86fb14610507578063d0fb020314610527578063d55ca38314610547578063d96427ff1461056757600080fd5b80639748cf7c116100d15780639748cf7c14610481578063afd9b706146104b5578063b187bd26146104c8578063b25ea8fb146104e757600080fd5b80638d3638f41461041257806394454a5d1461045b578063958c09371461046e57600080fd5b8063459656ee1161016f578063792921671161013e578063792921671461037157806384acd1bb14610384578063853d2c83146103b85780638a261c67146103cb57600080fd5b8063459656ee146102eb578063472d35b914610300578063538ee295146103205780635c975abb1461034057600080fd5b80632fcb4f04116101ab5780632fcb4f041461024857806332ad465f146102685780633f46e914146102a0578063452a9320146102b357600080fd5b8063078eab72146101dd5780631604b215146101f25780631b8789111461021257600080fd5b366101d857005b600080fd5b6101f06101eb36600461551d565b6106be565b005b3480156101fe57600080fd5b506101f061020d36600461539f565b610da6565b34801561021e57600080fd5b5061023261022d36600461539f565b61112d565b60405161023f9190615b57565b60405180910390f35b34801561025457600080fd5b506101f0610263366004615226565b6113bd565b34801561027457600080fd5b5061028861028336600461529f565b611409565b6040516001600160401b03909116815260200161023f565b6101f06102ae3660046155d9565b611744565b3480156102bf57600080fd5b506002546102d3906001600160a01b031681565b6040516001600160a01b03909116815260200161023f565b3480156102f757600080fd5b506101f0611c57565b34801561030c57600080fd5b506101f061031b366004615226565b611ca5565b34801561032c57600080fd5b506101f061033b36600461593b565b611cf1565b34801561034c57600080fd5b5060035461036190600160a01b900460ff1681565b604051901515815260200161023f565b61028861037f3660046158be565b611d3b565b34801561039057600080fd5b506102d37f00000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b81565b6102886103c6366004615431565b611f5a565b3480156103d757600080fd5b506103ff7f000000000000000000000000000000000000000000000000000000000000000181565b60405161ffff909116815260200161023f565b34801561041e57600080fd5b506104467f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff909116815260200161023f565b6102886104693660046152fa565b612383565b6101f061047c36600461549a565b612717565b34801561048d57600080fd5b506102d37f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af315581565b6101f06104c33660046156c2565b612d6c565b3480156104d457600080fd5b50600354600160a01b900460ff16610361565b3480156104f357600080fd5b506101f0610502366004615873565b6133d9565b34801561051357600080fd5b506101f0610522366004615367565b61348f565b34801561053357600080fd5b506001546102d3906001600160a01b031681565b34801561055357600080fd5b506101f06105623660046153d1565b6134d7565b34801561057357600080fd5b5061059b7f75233cdd3dab6c9f3134860c2b2443e80072b0880a3405b2bd87234f024711bc81565b60405190815260200161023f565b3480156105b557600080fd5b506001546105ca90600160a01b900460ff1681565b60405160ff909116815260200161023f565b3480156105e857600080fd5b506106346105f7366004615903565b60046020526000908152604090208054600182015460029092015490916001600160401b03811691600160401b9091046001600160a01b03169084565b604080519485526001600160401b0390931660208501526001600160a01b0390911691830191909152606082015260800161023f565b34801561067657600080fd5b506101f061068536600461525e565b613a5e565b34801561069657600080fd5b5061059b7f320a277b216ad7630fcdeec95878d2261ef01b423d48cea81ea808d7984a224681565b6106c6613a9c565b60008060007f00000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b6001600160a01b031663c0fd8bde876040518263ffffffff1660e01b81526004016107179190615aed565b60006040518083038186803b15801561072f57600080fd5b505afa158015610743573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261076b91908101906156f8565b92509250925081819061079a5760405162461bcd60e51b81526004016107919190615aed565b60405180910390fd5b50606083015161ffff166001146107eb5760405162461bcd60e51b815260206004820152601560248201527434b73b30b634b21032b6b4ba3a32b91031b430b4b760591b6044820152606401610791565b7f320a277b216ad7630fcdeec95878d2261ef01b423d48cea81ea808d7984a22468360800151146108575760405162461bcd60e51b815260206004820152601660248201527534b73b30b634b21039b7b630b7309032b6b4ba3a32b960511b6044820152606401610791565b60006108668460e0015161112d565b9050428161016001516001600160401b031610156108b85760405162461bcd60e51b815260206004820152600f60248201526e191958591b1a5b99481c185cdcd959608a1b6044820152606401610791565b6108c58160800151613af6565b6001600160a01b0316336001600160a01b0316146109165760405162461bcd60e51b815260206004820152600e60248201526d34b73b30b634b210323934bb32b960911b6044820152606401610791565b60006109238a6004613b4a565b905060006109328b600c613bad565b905060006109418c6078613c0a565b9050836101a0015163ffffffff168363ffffffff16146109995760405162461bcd60e51b815260206004820152601360248201527234b73b30b634b21031b1ba38103237b6b0b4b760691b6044820152606401610791565b836101c001516001600160401b0316826001600160401b0316146109f45760405162461bcd60e51b8152602060048201526012602482015271696e76616c69642063637470206e6f6e636560701b6044820152606401610791565b600080610a038e8e8786613c68565b61018088015191935091506001600160401b031615610aad5761018086015160405163a9059cbb60e01b81523360048201526001600160401b0390911660248201526001600160a01b0383169063a9059cbb90604401602060405180830381600087803b158015610a7357600080fd5b505af1158015610a87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aab9190615383565b505b6000610abc8760a00151613af6565b9050610ae2838d8961018001516001600160401b031685610add9190615ebe565b613fc8565b60006001600160a01b038216610af9575047610b73565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a082319060240160206040518083038186803b158015610b3857600080fd5b505afa158015610b4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b70919061585b565b90505b6000808e6001600160a01b031660008f604051610b909190615aa7565b60006040518083038185875af1925050503d8060008114610bcd576040519150601f19603f3d011682016040523d82523d6000602084013e610bd2565b606091505b5091509150818190610bf75760405162461bcd60e51b81526004016107919190615aed565b506001600160a01b038416610c1757610c108347615ebe565b9250610c9d565b6040516370a0823160e01b815230600482015283906001600160a01b038616906370a082319060240160206040518083038186803b158015610c5857600080fd5b505afa158015610c6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c90919061585b565b610c9a9190615ebe565b92505b60006001600160a01b038516610cb557506012610cc1565b610cbe85614081565b90505b6000610cda8c60c001516001600160401b03168361411c565b905080851015610d2c5760405162461bcd60e51b815260206004820152601760248201527f696e73756666696369656e7420616d6f756e74206f75740000000000000000006044820152606401610791565b610d378c8787614154565b6040805163ffffffff8d1681526001600160401b038c1660208201529081018690527fcc5626df3b699006387b64eca775dbdfecd5ae542e2d6ab22923082e1320dfcb9060600160405180910390a1505050505050505050505050505050610d9f6001600055565b5050505050565b610dae613a9c565b60008060007f00000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b6001600160a01b031663c0fd8bde856040518263ffffffff1660e01b8152600401610dff9190615aed565b60006040518083038186803b158015610e1757600080fd5b505afa158015610e2b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e5391908101906156f8565b925092509250818190610e795760405162461bcd60e51b81526004016107919190615aed565b50606083015161ffff1660011415610efc577f75233cdd3dab6c9f3134860c2b2443e80072b0880a3405b2bd87234f024711bc836080015114610ef75760405162461bcd60e51b815260206004820152601660248201527534b73b30b634b21039b7b630b7309032b6b4ba3a32b960511b6044820152606401610791565b610f5f565b306001600160a01b0316610f138460800151613af6565b6001600160a01b031614610f5f5760405162461bcd60e51b815260206004820152601360248201527234b73b30b634b21032bb369032b6b4ba3a32b960691b6044820152606401610791565b6000610f6e8460e001516144ca565b805190915060ff16600414610f9657604051634a7f394f60e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff16816060015163ffffffff1614610fe6576040516375893cc160e11b815260040160405180910390fd5b6040818101516001600160401b0390811660009081526004602090815290839020835160808101855281548152600182015493841692810192909252600160401b9092046001600160a01b03169281019290925260020154606082018190526110825760405162461bcd60e51b815260206004820152600e60248201526d199959481b9bdd081b1bd8dad95960921b6044820152606401610791565b80602001516001600160401b03168260a001516001600160401b031610156110bd57604051636e51edcd60e11b815260040160405180910390fd5b6110e76110cd8360800151613af6565b606083015160408401516001600160a01b03169190614592565b506040908101516001600160401b0316600090815260046020529081208181556001810180546001600160e01b0319169055600201555061112a91506144c39050565b50565b604080516101e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c08101829052906111b083826145f5565b60ff1682526111c0600182615d4e565b825190915060ff166002146111e857604051634a7f394f60e01b815260040160405180910390fd5b6111f283826145f5565b60ff166020830152611205600182615d4e565b90506112118382614651565b61ffff166040830152611225600282615d4e565b90506112318382613c0a565b6060830152611241602082615d4e565b905061124d8382613c0a565b608083015261125d602082615d4e565b90506112698382613c0a565b60a0830152611279602082615d4e565b90506112858382613bad565b6001600160401b031660c083015261129e600882615d4e565b90506112aa8382613bad565b6001600160401b031660e08301526112c3600882615d4e565b90506112cf8382613c0a565b6101008301526112e0602082615d4e565b90506112ec83826145f5565b60ff16610120830152611300600182615d4e565b905061130c83826145f5565b60ff16610140830152611320600182615d4e565b905061132c8382613bad565b6001600160401b0316610160830152611346600882615d4e565b90506113528382613bad565b6001600160401b031661018083015261136c600882615d4e565b90506113788382613b4a565b63ffffffff166101a083015261138f600482615d4e565b905061139b8382613bad565b6001600160401b03166101c08301526113b5600882615d4e565b905050919050565b6002546001600160a01b031633146113e7576040516282b42960e81b815260040160405180910390fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6000611413613a9c565b600354600160a01b900460ff161561143e576040516313d0ff5960e31b815260040160405180910390fd5b815163ffffffff1660051415611467576040516375893cc160e11b815260040160405180910390fd5b600083116114a95760405162461bcd60e51b815260206004820152600f60248201526e7a65726f2072656465656d2066656560881b6044820152606401610791565b6040516370a0823160e01b81523060048201526000906001600160a01b038816906370a082319060240160206040518083038186803b1580156114eb57600080fd5b505afa1580156114ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611523919061585b565b905061153a6001600160a01b0388163330896146ae565b6040516370a0823160e01b815230600482015281906001600160a01b038916906370a082319060240160206040518083038186803b15801561157b57600080fd5b505afa15801561158f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115b3919061585b565b6115bd9190615ebe565b90506115ee877f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155610add8785615ebe565b6001600160a01b037f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af31551663f856ddb66116278684615ebe565b8551602087015160408089015190516001600160e01b031960e087901b168152611658949392918e91600401615c58565b602060405180830381600087803b15801561167257600080fd5b505af1158015611686573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116aa919061591f565b6040805160808101825260208087015182526001600160401b03808a168284019081526001600160a01b03808e16858701908152606086018c815284891660009081526004909652969094209451855590516001850180549451909216600160401b026001600160e01b03199094169216919091179190911790559051600290910155915061173b90506001600055565b95945050505050565b61174c613a9c565b60008060007f00000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b6001600160a01b031663c0fd8bde896040518263ffffffff1660e01b815260040161179d9190615aed565b60006040518083038186803b1580156117b557600080fd5b505afa1580156117c9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117f191908101906156f8565b9250925092508181906118175760405162461bcd60e51b81526004016107919190615aed565b507f75233cdd3dab6c9f3134860c2b2443e80072b0880a3405b2bd87234f024711bc83608001511415801561186a5750306001600160a01b031661185e8460800151613af6565b6001600160a01b031614155b1561188857604051632c6bb35560e01b815260040160405180910390fd5b6000611895886004613b4a565b905060006118a489600c613bad565b905060006118b38a6078613c0a565b90506000806118c48c8c8786613c68565b915091506000611a1884838d8d604080516101c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a0810191909152604051806101c0016040528083600001518152602001836020015161ffff168152602001868152602001856001600160401b0316815260200184606001518152602001846080015161ffff1681526020018460a0015181526020018460c001516001600160401b0316815260200184604001516001600160401b031681526020018461010001516001600160401b031681526020018460e001516001600160401b03168152602001846101200151815260200184610140015160ff168152602001836040015160ff168152509050949350505050565b90506000611a25826146ec565b9050611a548688604051602001611a3d929190615ac3565b60408051601f19818403018152919052829061476d565b90506000818051906020012090506000611a718c60e001516147ea565b805190915060ff16600114611a9957604051634a7f394f60e01b815260040160405180910390fd5b80604001518214611abd5760405163af61069360e01b815260040160405180910390fd5b428461014001516001600160401b031610611b105760405162461bcd60e51b8152602060048201526013602482015272191958591b1a5b99481b9bdd081c185cdcd959606a1b6044820152606401610791565b6000611b2b8561010001516001600160401b0316601261411c565b9050803414611b4d57604051636e51edcd60e11b815260040160405180910390fd5b6000611b5c8660800151613af6565b90508115611b9c576040516001600160a01b0382169083156108fc029084906000818181858888f19350505050158015611b9a573d6000803e3d6000fd5b505b610120860151611bc1906001600160a01b038a169033906001600160401b0316614592565b611bf0818761012001516001600160401b031689611bdf9190615ebe565b6001600160a01b038b169190614592565b6040805163ffffffff8d1681526001600160401b038c1660208201529081018890527f4f7c61703b83b54f1af0ca9b67d73dc13cc2e91262faf81b0a4927cbce9242399060600160405180910390a15050505050505050505050505050610d9f6001600055565b6003546001600160a01b03163314611c81576040516282b42960e81b815260040160405180910390fd5b600354600280546001600160a01b0319166001600160a01b03909216919091179055565b6002546001600160a01b03163314611ccf576040516282b42960e81b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b03163314611d1b576040516282b42960e81b815260040160405180910390fd5b6001805460ff909216600160a01b0260ff60a01b19909216919091179055565b6000611d45613a9c565b60007f00000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b6001600160a01b0316631a90a2196040518163ffffffff1660e01b815260040160206040518083038186803b158015611da057600080fd5b505afa158015611db4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd8919061585b565b9050611de384613af6565b6001600160a01b03166108fc611df98334615ebe565b6040518115909202916000818181858888f19350505050158015611e21573d6000803e3d6000fd5b506040805160e0810190915260009080600560ff1681526001602082015263ffffffff808a166040830152881660608201526080810186905260a001611e71611e6a8534615ebe565b601261484c565b6001600160401b0316815260200186905290506000611e8f8261487a565b6001546040516358cd21bf60e11b81529192507f00000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b6001600160a01b03169163b19a437e918691611ef1916000918791600160a01b900460ff1690600401615b25565b6020604051808303818588803b158015611f0a57600080fd5b505af1158015611f1e573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611f43919061591f565b9350505050611f526001600055565b949350505050565b6000611f64613a9c565b6000611f71856004613b4a565b90506000611f8086600c613bad565b90506000611f97611f92886054613c0a565b613af6565b90506001600160a01b0381163014611fe25760405162461bcd60e51b815260206004820152600e60248201526d34b73b30b634b21031b0b63632b960911b6044820152606401610791565b6000611ff2611f92896098613c0a565b90506001600160a01b0381163014156120465760405162461bcd60e51b81526020600482015260166024820152751a5b9d985b1a59081b5a5b9d081c9958da5c1a595b9d60521b6044820152606401610791565b60007f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af31556001600160a01b0316632c1219216040518163ffffffff1660e01b815260040160206040518083038186803b1580156120a157600080fd5b505afa1580156120b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d99190615242565b6001600160a01b03166357ecfd288a8a6040518363ffffffff1660e01b8152600401612106929190615b00565b602060405180830381600087803b15801561212057600080fd5b505af1158015612134573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121589190615383565b9050806121785760405163605c687360e01b815260040160405180910390fd5b60007f00000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b6001600160a01b0316631a90a2196040518163ffffffff1660e01b815260040160206040518083038186803b1580156121d357600080fd5b505afa1580156121e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220b919061585b565b90506001600160a01b0383166108fc6122248334615ebe565b6040518115909202916000818181858888f1935050505015801561224c573d6000803e3d6000fd5b506040805160c0810190915260009080600460ff168152600160208201526001600160401b038816604082015263ffffffff89166060820152608081018b905260a00161229c611e6a8534615ebe565b6001600160401b03169052905060006122b482614910565b6001546040516358cd21bf60e11b81529192507f00000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b6001600160a01b03169163b19a437e918691612316916000918791600160a01b900460ff1690600401615b25565b6020604051808303818588803b15801561232f57600080fd5b505af1158015612343573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612368919061591f565b9850505050505050505061237c6001600055565b9392505050565b600061238d613a9c565b600354600160a01b900460ff16156123b8576040516313d0ff5960e31b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038916906370a082319060240160206040518083038186803b1580156123fa57600080fd5b505afa15801561240e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612432919061585b565b90506124496001600160a01b03891633308a6146ae565b6040516370a0823160e01b815230600482015281906001600160a01b038a16906370a082319060240160206040518083038186803b15801561248a57600080fd5b505afa15801561249e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124c2919061585b565b6124cc9190615ebe565b90506124f9887f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af315583613fc8565b60007f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af31556001600160a01b031663f856ddb683866000015187602001518d89604001516040518663ffffffff1660e01b815260040161255b959493929190615c58565b602060405180830381600087803b15801561257557600080fd5b505af1158015612589573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ad919061591f565b905060006040518060e00160405280600360058111156125dd57634e487b7160e01b600052602160045260246000fd5b60ff168152600160208201526001600160401b03808516604083015263ffffffff7f00000000000000000000000000000000000000000000000000000000000000001660608301526080820189905289811660a08301528a1660c0909101529050600061264982614998565b6001546040516358cd21bf60e11b81529192507f00000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b6001600160a01b03169163b19a437e9134916126ab916000918791600160a01b900460ff1690600401615b25565b6020604051808303818588803b1580156126c457600080fd5b505af11580156126d8573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906126fd919061591f565b94505050505061270d6001600055565b9695505050505050565b61271f613a9c565b60008060007f00000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b6001600160a01b031663c0fd8bde856040518263ffffffff1660e01b81526004016127709190615aed565b60006040518083038186803b15801561278857600080fd5b505afa15801561279c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526127c491908101906156f8565b9250925092508181906127ea5760405162461bcd60e51b81526004016107919190615aed565b507f75233cdd3dab6c9f3134860c2b2443e80072b0880a3405b2bd87234f024711bc83608001511415801561283d5750306001600160a01b03166128318460800151613af6565b6001600160a01b031614155b1561285b57604051632c6bb35560e01b815260040160405180910390fd5b600061286a8460e00151614a2e565b805190915060ff1660031461289257604051634a7f394f60e01b815260040160405180910390fd5b60006128ac8260a001516001600160401b0316601261411c565b90508034146128ce57604051636e51edcd60e11b815260040160405180910390fd5b60006128db896004613b4a565b905060006128ea8a600c613bad565b905060006128f98b6078613c0a565b9050846060015163ffffffff168363ffffffff161461292b576040516375893cc160e11b815260040160405180910390fd5b84604001516001600160401b0316826001600160401b03161461296157604051633ab3447f60e11b815260040160405180910390fd5b60007f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af31556001600160a01b031663cb75c11c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156129bc57600080fd5b505afa1580156129d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129f49190615242565b604051633c502b2f60e11b815263ffffffff86166004820152602481018490526001600160a01b0391909116906378a0565e9060440160206040518083038186803b158015612a4257600080fd5b505afa158015612a56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7a9190615242565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b158015612abf57600080fd5b505afa158015612ad3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612af7919061585b565b905060007f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af31556001600160a01b0316632c1219216040518163ffffffff1660e01b815260040160206040518083038186803b158015612b5457600080fd5b505afa158015612b68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b8c9190615242565b6001600160a01b03166357ecfd288f8f6040518363ffffffff1660e01b8152600401612bb9929190615b00565b602060405180830381600087803b158015612bd357600080fd5b505af1158015612be7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c0b9190615383565b905080612c2b5760405163605c687360e01b815260040160405180910390fd5b6040516370a0823160e01b815230600482015282906001600160a01b038516906370a082319060240160206040518083038186803b158015612c6c57600080fd5b505afa158015612c80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ca4919061585b565b612cae9190615ebe565b9150612cdb338960c001516001600160401b0316856001600160a01b03166145929092919063ffffffff16565b6000612cea8960800151613af6565b9050612d1a818a60c001516001600160401b031685612d099190615ebe565b6001600160a01b0387169190614592565b6040516001600160a01b0382169089156108fc02908a906000818181858888f19350505050158015612d50573d6000803e3d6000fd5b50505050505050505050505050612d676001600055565b505050565b612d74613a9c565b600354600160a01b900460ff1615612d9f576040516313d0ff5960e31b815260040160405180910390fd5b60a0820151158015612dbe5750600082604001516001600160401b0316115b15612ddc57604051636e51edcd60e11b815260040160405180910390fd5b60208201518251612dfc916001600160a01b0390911690339030906146ae565b612e2f82600001517f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af31558460200151613fc8565b60208083015182519183015184516040808601519051637c2b6edb60e11b81526000956001600160a01b037f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155169563f856ddb695612e969591949293909290600401615c58565b602060405180830381600087803b158015612eb057600080fd5b505af1158015612ec4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ee8919061591f565b9050603283610140015160ff161115612f3a5760405162461bcd60e51b8152602060048201526014602482015273696e76616c69642072656665727265722062707360601b6044820152606401610791565b6001546020840151845160a0860151608087015161014088015160405162bec7bb60e21b81526001600160401b0390951660048601526001600160a01b039384166024860152604485019290925261ffff16606484015260ff16608483015260009216906302fb1eec9060a40160206040518083038186803b158015612fbf57600080fd5b505afa158015612fd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ff79190615957565b905060328160ff1611156130445760405162461bcd60e51b8152602060048201526014602482015273696e76616c69642070726f746f636f6c2062707360601b6044820152606401610791565b6000604051806101c00160405280336001600160a01b031660001b81526020017f00000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b6001600160a01b0316639a8a05926040518163ffffffff1660e01b815260040160206040518083038186803b1580156130bd57600080fd5b505afa1580156130d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130f5919061583f565b61ffff16815260200186600001516001600160a01b031660001b815260200186602001516001600160401b0316815260200186606001518152602001866080015161ffff1681526020018660a0015181526020018660c001516001600160401b0316815260200186604001516001600160401b031681526020018661010001516001600160401b031681526020018660e001516001600160401b03168152602001866101200151815260200186610140015160ff1681526020018360ff16815250905060006131c3826146ec565b90506132db847f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af31556001600160a01b0316632c1219216040518163ffffffff1660e01b815260040160206040518083038186803b15801561322257600080fd5b505afa158015613236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061325a9190615242565b6001600160a01b0316638d3638f46040518163ffffffff1660e01b815260040160206040518083038186803b15801561329257600080fd5b505afa1580156132a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132ca91906158a2565b604051602001611a3d929190615ac3565b8051602080830191909120604080516060810182526001808252938101939093528201819052919250600061330f82614b05565b6001546040516358cd21bf60e11b81529192507f00000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b6001600160a01b03169163b19a437e913491613371916000918791600160a01b900460ff1690600401615b25565b6020604051808303818588803b15801561338a57600080fd5b505af115801561339e573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906133c3919061591f565b50505050505050506133d56001600055565b5050565b6002546001600160a01b03163314613403576040516282b42960e81b815260040160405180910390fd5b6001600160a01b0381166134595760405162461bcd60e51b815260206004820152601c60248201527f7472616e7366657220746f20746865207a65726f2061646472657373000000006044820152606401610791565b6040516001600160a01b0382169083156108fc029084906000818181858888f19350505050158015612d67573d6000803e3d6000fd5b6002546001600160a01b031633146134b9576040516282b42960e81b815260040160405180910390fd5b60038054911515600160a01b0260ff60a01b19909216919091179055565b6134df613a9c565b60008060007f00000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b6001600160a01b031663c0fd8bde866040518263ffffffff1660e01b81526004016135309190615aed565b60006040518083038186803b15801561354857600080fd5b505afa15801561355c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261358491908101906156f8565b9250925092508181906135aa5760405162461bcd60e51b81526004016107919190615aed565b507f75233cdd3dab6c9f3134860c2b2443e80072b0880a3405b2bd87234f024711bc8360800151141580156135fd5750306001600160a01b03166135f18460800151613af6565b6001600160a01b031614155b1561361b57604051632c6bb35560e01b815260040160405180910390fd5b600061362a8460e001516144ca565b805190915060ff1660051461365257604051634a7f394f60e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff16816060015163ffffffff16146136a2576040516375893cc160e11b815260040160405180910390fd5b6040818101516001600160401b0390811660009081526004602090815290839020835160808101855281548152600182015493841692810192909252600160401b9092046001600160a01b031692810192909252600201546060820181905261373e5760405162461bcd60e51b815260206004820152600e60248201526d199959481b9bdd081b1bd8dad95960921b6044820152606401610791565b80602001516001600160401b03168260a001516001600160401b03161061379c5760405162461bcd60e51b815260206004820152601260248201527119d85cc81dd85cc81cdd59999a58da595b9d60721b6044820152606401610791565b60008060007f00000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b6001600160a01b031663c0fd8bde8a6040518263ffffffff1660e01b81526004016137ed9190615aed565b60006040518083038186803b15801561380557600080fd5b505afa158015613819573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261384191908101906156f8565b9250925092508181906138675760405162461bcd60e51b81526004016107919190615aed565b507f75233cdd3dab6c9f3134860c2b2443e80072b0880a3405b2bd87234f024711bc8360800151141580156138ba5750306001600160a01b03166138ae8460800151613af6565b6001600160a01b031614155b156138d857604051632c6bb35560e01b815260040160405180910390fd5b60006138e78960e00151614b4d565b855160c0820151919250146139325760405162461bcd60e51b815260206004820152601160248201527034b73b30b634b2103232b9ba1030b2323960791b6044820152606401610791565b85604001516001600160401b031681604001516001600160401b03161461396c57604051633ab3447f60e11b815260040160405180910390fd5b856060015163ffffffff16816060015163ffffffff16146139a0576040516375893cc160e11b815260040160405180910390fd5b84602001516001600160401b03168660a001518260a001516139c29190615d66565b6001600160401b031610156139ea57604051636e51edcd60e11b815260040160405180910390fd5b613a146139fa8260800151613af6565b606087015160408801516001600160a01b03169190614592565b5050506040928301516001600160401b0316600090815260046020529283208381556001810180546001600160e01b031916905560020192909255506133d593506144c392505050565b6002546001600160a01b03163314613a88576040516282b42960e81b815260040160405180910390fd5b612d676001600160a01b0384168284614592565b60026000541415613aef5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610791565b6002600055565b60006001600160a01b0319821615613b465760405162461bcd60e51b8152602060048201526013602482015272696e76616c69642045564d206164647265737360681b6044820152606401610791565b5090565b6000613b57826004615d4e565b83511015613b9e5760405162461bcd60e51b8152602060048201526014602482015273746f55696e7433325f6f75744f66426f756e647360601b6044820152606401610791565b50818101600401515b92915050565b6000613bba826008615d4e565b83511015613c015760405162461bcd60e51b8152602060048201526014602482015273746f55696e7436345f6f75744f66426f756e647360601b6044820152606401610791565b50016008015190565b6000613c17826020615d4e565b83511015613c5f5760405162461bcd60e51b8152602060048201526015602482015274746f427974657333325f6f75744f66426f756e647360581b6044820152606401610791565b50016020015190565b60008060007f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af31556001600160a01b031663cb75c11c6040518163ffffffff1660e01b815260040160206040518083038186803b158015613cc657600080fd5b505afa158015613cda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cfe9190615242565b604051633c502b2f60e11b815263ffffffff87166004820152602481018690526001600160a01b0391909116906378a0565e9060440160206040518083038186803b158015613d4c57600080fd5b505afa158015613d60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d849190615242565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b158015613dc957600080fd5b505afa158015613ddd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e01919061585b565b905060007f000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af31556001600160a01b0316632c1219216040518163ffffffff1660e01b815260040160206040518083038186803b158015613e5e57600080fd5b505afa158015613e72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e969190615242565b6001600160a01b03166357ecfd288a8a6040518363ffffffff1660e01b8152600401613ec3929190615b00565b602060405180830381600087803b158015613edd57600080fd5b505af1158015613ef1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f159190615383565b905080613f355760405163605c687360e01b815260040160405180910390fd5b6040516370a0823160e01b815230600482015282906001600160a01b038516906370a082319060240160206040518083038186803b158015613f7657600080fd5b505afa158015613f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fae919061585b565b613fb89190615ebe565b9299929850919650505050505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152849160009183169063dd62ed3e9060440160206040518083038186803b15801561401457600080fd5b505afa158015614028573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061404c919061585b565b905082811015610d9f5761406b6001600160a01b038316856000614c24565b610d9f6001600160a01b03831685600019614c24565b60408051600481526024810182526020810180516001600160e01b031663313ce56760e01b179052905160009182916001600160a01b038516916140c491615aa7565b600060405180830381855afa9150503d80600081146140ff576040519150601f19603f3d011682016040523d82523d6000602084013e614104565b606091505b509150508080602001905181019061237c9190615957565b600060088260ff16111561414d57614135600883615ed5565b61414090600a615df4565b61414a9084615e9f565b92505b5090919050565b6000614164846101000151613af6565b905060006001600160a01b03821615801590614187575061012085015160ff1615155b156141b05761271085610120015160ff16846141a39190615e9f565b6141ad9190615d91565b90505b600085610140015160ff166000146141e65761271086610140015160ff16856141d99190615e9f565b6141e39190615d91565b90505b60006141f58760600151613af6565b90506001600160a01b038616614359578215614243576040516001600160a01b0385169084156108fc029085906000818181858888f19350505050158015614241573d6000803e3d6000fd5b505b811561430957600160009054906101000a90046001600160a01b03166001600160a01b031663c415b95c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561429757600080fd5b505afa1580156142ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142cf9190615242565b6001600160a01b03166108fc839081150290604051600060405180830381858888f19350505050158015614307573d6000803e3d6000fd5b505b6001600160a01b0381166108fc836143218689615ebe565b61432b9190615ebe565b6040518115909202916000818181858888f19350505050158015614353573d6000803e3d6000fd5b506144ba565b60e08701516001600160401b0316156143e15760006143868860e001516001600160401b0316601261411c565b90508034146143a857604051636e51edcd60e11b815260040160405180910390fd5b6040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156143de573d6000803e3d6000fd5b50505b82156143fb576143fb6001600160a01b0387168585614592565b811561449057600154604080516331056e5760e21b81529051614490926001600160a01b03169163c415b95c916004808301926020929190829003018186803b15801561444757600080fd5b505afa15801561445b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061447f9190615242565b6001600160a01b0388169084614592565b6144ba818361449f8689615ebe565b6144a99190615ebe565b6001600160a01b0389169190614592565b50505050505050565b6001600055565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091526040805160c08101909152806145138460006145f5565b60ff1681526020016145268460016145f5565b60ff168152602001614539846002613bad565b6001600160401b0316815260200161455284600a613b4a565b63ffffffff168152602001614571600e85613c0a90919063ffffffff16565b815260200161458184602e613bad565b6001600160401b0316905292915050565b6040516001600160a01b038316602482015260448101829052612d6790849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614d48565b6000614602826001615d4e565b835110156146485760405162461bcd60e51b8152602060048201526013602482015272746f55696e74385f6f75744f66426f756e647360681b6044820152606401610791565b50016001015190565b600061465e826002615d4e565b835110156146a55760405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b6044820152606401610791565b50016002015190565b6040516001600160a01b03808516602483015283166044820152606481018290526146e69085906323b872dd60e01b906084016145be565b50505050565b6060816000015182602001518360400151846060015185608001518660a001518760c001518860e001518961010001518a61012001518b61014001518c61016001518d61018001518e6101a001516040516020016147579e9d9c9b9a9998979695949392919061599f565b6040516020818303038152906040529050919050565b6060806040519050835180825260208201818101602087015b8183101561479e578051835260209283019201614786565b50855184518101855292509050808201602086015b818310156147cb5780518352602092830192016147b3565b508651929092011591909101601f01601f191660405250905092915050565b604080516060810182526000808252602082018190529181019190915260408051606081019091528061481e8460006145f5565b60ff1681526020016148318460016145f5565b60ff168152602001614844846002613c0a565b905292915050565b600060088260ff16111561414d57614865600883615ed5565b61487090600a615df4565b61414a9084615d91565b8051602080830151604080850151606086810151608088015160a089015160c0808b015196516001600160f81b031960f89b8c1b81169a82019a909a529790991b90971660218701526001600160c01b031993881b841660228701526001600160e01b031960e09290921b91909116602a860152602e8501529390941b909316604e820152605681019290925290607601614757565b8051602080830151604080850151606080870151608088015160a0890151945160f898891b6001600160f81b0319908116988201989098529590971b909516602185015260c091821b6001600160c01b0319908116602286015260e09590951b6001600160e01b031916602a850152602e8401959095521b909116604e820152605601614757565b8051602080830151604080850151606086810151608088015160a089015160c0808b015196516001600160f81b031960f89b8c1b81169a82019a909a529790991b90971660218701526001600160c01b031993881b841660228701526001600160e01b031960e09290921b91909116602a860152602e85015293851b8116604e840152931b909216605683015290605e01614757565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c08101919091526040805160e0810190915280614a7e8460006145f5565b60ff168152602001614a918460016145f5565b60ff168152602001614aa4846002613bad565b6001600160401b03168152602001614abd84600a613b4a565b63ffffffff168152602001614adc600e85613c0a90919063ffffffff16565b8152602001614aec84602e613bad565b6001600160401b03168152602001614581846036613bad565b60608160000151826020015183604001516040516020016147579392919060f893841b6001600160f81b031990811682529290931b9091166001830152600282015260220190565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c08101919091526040805160e0810190915280614b9d8460006145f5565b60ff168152602001614bb08460016145f5565b60ff168152602001614bc3846002613bad565b6001600160401b03168152602001614bdc84600a613b4a565b63ffffffff168152602001614bfb600e85613c0a90919063ffffffff16565b8152602001614c0b84602e613bad565b6001600160401b03168152602001614844846036613c0a565b801580614cad5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015614c7357600080fd5b505afa158015614c87573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614cab919061585b565b155b614d185760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610791565b6040516001600160a01b038316602482015260448101829052612d6790849063095ea7b360e01b906064016145be565b6000614d9d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614e1d9092919063ffffffff16565b9050805160001480614dbe575080806020019051810190614dbe9190615383565b612d675760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610791565b6060611f52848460008585600080866001600160a01b03168587604051614e449190615aa7565b60006040518083038185875af1925050503d8060008114614e81576040519150601f19603f3d011682016040523d82523d6000602084013e614e86565b606091505b5091509150614e9787838387614ea2565b979650505050505050565b60608315614f0e578251614f07576001600160a01b0385163b614f075760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610791565b5081611f52565b611f528383815115614f235781518083602001fd5b8060405162461bcd60e51b81526004016107919190615aed565b8035614f4881615f50565b919050565b600082601f830112614f5d578081fd5b815160206001600160401b03821115614f7857614f78615f3a565b614f86818360051b01615cf7565b80838252828201915082860187848660071b8901011115614fa5578586fd5b855b8581101561500c57608080838b031215614fbf578788fd5b614fc7615c8a565b835181528684015187820152604080850151614fe281615faa565b90820152606084810151614ff581615faa565b908201528552938501939190910190600101614fa7565b5090979650505050505050565b8051614f4881615f65565b600082601f830112615034578081fd5b813561504761504282615d27565b615cf7565b81815284602083860101111561505b578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112615085578081fd5b815161509361504282615d27565b8181528460208386010111156150a7578283fd5b611f52826020830160208701615ef8565b6000606082840312156150c9578081fd5b604051606081018181106001600160401b03821117156150eb576150eb615f3a565b60405290508082356150fc81615f83565b8082525060208301356020820152604083013560408201525092915050565b6000610160828403121561512d578081fd5b615135615cb2565b905061514082614f3d565b815260208201356020820152615158604083016151fa565b604082015260608201356060820152615173608083016151d9565b608082015260a082013560a082015261518e60c083016151fa565b60c082015261519f60e083016151fa565b60e08201526101006151b28184016151fa565b9082015261012082810135908201526101406151cf818401615210565b9082015292915050565b8035614f4881615f73565b8051614f4881615f73565b8051614f4881615f83565b8035614f4881615f95565b8051614f4881615f95565b8035614f4881615faa565b8051614f4881615faa565b600060208284031215615237578081fd5b813561237c81615f50565b600060208284031215615253578081fd5b815161237c81615f50565b600080600060608486031215615272578182fd5b833561527d81615f50565b925060208401359150604084013561529481615f50565b809150509250925092565b600080600080600060e086880312156152b6578283fd5b85356152c181615f50565b94506020860135935060408601356152d881615f95565b9250606086013591506152ee87608088016150b8565b90509295509295909350565b6000806000806000806101008789031215615313578384fd5b863561531e81615f50565b955060208701359450604087013561533581615f95565b9350606087013561534581615f95565b92506080870135915061535b8860a089016150b8565b90509295509295509295565b600060208284031215615378578081fd5b813561237c81615f65565b600060208284031215615394578081fd5b815161237c81615f65565b6000602082840312156153b0578081fd5b81356001600160401b038111156153c5578182fd5b611f5284828501615024565b600080604083850312156153e3578182fd5b82356001600160401b03808211156153f9578384fd5b61540586838701615024565b9350602085013591508082111561541a578283fd5b5061542785828601615024565b9150509250929050565b600080600060608486031215615445578081fd5b83356001600160401b038082111561545b578283fd5b61546787838801615024565b9450602086013591508082111561547c578283fd5b5061548986828701615024565b925050604084013590509250925092565b6000806000606084860312156154ae578081fd5b83356001600160401b03808211156154c4578283fd5b6154d087838801615024565b945060208601359150808211156154e5578283fd5b6154f187838801615024565b93506040860135915080821115615506578283fd5b5061551386828701615024565b9150509250925092565b600080600080600060a08688031215615534578283fd5b85356001600160401b038082111561554a578485fd5b61555689838a01615024565b9650602088013591508082111561556b578485fd5b61557789838a01615024565b9550604088013591508082111561558c578485fd5b61559889838a01615024565b9450606088013591506155aa82615f50565b909250608087013590808211156155bf578283fd5b506155cc88828901615024565b9150509295509295909350565b60008060008060008587036102208112156155f2578384fd5b86356001600160401b0380821115615608578586fd5b6156148a838b01615024565b97506020890135915080821115615629578586fd5b6156358a838b01615024565b9650604089013591508082111561564a578586fd5b5061565789828a01615024565b945050615667886060890161511b565b925060606101bf198201121561567b578182fd5b50615684615cd5565b6101c087013581526101e087013561569b81615f73565b60208201526102008701356156af81615faa565b6040820152949793965091945092919050565b6000806101c083850312156156d5578182fd5b6156df848461511b565b91506156ef8461016085016150b8565b90509250929050565b60008060006060848603121561570c578081fd5b83516001600160401b0380821115615722578283fd5b908501906101608288031215615736578283fd5b61573e615cb2565b6157478361521b565b8152615755602084016151ef565b6020820152615766604084016151ef565b6040820152615777606084016151e4565b60608201526080830151608082015261579260a08401615205565b60a08201526157a360c0840161521b565b60c082015260e0830151828111156157b9578485fd5b6157c589828601615075565b60e0830152506101006157d98185016151ef565b9082015261012083810151838111156157f0578586fd5b6157fc8a828701614f4d565b91830191909152506101408381015190820152945061581d60208701615019565b93506040860151915080821115615832578283fd5b5061551386828701615075565b600060208284031215615850578081fd5b815161237c81615f73565b60006020828403121561586c578081fd5b5051919050565b60008060408385031215615885578182fd5b82359150602083013561589781615f50565b809150509250929050565b6000602082840312156158b3578081fd5b815161237c81615f83565b600080600080608085870312156158d3578182fd5b84356158de81615f83565b935060208501356158ee81615f83565b93969395505050506040820135916060013590565b600060208284031215615914578081fd5b813561237c81615f95565b600060208284031215615930578081fd5b815161237c81615f95565b60006020828403121561594c578081fd5b813561237c81615faa565b600060208284031215615968578081fd5b815161237c81615faa565b6000815180845261598b816020860160208601615ef8565b601f01601f19169290920160200192915050565b8e815261ffff60f01b8e60f01b1660208201528c60228201526159d1604282018d60c01b6001600160c01b0319169052565b8a604a8201526159f0606a82018b60f01b6001600160f01b0319169052565b88606c820152615a0f608c82018960c01b6001600160c01b0319169052565b615a28609482018860c01b6001600160c01b0319169052565b615a41609c82018760c01b6001600160c01b0319169052565b615a5a60a482018660c01b6001600160c01b0319169052565b8360ac820152615a7960cc82018460f81b6001600160f81b0319169052565b615a9260cd82018360f81b6001600160f81b0319169052565b60ce019e9d5050505050505050505050505050565b60008251615ab9818460208701615ef8565b9190910192915050565b60c09290921b6001600160c01b031916825260e01b6001600160e01b0319166008820152600c0190565b60208152600061237c6020830184615973565b604081526000615b136040830185615973565b828103602084015261173b8185615973565b63ffffffff84168152606060208201526000615b446060830185615973565b905060ff83166040830152949350505050565b815160ff1681526101e081016020830151615b77602084018260ff169052565b506040830151615b8d604084018261ffff169052565b50606083015160608301526080830151608083015260a083015160a083015260c0830151615bc660c08401826001600160401b03169052565b5060e0830151615be160e08401826001600160401b03169052565b5061010083810151908301526101208084015160ff908116918401919091526101408085015190911690830152610160808401516001600160401b0390811691840191909152610180808501518216908401526101a08085015163ffffffff16908401526101c09384015116929091019190915290565b94855263ffffffff93909316602085015260408401919091526001600160a01b03166060830152608082015260a00190565b604051608081016001600160401b0381118282101715615cac57615cac615f3a565b60405290565b60405161016081016001600160401b0381118282101715615cac57615cac615f3a565b604051606081016001600160401b0381118282101715615cac57615cac615f3a565b604051601f8201601f191681016001600160401b0381118282101715615d1f57615d1f615f3a565b604052919050565b60006001600160401b03821115615d4057615d40615f3a565b50601f01601f191660200190565b60008219821115615d6157615d61615f24565b500190565b60006001600160401b03808316818516808303821115615d8857615d88615f24565b01949350505050565b600082615dac57634e487b7160e01b81526012600452602481fd5b500490565b600181815b80851115615dec578160001904821115615dd257615dd2615f24565b80851615615ddf57918102915b93841c9390800290615db6565b509250929050565b600061237c60ff841683600082615e0d57506001613ba7565b81615e1a57506000613ba7565b8160018114615e305760028114615e3a57615e56565b6001915050613ba7565b60ff841115615e4b57615e4b615f24565b50506001821b613ba7565b5060208310610133831016604e8410600b8410161715615e79575081810a613ba7565b615e838383615db1565b8060001904821115615e9757615e97615f24565b029392505050565b6000816000190483118215151615615eb957615eb9615f24565b500290565b600082821015615ed057615ed0615f24565b500390565b600060ff821660ff841680821015615eef57615eef615f24565b90039392505050565b60005b83811015615f13578181015183820152602001615efb565b838111156146e65750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461112a57600080fd5b801515811461112a57600080fd5b61ffff8116811461112a57600080fd5b63ffffffff8116811461112a57600080fd5b6001600160401b038116811461112a57600080fd5b60ff8116811461112a57600080fdfea2646970667358221220ced90ea25f6f664189f12f8a22a39ce4d8f647ced1e1c1cb900d58b7e591535d64736f6c63430008040033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af315500000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b000000000000000000000000d00d2a12b5f15992630c48e48d97a2b2f85713100000000000000000000000000000000000000000000000000000000000000001320a277b216ad7630fcdeec95878d2261ef01b423d48cea81ea808d7984a224675233cdd3dab6c9f3134860c2b2443e80072b0880a3405b2bd87234f024711bc0000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : _cctpTokenMessenger (address): 0xBd3fa81B58Ba92a82136038B25aDec7066af3155
Arg [1] : _wormhole (address): 0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B
Arg [2] : _feeManager (address): 0xD00D2A12b5F15992630C48e48D97a2B2F8571310
Arg [3] : _auctionChainId (uint16): 1
Arg [4] : _auctionAddr (bytes32): 0x320a277b216ad7630fcdeec95878d2261ef01b423d48cea81ea808d7984a2246
Arg [5] : _solanaEmitter (bytes32): 0x75233cdd3dab6c9f3134860c2b2443e80072b0880a3405b2bd87234f024711bc
Arg [6] : _consistencyLevel (uint8): 1
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155
Arg [1] : 00000000000000000000000098f3c9e6e3face36baad05fe09d375ef1464288b
Arg [2] : 000000000000000000000000d00d2a12b5f15992630c48e48d97a2b2f8571310
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [4] : 320a277b216ad7630fcdeec95878d2261ef01b423d48cea81ea808d7984a2246
Arg [5] : 75233cdd3dab6c9f3134860c2b2443e80072b0880a3405b2bd87234f024711bc
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000001
Loading...
Loading
Loading...
Loading
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.