Source Code
Latest 25 from a total of 13,439 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Redeem With Fee | 38642329 | 2 hrs ago | IN | 0 ETH | 0.00000114 | ||||
| Redeem With Fee | 38642328 | 2 hrs ago | IN | 0 ETH | 0.00000114 | ||||
| Redeem With Fee | 38642323 | 2 hrs ago | IN | 0 ETH | 0.00000114 | ||||
| Redeem With Fee | 38642322 | 2 hrs ago | IN | 0 ETH | 0.00000114 | ||||
| Redeem With Fee | 38641940 | 2 hrs ago | IN | 0 ETH | 0.00000115 | ||||
| Redeem With Fee | 38634646 | 4 hrs ago | IN | 0 ETH | 0.00000115 | ||||
| Redeem With Fee | 38627733 | 6 hrs ago | IN | 0 ETH | 0.00000115 | ||||
| Redeem With Fee | 38626195 | 7 hrs ago | IN | 0 ETH | 0.0000011 | ||||
| Redeem With Fee | 38624659 | 7 hrs ago | IN | 0 ETH | 0.00000116 | ||||
| Redeem With Fee | 38618976 | 9 hrs ago | IN | 0 ETH | 0.0000011 | ||||
| Redeem With Fee | 38617748 | 9 hrs ago | IN | 0 ETH | 0.00000109 | ||||
| Redeem With Fee | 38611561 | 11 hrs ago | IN | 0 ETH | 0.00000115 | ||||
| Redeem With Fee | 38568298 | 23 hrs ago | IN | 0 ETH | 0.00000109 | ||||
| Redeem With Fee | 38567978 | 23 hrs ago | IN | 0 ETH | 0.00000109 | ||||
| Redeem With Fee | 38567828 | 23 hrs ago | IN | 0 ETH | 0.00000109 | ||||
| Redeem With Fee | 38560149 | 25 hrs ago | IN | 0 ETH | 0.00000114 | ||||
| Redeem With Fee | 38557155 | 26 hrs ago | IN | 0 ETH | 0.00000114 | ||||
| Redeem With Fee | 38557154 | 26 hrs ago | IN | 0 ETH | 0.00000114 | ||||
| Redeem With Fee | 38557025 | 26 hrs ago | IN | 0 ETH | 0.00000114 | ||||
| Redeem With Fee | 38557024 | 26 hrs ago | IN | 0 ETH | 0.00000114 | ||||
| Redeem With Fee | 38556778 | 26 hrs ago | IN | 0 ETH | 0.00000114 | ||||
| Redeem With Fee | 38553182 | 27 hrs ago | IN | 0 ETH | 0.00000114 | ||||
| Redeem With Fee | 38550549 | 28 hrs ago | IN | 0 ETH | 0.00000114 | ||||
| Redeem With Fee | 38549343 | 28 hrs ago | IN | 0 ETH | 0.00000109 | ||||
| Redeem With Fee | 38535524 | 32 hrs ago | IN | 0 ETH | 0.0000011 |
Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers.
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | ||||
|---|---|---|---|---|---|---|---|
| 38642329 | 2 hrs ago | 0 ETH | |||||
| 38642329 | 2 hrs ago | 0 ETH | |||||
| 38642329 | 2 hrs ago | 0 ETH | |||||
| 38642329 | 2 hrs ago | 0 ETH | |||||
| 38642329 | 2 hrs ago | 0 ETH | |||||
| 38642329 | 2 hrs ago | 0 ETH | |||||
| 38642329 | 2 hrs ago | 0 ETH | |||||
| 38642329 | 2 hrs ago | 0 ETH | |||||
| 38642329 | 2 hrs ago | 0 ETH | |||||
| 38642329 | 2 hrs ago | 0 ETH | |||||
| 38642328 | 2 hrs ago | 0 ETH | |||||
| 38642328 | 2 hrs ago | 0 ETH | |||||
| 38642328 | 2 hrs ago | 0 ETH | |||||
| 38642328 | 2 hrs ago | 0 ETH | |||||
| 38642328 | 2 hrs ago | 0 ETH | |||||
| 38642328 | 2 hrs ago | 0 ETH | |||||
| 38642328 | 2 hrs ago | 0 ETH | |||||
| 38642328 | 2 hrs ago | 0 ETH | |||||
| 38642328 | 2 hrs ago | 0 ETH | |||||
| 38642328 | 2 hrs ago | 0 ETH | |||||
| 38642323 | 2 hrs ago | 0 ETH | |||||
| 38642323 | 2 hrs ago | 0 ETH | |||||
| 38642323 | 2 hrs ago | 0 ETH | |||||
| 38642323 | 2 hrs ago | 0 ETH | |||||
| 38642323 | 2 hrs ago | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
MayanCircle
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 800 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/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;
uint8 public consistencyLevel;
address public guardian;
address nextGuardian;
bool public paused;
mapping(uint64 => FeeLock) public feeStorage;
mapping(uint16 => bytes32) public chainIdToEmitter;
mapping(uint32 => bytes32) public domainToCaller;
mapping(bytes32 => bytes32) public keyToMintRecipient; // key is domain + local token address
mapping(uint16 => uint32) private chainIdToDomain;
uint8 constant ETH_DECIMALS = 18;
uint32 constant SOLANA_DOMAIN = 5;
uint16 constant SOLANA_CHAIN_ID = 1;
uint32 constant SUI_DOMAIN = 8;
uint256 constant CCTP_DOMAIN_INDEX = 4;
uint256 constant CCTP_NONCE_INDEX = 12;
uint256 constant CCTP_TOKEN_INDEX = 120;
uint256 constant CCTP_RECIPIENT_INDEX = 152;
uint256 constant CCTP_AMOUNT_INDEX = 208;
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();
error EmitterAlreadySet();
error InvalidDestAddr();
error InvalidMintRecipient();
error InvalidRedeemFee();
error InvalidPayload();
error CallerNotSet();
error MintRecipientNotSet();
error InvalidCaller();
error DeadlineViolation();
error InvalidAddress();
error InvalidReferrerFee();
error InvalidProtocolFee();
error EthTransferFailed();
error InvalidAmountOut();
error DomainNotSet();
error AlreadySet();
enum Action {
NONE,
SWAP,
FULFILL,
BRIDGE_WITH_FEE,
UNLOCK_FEE,
UNLOCK_FEE_REFINE
}
struct Order {
uint8 action;
uint8 payloadType;
bytes32 trader;
uint16 sourceChain;
bytes32 tokenIn;
uint64 amountIn;
bytes32 destAddr;
uint16 destChain;
bytes32 tokenOut;
uint64 minAmountOut;
uint64 gasDrop;
uint64 redeemFee;
uint64 deadline;
bytes32 referrerAddr;
}
struct OrderFields {
uint8 referrerBps;
uint8 protocolBps;
uint64 cctpSourceNonce;
uint32 cctpSourceDomain;
}
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 BridgeWithFeeMsg {
uint8 action;
uint8 payloadType;
uint64 cctpNonce;
uint32 cctpDomain;
bytes32 destAddr;
uint64 gasDrop;
uint64 redeemFee;
uint64 burnAmount;
bytes32 burnToken;
bytes32 customPayload;
}
struct BridgeWithFeeParams {
uint8 payloadType;
bytes32 destAddr;
uint64 gasDrop;
uint64 redeemFee;
uint64 burnAmount;
bytes32 burnToken;
bytes32 customPayload;
}
struct UnlockFeeMsg {
uint8 action;
uint8 payloadType;
uint64 cctpNonce;
uint32 cctpDomain;
bytes32 unlockerAddr;
uint64 gasDrop;
}
struct UnlockParams {
bytes32 unlockerAddr;
uint64 gasDrop;
}
struct UnlockRefinedFeeMsg {
uint8 action;
uint8 payloadType;
uint64 cctpNonce;
uint32 cctpDomain;
bytes32 unlockerAddr;
uint64 gasDrop;
bytes32 destAddr;
}
struct FulfillMsg {
uint8 action;
uint8 payloadType;
bytes32 tokenIn;
uint64 amountIn;
bytes32 destAddr;
uint16 destChainId;
bytes32 tokenOut;
uint64 promisedAmount;
uint64 gasDrop;
uint64 redeemFee;
uint64 deadline;
bytes32 referrerAddr;
uint8 referrerBps;
uint8 protocolBps;
uint64 cctpSourceNonce;
uint32 cctpSourceDomain;
bytes32 driver;
}
struct FulfillParams {
bytes32 destAddr;
uint16 destChainId;
bytes32 tokenOut;
uint64 promisedAmount;
uint64 gasDrop;
uint64 redeemFee;
uint64 deadline;
bytes32 referrerAddr;
uint8 referrerBps;
uint8 protocolBps;
bytes32 driver;
}
constructor(
address _cctpTokenMessenger,
address _wormhole,
address _feeManager,
uint16 _auctionChainId,
bytes32 _auctionAddr,
uint8 _consistencyLevel
) {
cctpTokenMessenger = ITokenMessenger(_cctpTokenMessenger);
wormhole = IWormhole(_wormhole);
feeManager = IFeeManager(_feeManager);
auctionChainId = _auctionChainId;
auctionAddr = _auctionAddr;
consistencyLevel = _consistencyLevel;
localDomain = ITokenMessenger(_cctpTokenMessenger).localMessageTransmitter().localDomain();
guardian = msg.sender;
}
function bridgeWithFee(
address tokenIn,
uint256 amountIn,
uint64 redeemFee,
uint64 gasDrop,
bytes32 destAddr,
uint32 destDomain,
uint8 payloadType,
bytes memory customPayload
) external payable nonReentrant returns (uint64 sequence) {
if (paused) {
revert Paused();
}
if (redeemFee >= amountIn) {
revert InvalidRedeemFee();
}
IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
approveIfNeeded(tokenIn, address(cctpTokenMessenger), amountIn, true);
uint64 cctpNonce = sendCctp(tokenIn, amountIn, destDomain);
bytes32 customPayloadHash;
if (payloadType == 2) {
customPayloadHash = keccak256(customPayload);
}
BridgeWithFeeMsg memory bridgeMsg = BridgeWithFeeMsg({
action: uint8(Action.BRIDGE_WITH_FEE),
payloadType: payloadType,
cctpNonce: cctpNonce,
cctpDomain: localDomain,
destAddr: destAddr,
gasDrop: gasDrop,
redeemFee: redeemFee,
burnAmount: uint64(amountIn),
burnToken: bytes32(uint256(uint160(tokenIn))),
customPayload: customPayloadHash
});
bytes memory payload = abi.encodePacked(keccak256(encodeBridgeWithFee(bridgeMsg)));
sequence = wormhole.publishMessage{
value : msg.value
}(0, payload, consistencyLevel);
}
function bridgeWithLockedFee(
address tokenIn,
uint256 amountIn,
uint64 gasDrop,
uint256 redeemFee,
uint32 destDomain,
bytes32 destAddr
) external nonReentrant returns (uint64 cctpNonce) {
if (paused) {
revert Paused();
}
if (bytes12(destAddr) != 0) {
revert InvalidDomain();
}
if (redeemFee == 0) {
revert InvalidRedeemFee();
}
IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
approveIfNeeded(tokenIn, address(cctpTokenMessenger), amountIn - redeemFee, true);
cctpNonce = cctpTokenMessenger.depositForBurnWithCaller(
amountIn - redeemFee,
destDomain,
destAddr,
tokenIn,
getCaller(destDomain)
);
feeStorage[cctpNonce] = FeeLock({
destAddr: destAddr,
gasDrop: gasDrop,
token: tokenIn,
redeemFee: redeemFee
});
}
function createOrder(
OrderParams memory params
) external payable nonReentrant returns (uint64 sequence) {
if (paused) {
revert Paused();
}
if (params.redeemFee >= params.amountIn) {
revert InvalidRedeemFee();
}
if (params.tokenOut == bytes32(0) && params.gasDrop > 0) {
revert InvalidGasDrop();
}
IERC20(params.tokenIn).safeTransferFrom(msg.sender, address(this), params.amountIn);
approveIfNeeded(params.tokenIn, address(cctpTokenMessenger), params.amountIn, true);
uint64 cctpNonce = sendCctp(params.tokenIn, params.amountIn, getDomain(params.destChain));
if (params.referrerBps > 100) {
revert InvalidReferrerFee();
}
uint8 protocolBps = feeManager.calcProtocolBps(uint64(params.amountIn), params.tokenIn, params.tokenOut, params.destChain, params.referrerBps);
if (protocolBps > 100) {
revert InvalidProtocolFee();
}
Order memory order = Order({
action: uint8(Action.SWAP),
payloadType: 1,
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
});
bytes memory encodedOrder = encodeOrder(order);
OrderFields memory orderFields = OrderFields({
referrerBps: params.referrerBps,
protocolBps: protocolBps,
cctpSourceNonce: cctpNonce,
cctpSourceDomain: cctpTokenMessenger.localMessageTransmitter().localDomain()
});
encodedOrder = encodedOrder.concat(encodeOrderFields(orderFields));
bytes memory payload = abi.encodePacked(keccak256(encodedOrder));
sequence = wormhole.publishMessage{
value : msg.value
}(0, payload, consistencyLevel);
}
function redeemWithFee(
bytes memory cctpMsg,
bytes memory cctpSigs,
bytes memory encodedVm,
BridgeWithFeeParams memory bridgeParams
) external nonReentrant payable {
(IWormhole.VM memory vm, bool valid, string memory reason) = wormhole.parseAndVerifyVM(encodedVm);
require(valid, reason);
validateEmitter(vm.emitterAddress, vm.emitterChainId);
if (truncateAddress(cctpMsg.toBytes32(CCTP_RECIPIENT_INDEX)) != address(this)) {
revert InvalidMintRecipient();
}
BridgeWithFeeMsg memory bridgeMsg = recreateBridgeWithFee(bridgeParams, cctpMsg);
bytes32 calculatedPayload = keccak256(encodeBridgeWithFee(bridgeMsg));
if (vm.payload.length != 32 || calculatedPayload != vm.payload.toBytes32(0)) {
revert InvalidPayload();
}
if (bridgeMsg.payloadType == 2 && msg.sender != truncateAddress(bridgeMsg.destAddr)) {
revert Unauthorized();
}
(address localToken, uint256 amount) = receiveCctp(cctpMsg, cctpSigs);
if (bridgeMsg.redeemFee > amount) {
revert InvalidRedeemFee();
}
depositRelayerFee(msg.sender, localToken, uint256(bridgeMsg.redeemFee));
address recipient = truncateAddress(bridgeMsg.destAddr);
IERC20(localToken).safeTransfer(recipient, amount - uint256(bridgeMsg.redeemFee));
if (bridgeMsg.gasDrop > 0) {
uint256 denormalizedGasDrop = deNormalizeAmount(bridgeMsg.gasDrop, ETH_DECIMALS);
if (msg.value != denormalizedGasDrop) {
revert InvalidGasDrop();
}
payEth(recipient, denormalizedGasDrop, false);
}
}
function redeemWithLockedFee(bytes memory cctpMsg, bytes memory cctpSigs, bytes32 unlockerAddr) external nonReentrant payable returns (uint64 sequence) {
uint32 cctpSourceDomain = cctpMsg.toUint32(CCTP_DOMAIN_INDEX);
uint64 cctpNonce = cctpMsg.toUint64(CCTP_NONCE_INDEX);
address mintRecipient = truncateAddress(cctpMsg.toBytes32(CCTP_RECIPIENT_INDEX));
if (mintRecipient == address(this)) {
revert InvalidMintRecipient();
}
bool success = cctpTokenMessenger.localMessageTransmitter().receiveMessage(cctpMsg, cctpSigs);
if (!success) {
revert CctpReceiveFailed();
}
uint256 wormholeFee = wormhole.messageFee();
if (msg.value > wormholeFee) {
payEth(mintRecipient, msg.value - wormholeFee, false);
}
UnlockFeeMsg memory unlockMsg = UnlockFeeMsg({
action: uint8(Action.UNLOCK_FEE),
payloadType: 1,
cctpDomain: cctpSourceDomain,
cctpNonce: cctpNonce,
unlockerAddr: unlockerAddr,
gasDrop: uint64(normalizeAmount(msg.value - wormholeFee, ETH_DECIMALS))
});
bytes memory encodedMsg = encodeUnlockFeeMsg(unlockMsg);
bytes memory payload = abi.encodePacked(keccak256(encodedMsg));
sequence = wormhole.publishMessage{
value : wormholeFee
}(0, payload, consistencyLevel);
}
function refineFee(uint32 cctpNonce, uint32 cctpDomain, bytes32 destAddr, bytes32 unlockerAddr) external nonReentrant payable returns (uint64 sequence) {
uint256 wormholeFee = wormhole.messageFee();
if (msg.value > wormholeFee) {
payEth(truncateAddress(destAddr), msg.value - wormholeFee, false);
}
UnlockRefinedFeeMsg memory unlockMsg = UnlockRefinedFeeMsg({
action: uint8(Action.UNLOCK_FEE_REFINE),
payloadType: 1,
cctpDomain: cctpDomain,
cctpNonce: cctpNonce,
unlockerAddr: unlockerAddr,
gasDrop: uint64(normalizeAmount(msg.value - wormholeFee, ETH_DECIMALS)),
destAddr: destAddr
});
bytes memory encodedMsg = encodeUnlockRefinedFeeMsg(unlockMsg);
bytes memory payload = abi.encodePacked(keccak256(encodedMsg));
sequence = wormhole.publishMessage{
value : wormholeFee
}(0, payload, consistencyLevel);
}
function unlockFee(
bytes memory encodedVm,
UnlockFeeMsg memory unlockMsg
) external nonReentrant {
(IWormhole.VM memory vm, bool valid, string memory reason) = wormhole.parseAndVerifyVM(encodedVm);
require(valid, reason);
validateEmitter(vm.emitterAddress, vm.emitterChainId);
unlockMsg.action = uint8(Action.UNLOCK_FEE);
bytes32 calculatedPayload = keccak256(encodeUnlockFeeMsg(unlockMsg));
if (vm.payload.length != 32 || calculatedPayload != vm.payload.toBytes32(0)) {
revert InvalidPayload();
}
if (unlockMsg.cctpDomain != localDomain) {
revert InvalidDomain();
}
FeeLock memory feeLock = feeStorage[unlockMsg.cctpNonce];
if (feeLock.redeemFee == 0) {
revert InvalidOrder();
}
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,
UnlockFeeMsg memory unlockMsg,
UnlockRefinedFeeMsg memory refinedMsg
) external nonReentrant {
(IWormhole.VM memory vm1, bool valid1, string memory reason1) = wormhole.parseAndVerifyVM(encodedVm1);
require(valid1, reason1);
validateEmitter(vm1.emitterAddress, vm1.emitterChainId);
unlockMsg.action = uint8(Action.UNLOCK_FEE);
bytes32 calculatedPayload1 = keccak256(encodeUnlockFeeMsg(unlockMsg));
if (vm1.payload.length != 32 || calculatedPayload1 != vm1.payload.toBytes32(0)) {
revert InvalidPayload();
}
if (unlockMsg.cctpDomain != localDomain) {
revert InvalidDomain();
}
FeeLock memory feeLock = feeStorage[unlockMsg.cctpNonce];
if (feeLock.redeemFee == 0) {
revert InvalidOrder();
}
if (unlockMsg.gasDrop >= feeLock.gasDrop) {
revert InvalidAction();
}
(IWormhole.VM memory vm2, bool valid2, string memory reason2) = wormhole.parseAndVerifyVM(encodedVm2);
require(valid2, reason2);
validateEmitter(vm2.emitterAddress, vm2.emitterChainId);
refinedMsg.action = uint8(Action.UNLOCK_FEE_REFINE);
bytes32 calculatedPayload2 = keccak256(encodeUnlockRefinedFeeMsg(refinedMsg));
if (vm2.payload.length != 32 || calculatedPayload2 != vm2.payload.toBytes32(0)) {
revert InvalidPayload();
}
if (refinedMsg.destAddr != feeLock.destAddr) {
revert InvalidDestAddr();
}
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,
FulfillParams memory params,
address swapProtocol,
bytes memory swapData
) external nonReentrant payable {
(IWormhole.VM memory vm, bool valid, string memory reason) = wormhole.parseAndVerifyVM(encodedVm);
require(valid, reason);
if (vm.emitterChainId != SOLANA_CHAIN_ID || vm.emitterAddress != auctionAddr) {
revert InvalidEmitter();
}
FulfillMsg memory fulfillMsg = recreateFulfillMsg(params, cctpMsg);
if (fulfillMsg.deadline < block.timestamp) {
revert DeadlineViolation();
}
if (msg.sender != truncateAddress(fulfillMsg.driver)) {
revert Unauthorized();
}
bytes32 calculatedPayload = calcFulfillPayload(fulfillMsg);
if (vm.payload.length != 32 || calculatedPayload != vm.payload.toBytes32(0)) {
revert InvalidPayload();
}
(address localToken, uint256 cctpAmount) = receiveCctp(cctpMsg, cctpSigs);
if (fulfillMsg.redeemFee > 0) {
IERC20(localToken).safeTransfer(msg.sender, fulfillMsg.redeemFee);
}
address tokenOut = truncateAddress(fulfillMsg.tokenOut);
approveIfNeeded(localToken, swapProtocol, cctpAmount - uint256(fulfillMsg.redeemFee), false);
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);
if (amountOut < promisedAmount) {
revert InvalidAmountOut();
}
makePayments(
fulfillMsg,
tokenOut,
amountOut
);
emit OrderFulfilled(fulfillMsg.cctpSourceDomain, fulfillMsg.cctpSourceNonce, amountOut);
}
function refund(
bytes memory encodedVm,
bytes memory cctpMsg,
bytes memory cctpSigs,
OrderParams memory orderParams,
ExtraParams memory extraParams
) external nonReentrant payable {
(IWormhole.VM memory vm, bool valid, string memory reason) = wormhole.parseAndVerifyVM(encodedVm);
require(valid, reason);
validateEmitter(vm.emitterAddress, vm.emitterChainId);
(address localToken, uint256 amount) = receiveCctp(cctpMsg, cctpSigs);
Order memory order = recreateOrder(orderParams, cctpMsg, extraParams);
bytes memory encodedOrder = encodeOrder(order);
OrderFields memory orderFields = OrderFields({
referrerBps: orderParams.referrerBps,
protocolBps: extraParams.protocolBps,
cctpSourceNonce: cctpMsg.toUint64(CCTP_NONCE_INDEX),
cctpSourceDomain: cctpMsg.toUint32(CCTP_DOMAIN_INDEX)
});
encodedOrder = encodedOrder.concat(encodeOrderFields(orderFields));
if (vm.payload.length != 32 || keccak256(encodedOrder) != vm.payload.toBytes32(0)) {
revert InvalidPayload();
}
if (order.deadline >= block.timestamp) {
revert DeadlineViolation();
}
uint256 gasDrop = deNormalizeAmount(order.gasDrop, ETH_DECIMALS);
if (msg.value != gasDrop) {
revert InvalidGasDrop();
}
address destAddr = truncateAddress(order.destAddr);
if (gasDrop > 0) {
payEth(destAddr, gasDrop, false);
}
IERC20(localToken).safeTransfer(msg.sender, order.redeemFee);
IERC20(localToken).safeTransfer(destAddr, amount - order.redeemFee);
logRefund(cctpMsg, amount);
}
function sendCctp(
address tokenIn,
uint256 amountIn,
uint32 destDomain
) internal returns (uint64 cctpNonce) {
if (destDomain == SUI_DOMAIN) {
cctpNonce = cctpTokenMessenger.depositForBurn(amountIn, destDomain, getMintRecipient(destDomain, tokenIn), tokenIn);
} else {
cctpNonce = cctpTokenMessenger.depositForBurnWithCaller(
amountIn,
destDomain,
getMintRecipient(destDomain, tokenIn),
tokenIn,
getCaller(destDomain)
);
}
}
function receiveCctp(bytes memory cctpMsg, bytes memory cctpSigs) internal returns (address, uint256) {
uint32 cctpDomain = cctpMsg.toUint32(CCTP_DOMAIN_INDEX);
bytes32 cctpSourceToken = cctpMsg.toBytes32(CCTP_TOKEN_INDEX);
address localToken = cctpTokenMessenger.localMinter().getLocalToken(cctpDomain, 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 getMintRecipient(uint32 destDomain, address tokenIn) internal view returns (bytes32) {
bytes32 mintRecepient = keyToMintRecipient[keccak256(abi.encodePacked(destDomain, tokenIn))];
if (mintRecepient == bytes32(0)) {
revert MintRecipientNotSet();
}
return mintRecepient;
}
function getCaller(uint32 destDomain) internal view returns (bytes32 caller) {
caller = domainToCaller[destDomain];
if (caller == bytes32(0)) {
revert CallerNotSet();
}
return caller;
}
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) {
payEth(referrerAddr, referrerAmount, false);
}
if (protocolAmount > 0) {
payEth(feeManager.feeCollector(), protocolAmount, false);
}
payEth(destAddr, amount - referrerAmount - protocolAmount, true);
} else {
if (fulfillMsg.gasDrop > 0) {
uint256 gasDrop = deNormalizeAmount(fulfillMsg.gasDrop, ETH_DECIMALS);
if (msg.value != gasDrop) {
revert InvalidGasDrop();
}
payEth(destAddr, gasDrop, false);
}
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 encodeBridgeWithFee(BridgeWithFeeMsg memory bridgeMsg) internal pure returns (bytes memory) {
return abi.encodePacked(
bridgeMsg.action,
bridgeMsg.payloadType,
bridgeMsg.cctpNonce,
bridgeMsg.cctpDomain,
bridgeMsg.destAddr,
bridgeMsg.gasDrop,
bridgeMsg.redeemFee,
bridgeMsg.burnAmount,
bridgeMsg.burnToken,
bridgeMsg.customPayload
);
}
function recreateBridgeWithFee(
BridgeWithFeeParams memory bridgeParams,
bytes memory cctpMsg
) internal pure returns (BridgeWithFeeMsg memory) {
return BridgeWithFeeMsg({
action: uint8(Action.BRIDGE_WITH_FEE),
payloadType: bridgeParams.payloadType,
cctpNonce: cctpMsg.toUint64(CCTP_NONCE_INDEX),
cctpDomain: cctpMsg.toUint32(CCTP_DOMAIN_INDEX),
destAddr: bridgeParams.destAddr,
gasDrop: bridgeParams.gasDrop,
redeemFee: bridgeParams.redeemFee,
burnAmount: cctpMsg.toUint64(CCTP_AMOUNT_INDEX),
burnToken: cctpMsg.toBytes32(CCTP_TOKEN_INDEX),
customPayload: bridgeParams.customPayload
});
}
function encodeUnlockFeeMsg(UnlockFeeMsg memory unlockMsg) internal pure returns (bytes memory) {
return abi.encodePacked(
unlockMsg.action,
unlockMsg.payloadType,
unlockMsg.cctpNonce,
unlockMsg.cctpDomain,
unlockMsg.unlockerAddr,
unlockMsg.gasDrop
);
}
function encodeUnlockRefinedFeeMsg(UnlockRefinedFeeMsg memory unlockMsg) internal pure returns (bytes memory) {
return abi.encodePacked(
unlockMsg.action,
unlockMsg.payloadType,
unlockMsg.cctpNonce,
unlockMsg.cctpDomain,
unlockMsg.unlockerAddr,
unlockMsg.gasDrop,
unlockMsg.destAddr
);
}
function parseUnlockFeeMsg(bytes memory payload) internal pure returns (UnlockFeeMsg memory) {
return UnlockFeeMsg({
action: payload.toUint8(0),
payloadType: 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),
payloadType: 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.action,
order.payloadType,
order.trader,
order.sourceChain,
order.tokenIn,
order.amountIn,
order.destAddr,
order.destChain,
order.tokenOut,
order.minAmountOut,
order.gasDrop,
order.redeemFee,
order.deadline,
order.referrerAddr
);
}
function encodeOrderFields(OrderFields memory orderFields) internal pure returns (bytes memory) {
return abi.encodePacked(
orderFields.referrerBps,
orderFields.protocolBps,
orderFields.cctpSourceNonce,
orderFields.cctpSourceDomain
);
}
function calcFulfillPayload(FulfillMsg memory fulfillMsg) internal pure returns (bytes32) {
bytes memory partialPayload = encodeFulfillMsg(fulfillMsg);
bytes memory completePayload = partialPayload.concat(abi.encodePacked(fulfillMsg.cctpSourceNonce, fulfillMsg.cctpSourceDomain, fulfillMsg.driver));
return keccak256(completePayload);
}
function recreateOrder(
OrderParams memory params,
bytes memory cctpMsg,
ExtraParams memory extraParams
) internal pure returns (Order memory) {
return Order({
action: uint8(Action.SWAP),
payloadType: 1,
trader: extraParams.trader,
sourceChain: extraParams.sourceChainId,
tokenIn: cctpMsg.toBytes32(CCTP_TOKEN_INDEX),
amountIn: cctpMsg.toUint64(CCTP_AMOUNT_INDEX),
destAddr: params.destAddr,
destChain: params.destChain,
tokenOut: params.tokenOut,
minAmountOut: params.minAmountOut,
gasDrop: params.gasDrop,
redeemFee: params.redeemFee,
deadline: params.deadline,
referrerAddr: params.referrerAddr
});
}
function encodeFulfillMsg(FulfillMsg memory fulfillMsg) internal pure returns (bytes memory) {
return abi.encodePacked(
fulfillMsg.action,
fulfillMsg.payloadType,
fulfillMsg.tokenIn,
fulfillMsg.amountIn,
fulfillMsg.destAddr,
fulfillMsg.destChainId,
fulfillMsg.tokenOut,
fulfillMsg.promisedAmount,
fulfillMsg.gasDrop,
fulfillMsg.redeemFee,
fulfillMsg.deadline,
fulfillMsg.referrerAddr,
fulfillMsg.referrerBps,
fulfillMsg.protocolBps
);
}
function recreateFulfillMsg(
FulfillParams memory params,
bytes memory cctpMsg
) internal pure returns (FulfillMsg memory) {
return FulfillMsg({
action: uint8(Action.FULFILL),
payloadType: 1,
tokenIn: cctpMsg.toBytes32(CCTP_TOKEN_INDEX),
amountIn: cctpMsg.toUint64(CCTP_AMOUNT_INDEX),
destAddr: params.destAddr,
destChainId: params.destChainId,
tokenOut: params.tokenOut,
promisedAmount: params.promisedAmount,
gasDrop: params.gasDrop,
redeemFee: params.redeemFee,
deadline: params.deadline,
referrerAddr: params.referrerAddr,
referrerBps: params.referrerBps,
protocolBps: params.protocolBps,
cctpSourceNonce: cctpMsg.toUint64(CCTP_NONCE_INDEX),
cctpSourceDomain: cctpMsg.toUint32(CCTP_DOMAIN_INDEX),
driver: params.driver
});
}
function validateEmitter(bytes32 emitter, uint16 chainId) view internal {
if (emitter != chainIdToEmitter[chainId]) {
revert InvalidEmitter();
}
}
function approveIfNeeded(address tokenAddr, address spender, uint256 amount, bool max) internal {
IERC20 token = IERC20(tokenAddr);
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < amount) {
if (currentAllowance > 0) {
token.safeApprove(spender, 0);
}
token.safeApprove(spender, max ? type(uint256).max : amount);
}
}
function payEth(address to, uint256 amount, bool revertOnFailure) internal {
(bool success, ) = payable(to).call{value: amount}('');
if (revertOnFailure) {
if (success != true) {
revert EthTransferFailed();
}
}
}
function depositRelayerFee(address relayer, address token, uint256 amount) internal {
IERC20(token).transfer(address(feeManager), amount);
try feeManager.depositFee(relayer, token, amount) {} catch {}
}
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 logRefund(bytes memory cctpMsg, uint256 amount) internal {
emit OrderRefunded(cctpMsg.toUint32(CCTP_DOMAIN_INDEX), cctpMsg.toUint64(CCTP_NONCE_INDEX), amount);
}
function truncateAddress(bytes32 b) internal pure returns (address) {
if (bytes12(b) != 0) {
revert InvalidAddress();
}
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 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();
}
payEth(to, amount, true);
}
function setDomainCallers(uint32 domain, bytes32 caller) public {
if (msg.sender != guardian) {
revert Unauthorized();
}
if (domainToCaller[domain] != bytes32(0)) {
revert AlreadySet();
}
domainToCaller[domain] = caller;
}
function setMintRecipient(uint32 destDomain, address tokenIn, bytes32 mintRecipient) public {
if (msg.sender != guardian) {
revert Unauthorized();
}
bytes32 key = keccak256(abi.encodePacked(destDomain, tokenIn));
if (keyToMintRecipient[key] != bytes32(0)) {
revert AlreadySet();
}
keyToMintRecipient[key] = mintRecipient;
}
function setEmitter(uint16 chainId, bytes32 emitter) public {
if (msg.sender != guardian) {
revert Unauthorized();
}
if (chainIdToEmitter[chainId] != bytes32(0)) {
revert AlreadySet();
}
chainIdToEmitter[chainId] = emitter;
}
function setDomains(uint16[] memory chainIds, uint32[] memory domains) public {
if (msg.sender != guardian) {
revert Unauthorized();
}
for (uint i = 0; i < chainIds.length; i++) {
if (chainIdToDomain[chainIds[i]] != 0) {
revert AlreadySet();
}
chainIdToDomain[chainIds[i]] = domains[i] + 1; // to distinguish between unset and 0
}
}
function getDomain(uint16 chainId) public view returns (uint32 domain) {
domain = chainIdToDomain[chainId];
if (domain == 0) {
revert DomainNotSet();
}
return domain - 1;
}
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: 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/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);
}// 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: 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);
}
}
}/*
* 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 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);
}/*
* 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
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 depositForBurn(
uint256 amount,
uint32 destinationDomain,
bytes32 mintRecipient,
address burnToken
) external returns (uint64 nonce);
function depositForBurnWithCaller(
uint256 amount,
uint32 destinationDomain,
bytes32 mintRecipient,
address burnToken,
bytes32 destinationCaller
) external returns (uint64 nonce);
}/*
* 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;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IFeeManager {
event ProtocolFeeCalced(uint8 bps);
event FeeDeposited(address relayer, address token, uint256 amount);
event FeeWithdrawn(address token, uint256 amount);
function calcProtocolBps(
uint64 amountIn,
address tokenIn,
bytes32 tokenOut,
uint16 destChain,
uint8 referrerBps
) external returns (uint8);
function feeCollector() external view returns (address);
function depositFee(address owner, address token, uint256 amount) payable external;
function withdrawFee(address token, uint256 amount) external;
}// 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;
}// 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; } }
{
"optimizer": {
"enabled": true,
"runs": 800
},
"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":"uint8","name":"_consistencyLevel","type":"uint8"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadySet","type":"error"},{"inputs":[],"name":"CallerNotSet","type":"error"},{"inputs":[],"name":"CctpReceiveFailed","type":"error"},{"inputs":[],"name":"DeadlineViolation","type":"error"},{"inputs":[],"name":"DomainNotSet","type":"error"},{"inputs":[],"name":"EmitterAlreadySet","type":"error"},{"inputs":[],"name":"EthTransferFailed","type":"error"},{"inputs":[],"name":"InvalidAction","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidAmountOut","type":"error"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[],"name":"InvalidDestAddr","type":"error"},{"inputs":[],"name":"InvalidDomain","type":"error"},{"inputs":[],"name":"InvalidEmitter","type":"error"},{"inputs":[],"name":"InvalidGasDrop","type":"error"},{"inputs":[],"name":"InvalidMintRecipient","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidOrder","type":"error"},{"inputs":[],"name":"InvalidPayload","type":"error"},{"inputs":[],"name":"InvalidProtocolFee","type":"error"},{"inputs":[],"name":"InvalidRedeemFee","type":"error"},{"inputs":[],"name":"InvalidReferrerFee","type":"error"},{"inputs":[],"name":"MintRecipientNotSet","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"},{"internalType":"uint32","name":"destDomain","type":"uint32"},{"internalType":"uint8","name":"payloadType","type":"uint8"},{"internalType":"bytes","name":"customPayload","type":"bytes"}],"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"},{"internalType":"uint32","name":"destDomain","type":"uint32"},{"internalType":"bytes32","name":"destAddr","type":"bytes32"}],"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":"uint16","name":"","type":"uint16"}],"name":"chainIdToEmitter","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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"}],"name":"createOrder","outputs":[{"internalType":"uint64","name":"sequence","type":"uint64"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"domainToCaller","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","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"},{"components":[{"internalType":"bytes32","name":"destAddr","type":"bytes32"},{"internalType":"uint16","name":"destChainId","type":"uint16"},{"internalType":"bytes32","name":"tokenOut","type":"bytes32"},{"internalType":"uint64","name":"promisedAmount","type":"uint64"},{"internalType":"uint64","name":"gasDrop","type":"uint64"},{"internalType":"uint64","name":"redeemFee","type":"uint64"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"bytes32","name":"referrerAddr","type":"bytes32"},{"internalType":"uint8","name":"referrerBps","type":"uint8"},{"internalType":"uint8","name":"protocolBps","type":"uint8"},{"internalType":"bytes32","name":"driver","type":"bytes32"}],"internalType":"struct MayanCircle.FulfillParams","name":"params","type":"tuple"},{"internalType":"address","name":"swapProtocol","type":"address"},{"internalType":"bytes","name":"swapData","type":"bytes"}],"name":"fulfillOrder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId","type":"uint16"}],"name":"getDomain","outputs":[{"internalType":"uint32","name":"domain","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"keyToMintRecipient","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"localDomain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","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"},{"components":[{"internalType":"uint8","name":"payloadType","type":"uint8"},{"internalType":"bytes32","name":"destAddr","type":"bytes32"},{"internalType":"uint64","name":"gasDrop","type":"uint64"},{"internalType":"uint64","name":"redeemFee","type":"uint64"},{"internalType":"uint64","name":"burnAmount","type":"uint64"},{"internalType":"bytes32","name":"burnToken","type":"bytes32"},{"internalType":"bytes32","name":"customPayload","type":"bytes32"}],"internalType":"struct MayanCircle.BridgeWithFeeParams","name":"bridgeParams","type":"tuple"}],"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":"uint32","name":"domain","type":"uint32"},{"internalType":"bytes32","name":"caller","type":"bytes32"}],"name":"setDomainCallers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16[]","name":"chainIds","type":"uint16[]"},{"internalType":"uint32[]","name":"domains","type":"uint32[]"}],"name":"setDomains","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitter","type":"bytes32"}],"name":"setEmitter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeManager","type":"address"}],"name":"setFeeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"destDomain","type":"uint32"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"bytes32","name":"mintRecipient","type":"bytes32"}],"name":"setMintRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_pause","type":"bool"}],"name":"setPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedVm","type":"bytes"},{"components":[{"internalType":"uint8","name":"action","type":"uint8"},{"internalType":"uint8","name":"payloadType","type":"uint8"},{"internalType":"uint64","name":"cctpNonce","type":"uint64"},{"internalType":"uint32","name":"cctpDomain","type":"uint32"},{"internalType":"bytes32","name":"unlockerAddr","type":"bytes32"},{"internalType":"uint64","name":"gasDrop","type":"uint64"}],"internalType":"struct MayanCircle.UnlockFeeMsg","name":"unlockMsg","type":"tuple"}],"name":"unlockFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedVm1","type":"bytes"},{"internalType":"bytes","name":"encodedVm2","type":"bytes"},{"components":[{"internalType":"uint8","name":"action","type":"uint8"},{"internalType":"uint8","name":"payloadType","type":"uint8"},{"internalType":"uint64","name":"cctpNonce","type":"uint64"},{"internalType":"uint32","name":"cctpDomain","type":"uint32"},{"internalType":"bytes32","name":"unlockerAddr","type":"bytes32"},{"internalType":"uint64","name":"gasDrop","type":"uint64"}],"internalType":"struct MayanCircle.UnlockFeeMsg","name":"unlockMsg","type":"tuple"},{"components":[{"internalType":"uint8","name":"action","type":"uint8"},{"internalType":"uint8","name":"payloadType","type":"uint8"},{"internalType":"uint64","name":"cctpNonce","type":"uint64"},{"internalType":"uint32","name":"cctpDomain","type":"uint32"},{"internalType":"bytes32","name":"unlockerAddr","type":"bytes32"},{"internalType":"uint64","name":"gasDrop","type":"uint64"},{"internalType":"bytes32","name":"destAddr","type":"bytes32"}],"internalType":"struct MayanCircle.UnlockRefinedFeeMsg","name":"refinedMsg","type":"tuple"}],"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
6101206040523480156200001257600080fd5b5060405162006397380380620063978339810160408190526200003591620001b6565b60016000819055606087811b6001600160601b031990811660a0529087901b16608052805460f085901b6001600160f01b03191660e0526101008490526001600160a01b038681166001600160a81b031990921691909117600160a01b60ff8516021790915560408051632c12192160e01b8152905191881691632c12192191600480820192602092909190829003018186803b158015620000d657600080fd5b505afa158015620000eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000111919062000246565b6001600160a01b0316638d3638f46040518163ffffffff1660e01b815260040160206040518083038186803b1580156200014a57600080fd5b505afa1580156200015f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200018591906200026c565b60e01b6001600160e01b03191660c052505060028054336001600160a01b031990911617905550620002ab92505050565b60008060008060008060c08789031215620001cf578182fd5b8651620001dc8162000292565b6020880151909650620001ef8162000292565b6040880151909550620002028162000292565b606088015190945061ffff811681146200021a578283fd5b608088015160a0890151919450925060ff8116811462000238578182fd5b809150509295509295509295565b60006020828403121562000258578081fd5b8151620002658162000292565b9392505050565b6000602082840312156200027e578081fd5b815163ffffffff8116811462000265578182fd5b6001600160a01b0381168114620002a857600080fd5b50565b60805160601c60a05160601c60c05160e01c60e05160f01c61010051615fde620003b9600039600081816107ab015261271c015260006104e301526000818161052a01528181610ea501528181611558015261205d01526000818161057e0152818161089b01528181610ba001528181610e2c01528181611a9701528181612489015281816124c301528181613153015281816132280152818161351d01526136b501526000818161049c01528181610a2f01528181610cfd01528181610f4d0152818161114d01528181611425015281816118100152818161197401528181611bc901528181611d1801528181611f2a0152818161216d015281816126420152612c940152615fde6000f3fe6080604052600436106102385760003560e01c8063853d2c8311610138578063bedb86fb116100b0578063e2de2a031161007f578063ec4cc7fb11610064578063ec4cc7fb146106e6578063f8a67a6214610779578063fa6a6d361461079957600080fd5b8063e2de2a03146106a0578063e8dfd508146106b357600080fd5b8063bedb86fb14610613578063bf7dc2b214610633578063d0fb020314610660578063e21e2d881461068057600080fd5b80639748cf7c116101075780639be95bb4116100ec5780639be95bb4146105c0578063a0883526146105e0578063b25ea8fb146105f357600080fd5b80639748cf7c1461056c5780639b9490d4146105a057600080fd5b8063853d2c83146104be5780638a261c67146104d15780638d3638f41461051857806393166d0c1461054c57600080fd5b806340e66b16116101cb578063538ee2951161019a5780635c975abb1161017f5780635c975abb14610446578063792921671461047757806384acd1bb1461048a57600080fd5b8063538ee295146103f157806358de7fb41461041157600080fd5b806340e66b1614610364578063452a932014610384578063459656ee146103bc578063472d35b9146103d157600080fd5b8063309cdceb11610207578063309cdceb146102e45780633441b13914610311578063375ef75e146103315780633f46e9141461035157600080fd5b80630431c358146102445780631c59b7fc146102845780632072197f146102af5780632fcb4f04146102c257600080fd5b3661023f57005b600080fd5b34801561025057600080fd5b5061027161025f36600461570b565b60066020526000908152604090205481565b6040519081526020015b60405180910390f35b6102976102923660046154f4565b6107cd565b6040516001600160401b03909116815260200161027b565b6102976102bd366004614eb9565b610db3565b3480156102ce57600080fd5b506102e26102dd366004614dda565b611008565b005b3480156102f057600080fd5b506102716102ff36600461505e565b60076020526000908152604090205481565b34801561031d57600080fd5b506102e261032c366004615699565b611054565b34801561033d57600080fd5b506102e261034c366004615783565b6110c7565b6102e261035f3660046152b6565b61113e565b34801561037057600080fd5b506102e261037f3660046154a8565b611416565b34801561039057600080fd5b506002546103a4906001600160a01b031681565b6040516001600160a01b03909116815260200161027b565b3480156103c857600080fd5b506102e26116d5565b3480156103dd57600080fd5b506102e26103ec366004614dda565b611723565b3480156103fd57600080fd5b506102e261040c36600461581d565b61176f565b34801561041d57600080fd5b5061043161042c366004615661565b6117b9565b60405163ffffffff909116815260200161027b565b34801561045257600080fd5b5060035461046790600160a01b900460ff1681565b604051901515815260200161027b565b6102976104853660046157a0565b611802565b34801561049657600080fd5b506103a47f000000000000000000000000000000000000000000000000000000000000000081565b6102976104cc366004615076565b611a2b565b3480156104dd57600080fd5b506105057f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff909116815260200161027b565b34801561052457600080fd5b506104317f000000000000000000000000000000000000000000000000000000000000000081565b34801561055857600080fd5b506102e2610567366004614f64565b611dd2565b34801561057857600080fd5b506103a47f000000000000000000000000000000000000000000000000000000000000000081565b3480156105ac57600080fd5b506102e26105bb36600461539f565b611f1b565b3480156105cc57600080fd5b506102976105db366004614e53565b6123f2565b6102e26105ee3660046151eb565b612633565b3480156105ff57600080fd5b506102e261060e3660046156dc565b612b4e565b34801561061f57600080fd5b506102e261062e366004615026565b612b84565b34801561063f57600080fd5b5061027161064e366004615661565b60056020526000908152604090205481565b34801561066c57600080fd5b506001546103a4906001600160a01b031681565b34801561068c57600080fd5b506102e261069b366004615743565b612bcc565b6102e26106ae3660046150df565b612c85565b3480156106bf57600080fd5b506001546106d490600160a01b900460ff1681565b60405160ff909116815260200161027b565b3480156106f257600080fd5b506107436107013660046157e5565b60046020526000908152604090208054600182015460029092015490916001600160401b03811691680100000000000000009091046001600160a01b03169084565b604080519485526001600160401b0390931660208501526001600160a01b0390911691830191909152606082015260800161027b565b34801561078557600080fd5b506102e2610794366004614e12565b612f5b565b3480156107a557600080fd5b506102717f000000000000000000000000000000000000000000000000000000000000000081565b60006107d7612f99565b600354600160a01b900460ff1615610802576040516313d0ff5960e31b815260040160405180910390fd5b81602001518261010001516001600160401b031610610834576040516308fefc0560e21b815260040160405180910390fd5b60a08201511580156108535750600082604001516001600160401b0316115b1561087157604051636e51edcd60e11b815260040160405180910390fd5b60208201518251610891916001600160a01b039091169033903090612ff3565b6108c682600001517f000000000000000000000000000000000000000000000000000000000000000084602001516001613073565b60006108e7836000015184602001516108e286608001516117b9565b613140565b9050606483610140015160ff16111561091357604051637940035960e11b815260040160405180910390fd5b6001546020840151845160a0860151608087015161014088015160405162bec7bb60e21b81526001600160401b0390951660048601526001600160a01b039384166024860152604485019290925261ffff16606484015260ff16608483015260009216906302fb1eec9060a401602060405180830381600087803b15801561099a57600080fd5b505af11580156109ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d29190615839565b905060648160ff1611156109f957604051631752ff0760e31b815260040160405180910390fd5b604080516101c081018252600180825260208083019190915233828401528251634d4502c960e11b8152925160009360608401927f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031692639a8a0592926004808201939291829003018186803b158015610a7a57600080fd5b505afa158015610a8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab2919061567d565b61ffff16815260200186600001516001600160a01b031660001b815260200186602001516001600160401b0316815260200186606001518152602001866080015161ffff1681526020018660a0015181526020018660c001516001600160401b0316815260200186604001516001600160401b031681526020018661010001516001600160401b031681526020018660e001516001600160401b0316815260200186610120015181525090506000610b6982613305565b90506000604051806080016040528088610140015160ff1681526020018560ff168152602001866001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632c1219216040518163ffffffff1660e01b815260040160206040518083038186803b158015610bf757600080fd5b505afa158015610c0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2f9190614df6565b6001600160a01b0316638d3638f46040518163ffffffff1660e01b815260040160206040518083038186803b158015610c6757600080fd5b505afa158015610c7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9f9190615727565b63ffffffff1690529050610cbc610cb582613386565b83906133f3565b915060008280519060200120604051602001610cda91815260200190565b60408051808303601f19018152908290526001546358cd21bf60e11b83529092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163b19a437e913491610d4a916000918791600160a01b900460ff1690600401615ba0565b6020604051808303818588803b158015610d6357600080fd5b505af1158015610d77573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610d9c9190615801565b9650505050505050610dae6001600055565b919050565b6000610dbd612f99565b600354600160a01b900460ff1615610de8576040516313d0ff5960e31b815260040160405180910390fd5b87876001600160401b031610610e11576040516308fefc0560e21b815260040160405180910390fd5b610e266001600160a01b038a1633308b612ff3565b610e53897f00000000000000000000000000000000000000000000000000000000000000008a6001613073565b6000610e608a8a87613140565b905060008460ff1660021415610e795750825160208401205b60408051610140810182526003815260ff871660208201526001600160401b03848116928201929092527f000000000000000000000000000000000000000000000000000000000000000063ffffffff1660608201526080810189905289821660a08201528a821660c0820152908b1660e08201526001600160a01b038c1661010082015261012081018290526000610f1182613477565b8051602091820120604051610f2a920190815260200190565b60408051808303601f19018152908290526001546358cd21bf60e11b83529092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163b19a437e913491610f9a916000918791600160a01b900460ff1690600401615ba0565b6020604051808303818588803b158015610fb357600080fd5b505af1158015610fc7573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610fec9190615801565b945050505050610ffc6001600055565b98975050505050505050565b6002546001600160a01b03163314611032576040516282b42960e81b815260040160405180910390fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b0316331461107e576040516282b42960e81b815260040160405180910390fd5b61ffff8216600090815260056020526040902054156110b05760405163a741a04560e01b815260040160405180910390fd5b61ffff909116600090815260056020526040902055565b6002546001600160a01b031633146110f1576040516282b42960e81b815260040160405180910390fd5b63ffffffff8216600090815260066020526040902054156111255760405163a741a04560e01b815260040160405180910390fd5b63ffffffff909116600090815260066020526040902055565b611146612f99565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c0fd8bde896040518263ffffffff1660e01b81526004016111979190615b5f565b60006040518083038186803b1580156111af57600080fd5b505afa1580156111c3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111eb9190810190615510565b92509250925081819061121a5760405162461bcd60e51b81526004016112119190615b5f565b60405180910390fd5b5061122d836080015184606001516134c6565b60008061123a89896134f9565b91509150600061124b888b89613876565b9050600061125882613305565b9050600060405180608001604052808b610140015160ff1681526020018a6040015160ff168152602001611296600c8f6139c690919063ffffffff16565b6001600160401b031681526020016112af8e6004613a2c565b63ffffffff16905290506112c5610cb582613386565b91508760e001515160201415806112f1575060e08801516112e7906000613a92565b8251602084012014155b1561130f57604051637c6953f960e01b815260040160405180910390fd5b428361018001516001600160401b03161061133d576040516354a36da760e11b815260040160405180910390fd5b60006113588461014001516001600160401b03166012613af8565b905080341461137a57604051636e51edcd60e11b815260040160405180910390fd5b60006113898560c00151613b30565b9050811561139d5761139d81836000613b5f565b6101608501516113c2906001600160a01b0389169033906001600160401b0316613bde565b6113f1818661016001516001600160401b0316886113e09190615e6a565b6001600160a01b038a169190613bde565b6113fb8e87613c0e565b5050505050505050505061140f6001600055565b5050505050565b61141e612f99565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c0fd8bde866040518263ffffffff1660e01b815260040161146f9190615b5f565b60006040518083038186803b15801561148757600080fd5b505afa15801561149b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526114c39190810190615510565b9250925092508181906114e95760405162461bcd60e51b81526004016112119190615b5f565b506114fc836080015184606001516134c6565b60048452600061150b85613c77565b8051906020012090508360e00151516020141580611538575060e0840151611534906000613a92565b8114155b1561155657604051637c6953f960e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff16856060015163ffffffff16146115a6576040516375893cc160e11b815260040160405180910390fd5b6040858101516001600160401b0390811660009081526004602090815290839020835160808101855281548152600182015493841692810192909252680100000000000000009092046001600160a01b03169281019290925260020154606082018190526116275760405163af61069360e01b815260040160405180910390fd5b80602001516001600160401b03168660a001516001600160401b0316101561166257604051636e51edcd60e11b815260040160405180910390fd5b61168c6116728760800151613b30565b606083015160408401516001600160a01b03169190613bde565b5050506040808401516001600160401b0316600090815260046020529081208181556001810180546001600160e01b031916905560020155506116d190506001600055565b5050565b6003546001600160a01b031633146116ff576040516282b42960e81b815260040160405180910390fd5b600354600280546001600160a01b0319166001600160a01b03909216919091179055565b6002546001600160a01b0316331461174d576040516282b42960e81b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b03163314611799576040516282b42960e81b815260040160405180910390fd5b6001805460ff909216600160a01b0260ff60a01b19909216919091179055565b61ffff811660009081526008602052604090205463ffffffff16806117f157604051638ad6d34360e01b815260040160405180910390fd5b6117fc600182615e81565b92915050565b600061180c612f99565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631a90a2196040518163ffffffff1660e01b815260040160206040518083038186803b15801561186757600080fd5b505afa15801561187b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189f91906156c4565b9050803411156118c6576118c66118b585613b30565b6118bf8334615e6a565b6000613b5f565b6040805160e0810190915260009080600560ff1681526001602082015263ffffffff808a166040830152881660608201526080810186905260a00161191561190e8534615e6a565b6012613cff565b6001600160401b031681526020018690529050600061193382613d2d565b90506000818051906020012060405160200161195191815260200190565b60408051808303601f19018152908290526001546358cd21bf60e11b83529092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163b19a437e9187916119c1916000918791600160a01b900460ff1690600401615ba0565b6020604051808303818588803b1580156119da57600080fd5b505af11580156119ee573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611a139190615801565b945050505050611a236001600055565b949350505050565b6000611a35612f99565b6000611a42856004613a2c565b90506000611a5186600c6139c6565b90506000611a68611a63886098613a92565b613b30565b90506001600160a01b038116301415611a935760405162bc52d160e21b815260040160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632c1219216040518163ffffffff1660e01b815260040160206040518083038186803b158015611aee57600080fd5b505afa158015611b02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b269190614df6565b6001600160a01b03166357ecfd2889896040518363ffffffff1660e01b8152600401611b53929190615b72565b602060405180830381600087803b158015611b6d57600080fd5b505af1158015611b81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba59190615042565b905080611bc55760405163605c687360e01b815260040160405180910390fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631a90a2196040518163ffffffff1660e01b815260040160206040518083038186803b158015611c2057600080fd5b505afa158015611c34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c5891906156c4565b905080341115611c7057611c70836118bf8334615e6a565b6040805160c0810190915260009080600460ff168152600160208201526001600160401b038716604082015263ffffffff88166060820152608081018a905260a001611cbf61190e8534615e6a565b6001600160401b0316905290506000611cd782613c77565b905060008180519060200120604051602001611cf591815260200190565b60408051808303601f19018152908290526001546358cd21bf60e11b83529092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163b19a437e918791611d65916000918791600160a01b900460ff1690600401615ba0565b6020604051808303818588803b158015611d7e57600080fd5b505af1158015611d92573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611db79190615801565b98505050505050505050611dcb6001600055565b9392505050565b6002546001600160a01b03163314611dfc576040516282b42960e81b815260040160405180910390fd5b60005b8251811015611f165760086000848381518110611e2c57634e487b7160e01b600052603260045260246000fd5b60209081029190910181015161ffff1682528101919091526040016000205463ffffffff1615611e6f5760405163a741a04560e01b815260040160405180910390fd5b818181518110611e8f57634e487b7160e01b600052603260045260246000fd5b60200260200101516001611ea39190615cf3565b60086000858481518110611ec757634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff1661ffff16815260200190815260200160002060006101000a81548163ffffffff021916908363ffffffff1602179055508080611f0e90615ef5565b915050611dff565b505050565b611f23612f99565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c0fd8bde886040518263ffffffff1660e01b8152600401611f749190615b5f565b60006040518083038186803b158015611f8c57600080fd5b505afa158015611fa0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611fc89190810190615510565b925092509250818190611fee5760405162461bcd60e51b81526004016112119190615b5f565b50612001836080015184606001516134c6565b60048552600061201086613c77565b8051906020012090508360e0015151602014158061203d575060e0840151612039906000613a92565b8114155b1561205b57604051637c6953f960e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff16866060015163ffffffff16146120ab576040516375893cc160e11b815260040160405180910390fd5b6040868101516001600160401b0390811660009081526004602090815290839020835160808101855281548152600182015493841692810192909252680100000000000000009092046001600160a01b031692810192909252600201546060820181905261212c5760405163af61069360e01b815260040160405180910390fd5b80602001516001600160401b03168760a001516001600160401b03161061216657604051634a7f394f60e01b815260040160405180910390fd5b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c0fd8bde8c6040518263ffffffff1660e01b81526004016121b79190615b5f565b60006040518083038186803b1580156121cf57600080fd5b505afa1580156121e3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261220b9190810190615510565b9250925092508181906122315760405162461bcd60e51b81526004016112119190615b5f565b50612244836080015184606001516134c6565b6005895260006122538a613d2d565b8051906020012090508360e00151516020141580612280575060e084015161227c906000613a92565b8114155b1561229e57604051637c6953f960e01b815260040160405180910390fd5b845160c08b0151146122c257604051620fd39f60e51b815260040160405180910390fd5b8a604001516001600160401b03168a604001516001600160401b0316146122fc57604051633ab3447f60e11b815260040160405180910390fd5b8a6060015163ffffffff168a6060015163ffffffff1614612330576040516375893cc160e11b815260040160405180910390fd5b84602001516001600160401b03168b60a001518b60a001516123529190615d1b565b6001600160401b0316101561237a57604051636e51edcd60e11b815260040160405180910390fd5b6123a461238a8b60800151613b30565b606087015160408801516001600160a01b03169190613bde565b5050506040808901516001600160401b0316600090815260046020529081208181556001810180546001600160e01b031916905560020155506123ec94506134709350505050565b50505050565b60006123fc612f99565b600354600160a01b900460ff1615612427576040516313d0ff5960e31b815260040160405180910390fd5b6001600160a01b0319821615612450576040516375893cc160e11b815260040160405180910390fd5b8361246e576040516308fefc0560e21b815260040160405180910390fd5b6124836001600160a01b038816333089612ff3565b6124b9877f00000000000000000000000000000000000000000000000000000000000000006124b2878a615e6a565b6001613073565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663f856ddb66124f28689615e6a565b85858b6124fe89613dc3565b6040516001600160e01b031960e088901b168152600481019590955263ffffffff93909316602485015260448401919091526001600160a01b03166064830152608482015260a401602060405180830381600087803b15801561256057600080fd5b505af1158015612574573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125989190615801565b604080516080810182528481526001600160401b0380891660208084019182526001600160a01b03808e16858701908152606086018c81528589166000908152600490945296909220945185559151600185018054925190931668010000000000000000026001600160e01b0319909216931692909217919091179055905160029091015590506126296001600055565b9695505050505050565b61263b612f99565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c0fd8bde886040518263ffffffff1660e01b815260040161268c9190615b5f565b60006040518083038186803b1580156126a457600080fd5b505afa1580156126b8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526126e09190810190615510565b9250925092508181906127065760405162461bcd60e51b81526004016112119190615b5f565b50606083015161ffff16600114158061274357507f0000000000000000000000000000000000000000000000000000000000000000836080015114155b1561276157604051632c6bb35560e01b815260040160405180910390fd5b600061276d878b613df7565b9050428161014001516001600160401b0316101561279e576040516354a36da760e11b815260040160405180910390fd5b6127ac816102000151613b30565b6001600160a01b0316336001600160a01b0316146127dc576040516282b42960e81b815260040160405180910390fd5b60006127e782613f9d565b90508460e0015151602014158061280d575060e0850151612809906000613a92565b8114155b1561282b57604051637c6953f960e01b815260040160405180910390fd5b6000806128388d8d6134f9565b61012086015191935091506001600160401b03161561287657610120840151612876906001600160a01b0384169033906001600160401b0316613bde565b60006128858560c00151613b30565b90506128ad838b8761012001516001600160401b0316856128a69190615e6a565b6000613073565b60006001600160a01b0382166128c457504761293e565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a082319060240160206040518083038186803b15801561290357600080fd5b505afa158015612917573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061293b91906156c4565b90505b6000808c6001600160a01b031660008d60405161295b9190615881565b60006040518083038185875af1925050503d8060008114612998576040519150601f19603f3d011682016040523d82523d6000602084013e61299d565b606091505b50915091508181906129c25760405162461bcd60e51b81526004016112119190615b5f565b506001600160a01b0384166129e2576129db8347615e6a565b9250612a68565b6040516370a0823160e01b815230600482015283906001600160a01b038616906370a082319060240160206040518083038186803b158015612a2357600080fd5b505afa158015612a37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a5b91906156c4565b612a659190615e6a565b92505b60006001600160a01b038516612a8057506012612a8c565b612a8985614028565b90505b6000612aa58a60e001516001600160401b031683613af8565b905080851015612ac8576040516309d2d38b60e31b815260040160405180910390fd5b612ad38a87876140d8565b6101e08a01516101c08b01516040805163ffffffff90931683526001600160401b03909116602083015281018690527fcc5626df3b699006387b64eca775dbdfecd5ae542e2d6ab22923082e1320dfcb9060600160405180910390a150505050505050505050505050612b466001600055565b505050505050565b6002546001600160a01b03163314612b78576040516282b42960e81b815260040160405180910390fd5b6116d181836001613b5f565b6002546001600160a01b03163314612bae576040516282b42960e81b815260040160405180910390fd5b60038054911515600160a01b0260ff60a01b19909216919091179055565b6002546001600160a01b03163314612bf6576040516282b42960e81b815260040160405180910390fd5b6040516001600160e01b031960e085901b1660208201526bffffffffffffffffffffffff19606084901b16602482015260009060380160408051601f1981840301815291815281516020928301206000818152600790935291205490915015612c725760405163a741a04560e01b815260040160405180910390fd5b6000908152600760205260409020555050565b612c8d612f99565b60008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c0fd8bde866040518263ffffffff1660e01b8152600401612cde9190615b5f565b60006040518083038186803b158015612cf657600080fd5b505afa158015612d0a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d329190810190615510565b925092509250818190612d585760405162461bcd60e51b81526004016112119190615b5f565b50612d6b836080015184606001516134c6565b30612d7a611a63896098613a92565b6001600160a01b031614612da05760405162bc52d160e21b815260040160405180910390fd5b6000612dac858961438d565b90506000612db982613477565b8051906020012090508460e00151516020141580612de6575060e0850151612de2906000613a92565b8114155b15612e0457604051637c6953f960e01b815260040160405180910390fd5b816020015160ff166002148015612e395750612e238260800151613b30565b6001600160a01b0316336001600160a01b031614155b15612e56576040516282b42960e81b815260040160405180910390fd5b600080612e638b8b6134f9565b91509150808460c001516001600160401b03161115612e95576040516308fefc0560e21b815260040160405180910390fd5b612ead33838660c001516001600160401b0316614499565b6000612ebc8560800151613b30565b9050612eec818660c001516001600160401b031684612edb9190615e6a565b6001600160a01b0386169190613bde565b60a08501516001600160401b031615612f49576000612f198660a001516001600160401b03166012613af8565b9050803414612f3b57604051636e51edcd60e11b815260040160405180910390fd5b612f4782826000613b5f565b505b50505050505050506123ec6001600055565b6002546001600160a01b03163314612f85576040516282b42960e81b815260040160405180910390fd5b611f166001600160a01b0384168284613bde565b60026000541415612fec5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611211565b6002600055565b6040516001600160a01b03808516602483015283166044820152606481018290526123ec9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152614590565b604051636eb1769f60e11b81523060048201526001600160a01b038481166024830152859160009183169063dd62ed3e9060440160206040518083038186803b1580156130bf57600080fd5b505afa1580156130d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130f791906156c4565b905083811015612b4657801561311c5761311c6001600160a01b038316866000614678565b612b46858461312b578561312f565b6000195b6001600160a01b0385169190614678565b600063ffffffff821660081415613226577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636fd3504e848461318c86896147a3565b6040516001600160e01b031960e086901b168152600481019390935263ffffffff91909116602483015260448201526001600160a01b0387166064820152608401602060405180830381600087803b1580156131e757600080fd5b505af11580156131fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061321f9190615801565b9050611dcb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f856ddb6848461326186896147a3565b8861326b88613dc3565b6040516001600160e01b031960e088901b168152600481019590955263ffffffff93909316602485015260448401919091526001600160a01b03166064830152608482015260a401602060405180830381600087803b1580156132cd57600080fd5b505af11580156132e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a239190615801565b6060816000015182602001518360400151846060015185608001518660a001518760c001518860e001518961010001518a61012001518b61014001518c61016001518d61018001518e6101a001516040516020016133709e9d9c9b9a9998979695949392919061589d565b6040516020818303038152906040529050919050565b60608160000151826020015183604001518460600151604051602001613370949392919060f894851b6001600160f81b031990811682529390941b909216600184015260c01b6001600160c01b031916600283015260e01b6001600160e01b031916600a820152600e0190565b6060806040519050835180825260208201818101602087015b8183101561342457805183526020928301920161340c565b50855184518101855292509050808201602086015b81831015613451578051835260209283019201613439565b508651929092011591909101601f01601f191660405250905092915050565b6001600055565b6060816000015182602001518360400151846060015185608001518660a001518760c001518860e001518961010001518a61012001516040516020016133709a99989796959493929190615ac9565b61ffff811660009081526005602052604090205482146116d157604051632c6bb35560e01b815260040160405180910390fd5b60008080613508856004613a2c565b90506000613517866078613a92565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663cb75c11c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561357457600080fd5b505afa158015613588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135ac9190614df6565b604051633c502b2f60e11b815263ffffffff85166004820152602481018490526001600160a01b0391909116906378a0565e9060440160206040518083038186803b1580156135fa57600080fd5b505afa15801561360e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136329190614df6565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b15801561367757600080fd5b505afa15801561368b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136af91906156c4565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632c1219216040518163ffffffff1660e01b815260040160206040518083038186803b15801561370c57600080fd5b505afa158015613720573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137449190614df6565b6001600160a01b03166357ecfd288a8a6040518363ffffffff1660e01b8152600401613771929190615b72565b602060405180830381600087803b15801561378b57600080fd5b505af115801561379f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c39190615042565b9050806137e35760405163605c687360e01b815260040160405180910390fd5b6040516370a0823160e01b815230600482015282906001600160a01b038516906370a082319060240160206040518083038186803b15801561382457600080fd5b505afa158015613838573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061385c91906156c4565b6138669190615e6a565b9299929850919650505050505050565b604080516101c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a0810191909152604080516101c0810190915280600160ff16815260016020808301919091528451604083015284015161ffff166060820152608001613927856078613a92565b81526020016139378560d06139c6565b6001600160401b0316815260200185606001518152602001856080015161ffff1681526020018560a0015181526020018560c001516001600160401b0316815260200185604001516001600160401b031681526020018561010001516001600160401b031681526020018560e001516001600160401b0316815260200185610120015181525090509392505050565b60006139d3826008615cdb565b83511015613a235760405162461bcd60e51b815260206004820152601460248201527f746f55696e7436345f6f75744f66426f756e64730000000000000000000000006044820152606401611211565b50016008015190565b6000613a39826004615cdb565b83511015613a895760405162461bcd60e51b815260206004820152601460248201527f746f55696e7433325f6f75744f66426f756e64730000000000000000000000006044820152606401611211565b50016004015190565b6000613a9f826020615cdb565b83511015613aef5760405162461bcd60e51b815260206004820152601560248201527f746f427974657333325f6f75744f66426f756e647300000000000000000000006044820152606401611211565b50016020015190565b600060088260ff161115613b2957613b11600883615ea6565b613b1c90600a615da0565b613b269084615e4b565b92505b5090919050565b60006001600160a01b0319821615613b5b5760405163e6c4247b60e01b815260040160405180910390fd5b5090565b6000836001600160a01b03168360405160006040518083038185875af1925050503d8060008114613bac576040519150601f19603f3d011682016040523d82523d6000602084013e613bb1565b606091505b5050905081156123ec576001811515146123ec57604051630db2c7f160e31b815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052611f1690849063a9059cbb60e01b90606401613027565b7f4f7c61703b83b54f1af0ca9b67d73dc13cc2e91262faf81b0a4927cbce924239613c3a836004613a2c565b613c4584600c6139c6565b6040805163ffffffff90931683526001600160401b039091166020830152810183905260600160405180910390a15050565b8051602080830151604080850151606080870151608088015160a0890151945160f898891b6001600160f81b0319908116988201989098529590971b909516602185015260c091821b6001600160c01b0319908116602286015260e09590951b6001600160e01b031916602a850152602e8401959095521b909116604e820152605601613370565b600060088260ff161115613b2957613d18600883615ea6565b613d2390600a615da0565b613b269084615d3d565b8051602080830151604080850151606086810151608088015160a089015160c0808b015196516001600160f81b031960f89b8c1b81169a82019a909a529790991b90971660218701526001600160c01b031993881b841660228701526001600160e01b031960e09290921b91909116602a860152602e8501529390941b909316604e820152605681019290925290607601613370565b63ffffffff811660009081526006602052604090205480610dae5760405163133bff2160e21b815260040160405180910390fd5b60408051610220808201835260008083526020808401829052838501829052606084018290526080840182905260a0840182905260c0840182905260e08401829052610100840182905261012084018290526101408401829052610160840182905261018084018290526101a084018290526101c084018290526101e08401829052610200840191909152835191820184526002825260019082015290918101613ea2846078613a92565b8152602001613eb28460d06139c6565b6001600160401b0316815260200184600001518152602001846020015161ffff1681526020018460400151815260200184606001516001600160401b0316815260200184608001516001600160401b031681526020018460a001516001600160401b031681526020018460c001516001600160401b031681526020018460e00151815260200184610100015160ff16815260200184610120015160ff168152602001613f68600c856139c690919063ffffffff16565b6001600160401b03168152602001613f81846004613a2c565b63ffffffff168152602001846101400151815250905092915050565b600080613fa98361481d565b90506000614018846101c00151856101e001518661020001516040516020016140019392919060c09390931b6001600160c01b031916835260e09190911b6001600160e01b0319166008830152600c820152602c0190565b60408051601f1981840301815291905283906133f3565b8051602090910120949350505050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663313ce56760e01b179052905160009182916001600160a01b0385169161408091615881565b600060405180830381855afa9150503d80600081146140bb576040519150601f19603f3d011682016040523d82523d6000602084013e6140c0565b606091505b5091505080806020019051810190611dcb9190615839565b60006140e8846101600151613b30565b905060006001600160a01b0382161580159061410b575061018085015160ff1615155b156141345761271085610180015160ff16846141279190615e4b565b6141319190615d3d565b90505b6000856101a0015160ff1660001461416a57612710866101a0015160ff168561415d9190615e4b565b6141679190615d3d565b90505b60006141798760800151613b30565b90506001600160a01b03861661424c57821561419b5761419b84846000613b5f565b811561422757600154604080516331056e5760e21b81529051614227926001600160a01b03169163c415b95c916004808301926020929190829003018186803b1580156141e757600080fd5b505afa1580156141fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061421f9190614df6565b836000613b5f565b61424781836142368689615e6a565b6142409190615e6a565b6001613b5f565b614384565b6101008701516001600160401b0316156142ab57600061427b8861010001516001600160401b03166012613af8565b905080341461429d57604051636e51edcd60e11b815260040160405180910390fd5b6142a982826000613b5f565b505b82156142c5576142c56001600160a01b0387168585613bde565b811561435a57600154604080516331056e5760e21b8152905161435a926001600160a01b03169163c415b95c916004808301926020929190829003018186803b15801561431157600080fd5b505afa158015614325573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143499190614df6565b6001600160a01b0388169084613bde565b61438481836143698689615e6a565b6143739190615e6a565b6001600160a01b0389169190613bde565b50505050505050565b60408051610140808201835260008083526020808401829052838501829052606084018290526080840182905260a0840182905260c0840182905260e0840182905261010084018290526101208401919091528351918201845260038252855160ff16908201529091810161440384600c6139c6565b6001600160401b0316815260200161441c846004613a2c565b63ffffffff1681526020018460200151815260200184604001516001600160401b0316815260200184606001516001600160401b0316815260200161446b60d0856139c690919063ffffffff16565b6001600160401b03168152602001614484846078613a92565b81526020018460c00151815250905092915050565b60015460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018390529083169063a9059cbb90604401602060405180830381600087803b1580156144e757600080fd5b505af11580156144fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061451f9190615042565b50600154604051631c43245560e01b81526001600160a01b03858116600483015284811660248301526044820184905290911690631c43245590606401600060405180830381600087803b15801561457657600080fd5b505af1925050508015614587575060015b611f1657505050565b60006145e5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166148889092919063ffffffff16565b90508051600014806146065750808060200190518101906146069190615042565b611f165760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611211565b8015806147015750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156146c757600080fd5b505afa1580156146db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146ff91906156c4565b155b6147735760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401611211565b6040516001600160a01b038316602482015260448101829052611f1690849063095ea7b360e01b90606401613027565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff191660248301528251601881840301815260389092018352815191810191909120600090815260079091529081205480611dcb57604051626130e960e01b815260040160405180910390fd5b6060816000015182602001518360400151846060015185608001518660a001518760c001518860e001518961010001518a61012001518b61014001518c61016001518d61018001518e6101a001516040516020016133709e9d9c9b9a999897969594939291906159aa565b6060611a23848460008585600080866001600160a01b031685876040516148af9190615881565b60006040518083038185875af1925050503d80600081146148ec576040519150601f19603f3d011682016040523d82523d6000602084013e6148f1565b606091505b50915091506149028783838761490d565b979650505050505050565b60608315614979578251614972576001600160a01b0385163b6149725760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611211565b5081611a23565b611a23838381511561498e5781518083602001fd5b8060405162461bcd60e51b81526004016112119190615b5f565b8035610dae81615f3c565b600082601f8301126149c3578081fd5b815160206149d86149d383615c91565b615c61565b80838252828201915082860187848660071b89010111156149f7578586fd5b855b85811015614a5e57608080838b031215614a11578788fd5b614a19615bd2565b835181528684015187820152604080850151614a3481615f99565b90820152606084810151614a4781615f99565b9082015285529385019391909101906001016149f9565b5090979650505050505050565b600082601f830112614a7b578081fd5b81356020614a8b6149d383615c91565b80838252828201915082860187848660051b8901011115614aaa578586fd5b855b85811015614a5e578135614abf81615f72565b84529284019290840190600101614aac565b8051610dae81615f54565b600082601f830112614aec578081fd5b8135614afa6149d382615cb4565b818152846020838601011115614b0e578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112614b38578081fd5b8151614b466149d382615cb4565b818152846020838601011115614b5a578283fd5b611a23826020830160208701615ec9565b60006101608284031215614b7d578081fd5b614b85615bfa565b905081358152614b9760208301614d8d565b602082015260408201356040820152614bb260608301614dae565b6060820152614bc360808301614dae565b6080820152614bd460a08301614dae565b60a0820152614be560c08301614dae565b60c082015260e082013560e0820152610100614c02818401614dc4565b90820152610120614c14838201614dc4565b818301525061014080830135818301525092915050565b60006101608284031215614c3d578081fd5b614c45615bfa565b9050614c50826149a8565b815260208201356020820152614c6860408301614dae565b604082015260608201356060820152614c8360808301614d8d565b608082015260a082013560a0820152614c9e60c08301614dae565b60c0820152614caf60e08301614dae565b60e0820152610100614cc2818401614dae565b908201526101208281013590820152610140614cdf818401614dc4565b9082015292915050565b600060c08284031215614cfa578081fd5b60405160c081018181106001600160401b0382111715614d1c57614d1c615f26565b6040529050808235614d2d81615f99565b81526020830135614d3d81615f99565b60208201526040830135614d5081615f84565b60408201526060830135614d6381615f72565b60608201526080838101359082015260a0830135614d8081615f84565b60a0919091015292915050565b8035610dae81615f62565b8051610dae81615f62565b8051610dae81615f72565b8035610dae81615f84565b8051610dae81615f84565b8035610dae81615f99565b8051610dae81615f99565b600060208284031215614deb578081fd5b8135611dcb81615f3c565b600060208284031215614e07578081fd5b8151611dcb81615f3c565b600080600060608486031215614e26578182fd5b8335614e3181615f3c565b9250602084013591506040840135614e4881615f3c565b809150509250925092565b60008060008060008060c08789031215614e6b578384fd5b8635614e7681615f3c565b9550602087013594506040870135614e8d81615f84565b9350606087013592506080870135614ea481615f72565b8092505060a087013590509295509295509295565b600080600080600080600080610100898b031215614ed5578586fd5b8835614ee081615f3c565b9750602089013596506040890135614ef781615f84565b95506060890135614f0781615f84565b94506080890135935060a0890135614f1e81615f72565b925060c0890135614f2e81615f99565b915060e08901356001600160401b03811115614f48578182fd5b614f548b828c01614adc565b9150509295985092959890939650565b60008060408385031215614f76578182fd5b82356001600160401b0380821115614f8c578384fd5b818501915085601f830112614f9f578384fd5b81356020614faf6149d383615c91565b8083825282820191508286018a848660051b8901011115614fce578889fd5b8896505b84871015614ff9578035614fe581615f62565b835260019690960195918301918301614fd2565b509650508601359250508082111561500f578283fd5b5061501c85828601614a6b565b9150509250929050565b600060208284031215615037578081fd5b8135611dcb81615f54565b600060208284031215615053578081fd5b8151611dcb81615f54565b60006020828403121561506f578081fd5b5035919050565b60008060006060848603121561508a578081fd5b83356001600160401b03808211156150a0578283fd5b6150ac87838801614adc565b945060208601359150808211156150c1578283fd5b506150ce86828701614adc565b925050604084013590509250925092565b6000806000808486036101408112156150f6578283fd5b85356001600160401b038082111561510c578485fd5b61511889838a01614adc565b9650602088013591508082111561512d578485fd5b61513989838a01614adc565b9550604088013591508082111561514e578485fd5b5061515b88828901614adc565b93505060e0605f198201121561516f578182fd5b50615178615c1d565b606086013561518681615f99565b81526080860135602082015260a08601356151a081615f84565b604082015260c08601356151b381615f84565b60608201526151c460e08701614dae565b608082015261010086013560a08201526101209095013560c0860152509194909350909190565b6000806000806000806102008789031215615204578384fd5b86356001600160401b038082111561521a578586fd5b6152268a838b01614adc565b9750602089013591508082111561523b578586fd5b6152478a838b01614adc565b9650604089013591508082111561525c578586fd5b6152688a838b01614adc565b95506152778a60608b01614b6b565b94506152866101c08a016149a8565b93506101e089013591508082111561529c578283fd5b506152a989828a01614adc565b9150509295509295509295565b60008060008060008587036102208112156152cf578384fd5b86356001600160401b03808211156152e5578586fd5b6152f18a838b01614adc565b97506020890135915080821115615306578586fd5b6153128a838b01614adc565b96506040890135915080821115615327578586fd5b5061533489828a01614adc565b9450506153448860608901614c2b565b925060606101bf1982011215615358578182fd5b50615361615c3f565b6101c087013581526101e087013561537881615f62565b602082015261020087013561538c81615f99565b6040820152949793965091945092919050565b6000806000808486036101e08112156153b6578283fd5b85356001600160401b03808211156153cc578485fd5b6153d889838a01614adc565b965060208801359150808211156153ed578485fd5b506153fa88828901614adc565b94505061540a8760408801614ce9565b925060e060ff198201121561541d578182fd5b50615426615c1d565b61010086013561543581615f99565b815261012086013561544681615f99565b602082015261014086013561545a81615f84565b604082015261016086013561546e81615f72565b6060820152610180860135608082015261548b6101a08701614dae565b60a08201526101c086013560c08201528091505092959194509250565b60008060e083850312156154ba578182fd5b82356001600160401b038111156154cf578283fd5b6154db85828601614adc565b9250506154eb8460208501614ce9565b90509250929050565b60006101608284031215615506578081fd5b611dcb8383614c2b565b600080600060608486031215615524578081fd5b83516001600160401b038082111561553a578283fd5b90850190610160828803121561554e578283fd5b615556615bfa565b61555f83614dcf565b815261556d60208401614da3565b602082015261557e60408401614da3565b604082015261558f60608401614d98565b6060820152608083015160808201526155aa60a08401614db9565b60a08201526155bb60c08401614dcf565b60c082015260e0830151828111156155d1578485fd5b6155dd89828601614b28565b60e0830152506101006155f1818501614da3565b908201526101208381015183811115615608578586fd5b6156148a8287016149b3565b91830191909152506101408381015190820152945061563560208701614ad1565b9350604086015191508082111561564a578283fd5b5061565786828701614b28565b9150509250925092565b600060208284031215615672578081fd5b8135611dcb81615f62565b60006020828403121561568e578081fd5b8151611dcb81615f62565b600080604083850312156156ab578182fd5b82356156b681615f62565b946020939093013593505050565b6000602082840312156156d5578081fd5b5051919050565b600080604083850312156156ee578182fd5b82359150602083013561570081615f3c565b809150509250929050565b60006020828403121561571c578081fd5b8135611dcb81615f72565b600060208284031215615738578081fd5b8151611dcb81615f72565b600080600060608486031215615757578081fd5b833561576281615f72565b9250602084013561577281615f3c565b929592945050506040919091013590565b60008060408385031215615795578182fd5b82356156b681615f72565b600080600080608085870312156157b5578182fd5b84356157c081615f72565b935060208501356157d081615f72565b93969395505050506040820135916060013590565b6000602082840312156157f6578081fd5b8135611dcb81615f84565b600060208284031215615812578081fd5b8151611dcb81615f84565b60006020828403121561582e578081fd5b8135611dcb81615f99565b60006020828403121561584a578081fd5b8151611dcb81615f99565b6000815180845261586d816020860160208601615ec9565b601f01601f19169290920160200192915050565b60008251615893818460208701615ec9565b9190910192915050565b60f88f901b6001600160f81b03191681526158c7600182018f60f81b6001600160f81b0319169052565b8c60028201526158e6602282018d60f01b6001600160f01b0319169052565b8a6024820152615905604482018b60c01b6001600160c01b0319169052565b88604c820152615924606c82018960f01b6001600160f01b0319169052565b86606e820152615943608e82018760c01b6001600160c01b0319169052565b61595c609682018660c01b6001600160c01b0319169052565b615975609e82018560c01b6001600160c01b0319169052565b61598e60a682018460c01b6001600160c01b0319169052565b60ae81019190915260ce019d9c50505050505050505050505050565b60f88f901b6001600160f81b03191681526159d4600182018f60f81b6001600160f81b0319169052565b8c60028201526159f3602282018d60c01b6001600160c01b0319169052565b8a602a820152615a12604a82018b60f01b6001600160f01b0319169052565b88604c820152615a31606c82018960c01b6001600160c01b0319169052565b615a4a607482018860c01b6001600160c01b0319169052565b615a63607c82018760c01b6001600160c01b0319169052565b615a7c608482018660c01b6001600160c01b0319169052565b83608c820152615a9b60ac82018460f81b6001600160f81b0319169052565b615ab460ad82018360f81b6001600160f81b0319169052565b60ae019e9d5050505050505050505050505050565b6001600160f81b031960f88c811b821683528b901b1660018201526001600160c01b031960c08a811b821660028401526001600160e01b031960e08b901b16600a840152600e830189905287811b8216602e84015286901b1660368201526000615b42603e83018660c01b6001600160c01b0319169052565b506046810192909252606682015260860198975050505050505050565b602081526000611dcb6020830184615855565b604081526000615b856040830185615855565b8281036020840152615b978185615855565b95945050505050565b63ffffffff84168152606060208201526000615bbf6060830185615855565b905060ff83166040830152949350505050565b604051608081016001600160401b0381118282101715615bf457615bf4615f26565b60405290565b60405161016081016001600160401b0381118282101715615bf457615bf4615f26565b60405160e081016001600160401b0381118282101715615bf457615bf4615f26565b604051606081016001600160401b0381118282101715615bf457615bf4615f26565b604051601f8201601f191681016001600160401b0381118282101715615c8957615c89615f26565b604052919050565b60006001600160401b03821115615caa57615caa615f26565b5060051b60200190565b60006001600160401b03821115615ccd57615ccd615f26565b50601f01601f191660200190565b60008219821115615cee57615cee615f10565b500190565b600063ffffffff808316818516808303821115615d1257615d12615f10565b01949350505050565b60006001600160401b03808316818516808303821115615d1257615d12615f10565b600082615d5857634e487b7160e01b81526012600452602481fd5b500490565b600181815b80851115615d98578160001904821115615d7e57615d7e615f10565b80851615615d8b57918102915b93841c9390800290615d62565b509250929050565b6000611dcb60ff841683600082615db9575060016117fc565b81615dc6575060006117fc565b8160018114615ddc5760028114615de657615e02565b60019150506117fc565b60ff841115615df757615df7615f10565b50506001821b6117fc565b5060208310610133831016604e8410600b8410161715615e25575081810a6117fc565b615e2f8383615d5d565b8060001904821115615e4357615e43615f10565b029392505050565b6000816000190483118215151615615e6557615e65615f10565b500290565b600082821015615e7c57615e7c615f10565b500390565b600063ffffffff83811690831681811015615e9e57615e9e615f10565b039392505050565b600060ff821660ff841680821015615ec057615ec0615f10565b90039392505050565b60005b83811015615ee4578181015183820152602001615ecc565b838111156123ec5750506000910152565b6000600019821415615f0957615f09615f10565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114615f5157600080fd5b50565b8015158114615f5157600080fd5b61ffff81168114615f5157600080fd5b63ffffffff81168114615f5157600080fd5b6001600160401b0381168114615f5157600080fd5b60ff81168114615f5157600080fdfea26469706673582212205ac7d0e9ed298919276884025f98a08fe9bc83d17a3dacd396b608e527e56c1d64736f6c634300080400330000000000000000000000004e744b28e787c3ad0e810ed65a24461d4ac5a762000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018315814095c3ee003c10a905070b33f5a9ad18057cedf16e8192c8d3fc118ec80000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x6080604052600436106102385760003560e01c8063853d2c8311610138578063bedb86fb116100b0578063e2de2a031161007f578063ec4cc7fb11610064578063ec4cc7fb146106e6578063f8a67a6214610779578063fa6a6d361461079957600080fd5b8063e2de2a03146106a0578063e8dfd508146106b357600080fd5b8063bedb86fb14610613578063bf7dc2b214610633578063d0fb020314610660578063e21e2d881461068057600080fd5b80639748cf7c116101075780639be95bb4116100ec5780639be95bb4146105c0578063a0883526146105e0578063b25ea8fb146105f357600080fd5b80639748cf7c1461056c5780639b9490d4146105a057600080fd5b8063853d2c83146104be5780638a261c67146104d15780638d3638f41461051857806393166d0c1461054c57600080fd5b806340e66b16116101cb578063538ee2951161019a5780635c975abb1161017f5780635c975abb14610446578063792921671461047757806384acd1bb1461048a57600080fd5b8063538ee295146103f157806358de7fb41461041157600080fd5b806340e66b1614610364578063452a932014610384578063459656ee146103bc578063472d35b9146103d157600080fd5b8063309cdceb11610207578063309cdceb146102e45780633441b13914610311578063375ef75e146103315780633f46e9141461035157600080fd5b80630431c358146102445780631c59b7fc146102845780632072197f146102af5780632fcb4f04146102c257600080fd5b3661023f57005b600080fd5b34801561025057600080fd5b5061027161025f36600461570b565b60066020526000908152604090205481565b6040519081526020015b60405180910390f35b6102976102923660046154f4565b6107cd565b6040516001600160401b03909116815260200161027b565b6102976102bd366004614eb9565b610db3565b3480156102ce57600080fd5b506102e26102dd366004614dda565b611008565b005b3480156102f057600080fd5b506102716102ff36600461505e565b60076020526000908152604090205481565b34801561031d57600080fd5b506102e261032c366004615699565b611054565b34801561033d57600080fd5b506102e261034c366004615783565b6110c7565b6102e261035f3660046152b6565b61113e565b34801561037057600080fd5b506102e261037f3660046154a8565b611416565b34801561039057600080fd5b506002546103a4906001600160a01b031681565b6040516001600160a01b03909116815260200161027b565b3480156103c857600080fd5b506102e26116d5565b3480156103dd57600080fd5b506102e26103ec366004614dda565b611723565b3480156103fd57600080fd5b506102e261040c36600461581d565b61176f565b34801561041d57600080fd5b5061043161042c366004615661565b6117b9565b60405163ffffffff909116815260200161027b565b34801561045257600080fd5b5060035461046790600160a01b900460ff1681565b604051901515815260200161027b565b6102976104853660046157a0565b611802565b34801561049657600080fd5b506103a47f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d81565b6102976104cc366004615076565b611a2b565b3480156104dd57600080fd5b506105057f000000000000000000000000000000000000000000000000000000000000000181565b60405161ffff909116815260200161027b565b34801561052457600080fd5b506104317f000000000000000000000000000000000000000000000000000000000000000a81565b34801561055857600080fd5b506102e2610567366004614f64565b611dd2565b34801561057857600080fd5b506103a47f0000000000000000000000004e744b28e787c3ad0e810ed65a24461d4ac5a76281565b3480156105ac57600080fd5b506102e26105bb36600461539f565b611f1b565b3480156105cc57600080fd5b506102976105db366004614e53565b6123f2565b6102e26105ee3660046151eb565b612633565b3480156105ff57600080fd5b506102e261060e3660046156dc565b612b4e565b34801561061f57600080fd5b506102e261062e366004615026565b612b84565b34801561063f57600080fd5b5061027161064e366004615661565b60056020526000908152604090205481565b34801561066c57600080fd5b506001546103a4906001600160a01b031681565b34801561068c57600080fd5b506102e261069b366004615743565b612bcc565b6102e26106ae3660046150df565b612c85565b3480156106bf57600080fd5b506001546106d490600160a01b900460ff1681565b60405160ff909116815260200161027b565b3480156106f257600080fd5b506107436107013660046157e5565b60046020526000908152604090208054600182015460029092015490916001600160401b03811691680100000000000000009091046001600160a01b03169084565b604080519485526001600160401b0390931660208501526001600160a01b0390911691830191909152606082015260800161027b565b34801561078557600080fd5b506102e2610794366004614e12565b612f5b565b3480156107a557600080fd5b506102717f8315814095c3ee003c10a905070b33f5a9ad18057cedf16e8192c8d3fc118ec881565b60006107d7612f99565b600354600160a01b900460ff1615610802576040516313d0ff5960e31b815260040160405180910390fd5b81602001518261010001516001600160401b031610610834576040516308fefc0560e21b815260040160405180910390fd5b60a08201511580156108535750600082604001516001600160401b0316115b1561087157604051636e51edcd60e11b815260040160405180910390fd5b60208201518251610891916001600160a01b039091169033903090612ff3565b6108c682600001517f0000000000000000000000004e744b28e787c3ad0e810ed65a24461d4ac5a76284602001516001613073565b60006108e7836000015184602001516108e286608001516117b9565b613140565b9050606483610140015160ff16111561091357604051637940035960e11b815260040160405180910390fd5b6001546020840151845160a0860151608087015161014088015160405162bec7bb60e21b81526001600160401b0390951660048601526001600160a01b039384166024860152604485019290925261ffff16606484015260ff16608483015260009216906302fb1eec9060a401602060405180830381600087803b15801561099a57600080fd5b505af11580156109ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d29190615839565b905060648160ff1611156109f957604051631752ff0760e31b815260040160405180910390fd5b604080516101c081018252600180825260208083019190915233828401528251634d4502c960e11b8152925160009360608401927f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b031692639a8a0592926004808201939291829003018186803b158015610a7a57600080fd5b505afa158015610a8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab2919061567d565b61ffff16815260200186600001516001600160a01b031660001b815260200186602001516001600160401b0316815260200186606001518152602001866080015161ffff1681526020018660a0015181526020018660c001516001600160401b0316815260200186604001516001600160401b031681526020018661010001516001600160401b031681526020018660e001516001600160401b0316815260200186610120015181525090506000610b6982613305565b90506000604051806080016040528088610140015160ff1681526020018560ff168152602001866001600160401b031681526020017f0000000000000000000000004e744b28e787c3ad0e810ed65a24461d4ac5a7626001600160a01b0316632c1219216040518163ffffffff1660e01b815260040160206040518083038186803b158015610bf757600080fd5b505afa158015610c0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2f9190614df6565b6001600160a01b0316638d3638f46040518163ffffffff1660e01b815260040160206040518083038186803b158015610c6757600080fd5b505afa158015610c7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9f9190615727565b63ffffffff1690529050610cbc610cb582613386565b83906133f3565b915060008280519060200120604051602001610cda91815260200190565b60408051808303601f19018152908290526001546358cd21bf60e11b83529092507f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b03169163b19a437e913491610d4a916000918791600160a01b900460ff1690600401615ba0565b6020604051808303818588803b158015610d6357600080fd5b505af1158015610d77573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610d9c9190615801565b9650505050505050610dae6001600055565b919050565b6000610dbd612f99565b600354600160a01b900460ff1615610de8576040516313d0ff5960e31b815260040160405180910390fd5b87876001600160401b031610610e11576040516308fefc0560e21b815260040160405180910390fd5b610e266001600160a01b038a1633308b612ff3565b610e53897f0000000000000000000000004e744b28e787c3ad0e810ed65a24461d4ac5a7628a6001613073565b6000610e608a8a87613140565b905060008460ff1660021415610e795750825160208401205b60408051610140810182526003815260ff871660208201526001600160401b03848116928201929092527f000000000000000000000000000000000000000000000000000000000000000a63ffffffff1660608201526080810189905289821660a08201528a821660c0820152908b1660e08201526001600160a01b038c1661010082015261012081018290526000610f1182613477565b8051602091820120604051610f2a920190815260200190565b60408051808303601f19018152908290526001546358cd21bf60e11b83529092507f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b03169163b19a437e913491610f9a916000918791600160a01b900460ff1690600401615ba0565b6020604051808303818588803b158015610fb357600080fd5b505af1158015610fc7573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610fec9190615801565b945050505050610ffc6001600055565b98975050505050505050565b6002546001600160a01b03163314611032576040516282b42960e81b815260040160405180910390fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b0316331461107e576040516282b42960e81b815260040160405180910390fd5b61ffff8216600090815260056020526040902054156110b05760405163a741a04560e01b815260040160405180910390fd5b61ffff909116600090815260056020526040902055565b6002546001600160a01b031633146110f1576040516282b42960e81b815260040160405180910390fd5b63ffffffff8216600090815260066020526040902054156111255760405163a741a04560e01b815260040160405180910390fd5b63ffffffff909116600090815260066020526040902055565b611146612f99565b60008060007f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b031663c0fd8bde896040518263ffffffff1660e01b81526004016111979190615b5f565b60006040518083038186803b1580156111af57600080fd5b505afa1580156111c3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111eb9190810190615510565b92509250925081819061121a5760405162461bcd60e51b81526004016112119190615b5f565b60405180910390fd5b5061122d836080015184606001516134c6565b60008061123a89896134f9565b91509150600061124b888b89613876565b9050600061125882613305565b9050600060405180608001604052808b610140015160ff1681526020018a6040015160ff168152602001611296600c8f6139c690919063ffffffff16565b6001600160401b031681526020016112af8e6004613a2c565b63ffffffff16905290506112c5610cb582613386565b91508760e001515160201415806112f1575060e08801516112e7906000613a92565b8251602084012014155b1561130f57604051637c6953f960e01b815260040160405180910390fd5b428361018001516001600160401b03161061133d576040516354a36da760e11b815260040160405180910390fd5b60006113588461014001516001600160401b03166012613af8565b905080341461137a57604051636e51edcd60e11b815260040160405180910390fd5b60006113898560c00151613b30565b9050811561139d5761139d81836000613b5f565b6101608501516113c2906001600160a01b0389169033906001600160401b0316613bde565b6113f1818661016001516001600160401b0316886113e09190615e6a565b6001600160a01b038a169190613bde565b6113fb8e87613c0e565b5050505050505050505061140f6001600055565b5050505050565b61141e612f99565b60008060007f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b031663c0fd8bde866040518263ffffffff1660e01b815260040161146f9190615b5f565b60006040518083038186803b15801561148757600080fd5b505afa15801561149b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526114c39190810190615510565b9250925092508181906114e95760405162461bcd60e51b81526004016112119190615b5f565b506114fc836080015184606001516134c6565b60048452600061150b85613c77565b8051906020012090508360e00151516020141580611538575060e0840151611534906000613a92565b8114155b1561155657604051637c6953f960e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000a63ffffffff16856060015163ffffffff16146115a6576040516375893cc160e11b815260040160405180910390fd5b6040858101516001600160401b0390811660009081526004602090815290839020835160808101855281548152600182015493841692810192909252680100000000000000009092046001600160a01b03169281019290925260020154606082018190526116275760405163af61069360e01b815260040160405180910390fd5b80602001516001600160401b03168660a001516001600160401b0316101561166257604051636e51edcd60e11b815260040160405180910390fd5b61168c6116728760800151613b30565b606083015160408401516001600160a01b03169190613bde565b5050506040808401516001600160401b0316600090815260046020529081208181556001810180546001600160e01b031916905560020155506116d190506001600055565b5050565b6003546001600160a01b031633146116ff576040516282b42960e81b815260040160405180910390fd5b600354600280546001600160a01b0319166001600160a01b03909216919091179055565b6002546001600160a01b0316331461174d576040516282b42960e81b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b03163314611799576040516282b42960e81b815260040160405180910390fd5b6001805460ff909216600160a01b0260ff60a01b19909216919091179055565b61ffff811660009081526008602052604090205463ffffffff16806117f157604051638ad6d34360e01b815260040160405180910390fd5b6117fc600182615e81565b92915050565b600061180c612f99565b60007f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b0316631a90a2196040518163ffffffff1660e01b815260040160206040518083038186803b15801561186757600080fd5b505afa15801561187b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189f91906156c4565b9050803411156118c6576118c66118b585613b30565b6118bf8334615e6a565b6000613b5f565b6040805160e0810190915260009080600560ff1681526001602082015263ffffffff808a166040830152881660608201526080810186905260a00161191561190e8534615e6a565b6012613cff565b6001600160401b031681526020018690529050600061193382613d2d565b90506000818051906020012060405160200161195191815260200190565b60408051808303601f19018152908290526001546358cd21bf60e11b83529092507f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b03169163b19a437e9187916119c1916000918791600160a01b900460ff1690600401615ba0565b6020604051808303818588803b1580156119da57600080fd5b505af11580156119ee573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611a139190615801565b945050505050611a236001600055565b949350505050565b6000611a35612f99565b6000611a42856004613a2c565b90506000611a5186600c6139c6565b90506000611a68611a63886098613a92565b613b30565b90506001600160a01b038116301415611a935760405162bc52d160e21b815260040160405180910390fd5b60007f0000000000000000000000004e744b28e787c3ad0e810ed65a24461d4ac5a7626001600160a01b0316632c1219216040518163ffffffff1660e01b815260040160206040518083038186803b158015611aee57600080fd5b505afa158015611b02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b269190614df6565b6001600160a01b03166357ecfd2889896040518363ffffffff1660e01b8152600401611b53929190615b72565b602060405180830381600087803b158015611b6d57600080fd5b505af1158015611b81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba59190615042565b905080611bc55760405163605c687360e01b815260040160405180910390fd5b60007f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b0316631a90a2196040518163ffffffff1660e01b815260040160206040518083038186803b158015611c2057600080fd5b505afa158015611c34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c5891906156c4565b905080341115611c7057611c70836118bf8334615e6a565b6040805160c0810190915260009080600460ff168152600160208201526001600160401b038716604082015263ffffffff88166060820152608081018a905260a001611cbf61190e8534615e6a565b6001600160401b0316905290506000611cd782613c77565b905060008180519060200120604051602001611cf591815260200190565b60408051808303601f19018152908290526001546358cd21bf60e11b83529092507f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b03169163b19a437e918791611d65916000918791600160a01b900460ff1690600401615ba0565b6020604051808303818588803b158015611d7e57600080fd5b505af1158015611d92573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611db79190615801565b98505050505050505050611dcb6001600055565b9392505050565b6002546001600160a01b03163314611dfc576040516282b42960e81b815260040160405180910390fd5b60005b8251811015611f165760086000848381518110611e2c57634e487b7160e01b600052603260045260246000fd5b60209081029190910181015161ffff1682528101919091526040016000205463ffffffff1615611e6f5760405163a741a04560e01b815260040160405180910390fd5b818181518110611e8f57634e487b7160e01b600052603260045260246000fd5b60200260200101516001611ea39190615cf3565b60086000858481518110611ec757634e487b7160e01b600052603260045260246000fd5b602002602001015161ffff1661ffff16815260200190815260200160002060006101000a81548163ffffffff021916908363ffffffff1602179055508080611f0e90615ef5565b915050611dff565b505050565b611f23612f99565b60008060007f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b031663c0fd8bde886040518263ffffffff1660e01b8152600401611f749190615b5f565b60006040518083038186803b158015611f8c57600080fd5b505afa158015611fa0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611fc89190810190615510565b925092509250818190611fee5760405162461bcd60e51b81526004016112119190615b5f565b50612001836080015184606001516134c6565b60048552600061201086613c77565b8051906020012090508360e0015151602014158061203d575060e0840151612039906000613a92565b8114155b1561205b57604051637c6953f960e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000a63ffffffff16866060015163ffffffff16146120ab576040516375893cc160e11b815260040160405180910390fd5b6040868101516001600160401b0390811660009081526004602090815290839020835160808101855281548152600182015493841692810192909252680100000000000000009092046001600160a01b031692810192909252600201546060820181905261212c5760405163af61069360e01b815260040160405180910390fd5b80602001516001600160401b03168760a001516001600160401b03161061216657604051634a7f394f60e01b815260040160405180910390fd5b60008060007f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b031663c0fd8bde8c6040518263ffffffff1660e01b81526004016121b79190615b5f565b60006040518083038186803b1580156121cf57600080fd5b505afa1580156121e3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261220b9190810190615510565b9250925092508181906122315760405162461bcd60e51b81526004016112119190615b5f565b50612244836080015184606001516134c6565b6005895260006122538a613d2d565b8051906020012090508360e00151516020141580612280575060e084015161227c906000613a92565b8114155b1561229e57604051637c6953f960e01b815260040160405180910390fd5b845160c08b0151146122c257604051620fd39f60e51b815260040160405180910390fd5b8a604001516001600160401b03168a604001516001600160401b0316146122fc57604051633ab3447f60e11b815260040160405180910390fd5b8a6060015163ffffffff168a6060015163ffffffff1614612330576040516375893cc160e11b815260040160405180910390fd5b84602001516001600160401b03168b60a001518b60a001516123529190615d1b565b6001600160401b0316101561237a57604051636e51edcd60e11b815260040160405180910390fd5b6123a461238a8b60800151613b30565b606087015160408801516001600160a01b03169190613bde565b5050506040808901516001600160401b0316600090815260046020529081208181556001810180546001600160e01b031916905560020155506123ec94506134709350505050565b50505050565b60006123fc612f99565b600354600160a01b900460ff1615612427576040516313d0ff5960e31b815260040160405180910390fd5b6001600160a01b0319821615612450576040516375893cc160e11b815260040160405180910390fd5b8361246e576040516308fefc0560e21b815260040160405180910390fd5b6124836001600160a01b038816333089612ff3565b6124b9877f0000000000000000000000004e744b28e787c3ad0e810ed65a24461d4ac5a7626124b2878a615e6a565b6001613073565b6001600160a01b037f0000000000000000000000004e744b28e787c3ad0e810ed65a24461d4ac5a7621663f856ddb66124f28689615e6a565b85858b6124fe89613dc3565b6040516001600160e01b031960e088901b168152600481019590955263ffffffff93909316602485015260448401919091526001600160a01b03166064830152608482015260a401602060405180830381600087803b15801561256057600080fd5b505af1158015612574573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125989190615801565b604080516080810182528481526001600160401b0380891660208084019182526001600160a01b03808e16858701908152606086018c81528589166000908152600490945296909220945185559151600185018054925190931668010000000000000000026001600160e01b0319909216931692909217919091179055905160029091015590506126296001600055565b9695505050505050565b61263b612f99565b60008060007f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b031663c0fd8bde886040518263ffffffff1660e01b815260040161268c9190615b5f565b60006040518083038186803b1580156126a457600080fd5b505afa1580156126b8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526126e09190810190615510565b9250925092508181906127065760405162461bcd60e51b81526004016112119190615b5f565b50606083015161ffff16600114158061274357507f8315814095c3ee003c10a905070b33f5a9ad18057cedf16e8192c8d3fc118ec8836080015114155b1561276157604051632c6bb35560e01b815260040160405180910390fd5b600061276d878b613df7565b9050428161014001516001600160401b0316101561279e576040516354a36da760e11b815260040160405180910390fd5b6127ac816102000151613b30565b6001600160a01b0316336001600160a01b0316146127dc576040516282b42960e81b815260040160405180910390fd5b60006127e782613f9d565b90508460e0015151602014158061280d575060e0850151612809906000613a92565b8114155b1561282b57604051637c6953f960e01b815260040160405180910390fd5b6000806128388d8d6134f9565b61012086015191935091506001600160401b03161561287657610120840151612876906001600160a01b0384169033906001600160401b0316613bde565b60006128858560c00151613b30565b90506128ad838b8761012001516001600160401b0316856128a69190615e6a565b6000613073565b60006001600160a01b0382166128c457504761293e565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a082319060240160206040518083038186803b15801561290357600080fd5b505afa158015612917573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061293b91906156c4565b90505b6000808c6001600160a01b031660008d60405161295b9190615881565b60006040518083038185875af1925050503d8060008114612998576040519150601f19603f3d011682016040523d82523d6000602084013e61299d565b606091505b50915091508181906129c25760405162461bcd60e51b81526004016112119190615b5f565b506001600160a01b0384166129e2576129db8347615e6a565b9250612a68565b6040516370a0823160e01b815230600482015283906001600160a01b038616906370a082319060240160206040518083038186803b158015612a2357600080fd5b505afa158015612a37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a5b91906156c4565b612a659190615e6a565b92505b60006001600160a01b038516612a8057506012612a8c565b612a8985614028565b90505b6000612aa58a60e001516001600160401b031683613af8565b905080851015612ac8576040516309d2d38b60e31b815260040160405180910390fd5b612ad38a87876140d8565b6101e08a01516101c08b01516040805163ffffffff90931683526001600160401b03909116602083015281018690527fcc5626df3b699006387b64eca775dbdfecd5ae542e2d6ab22923082e1320dfcb9060600160405180910390a150505050505050505050505050612b466001600055565b505050505050565b6002546001600160a01b03163314612b78576040516282b42960e81b815260040160405180910390fd5b6116d181836001613b5f565b6002546001600160a01b03163314612bae576040516282b42960e81b815260040160405180910390fd5b60038054911515600160a01b0260ff60a01b19909216919091179055565b6002546001600160a01b03163314612bf6576040516282b42960e81b815260040160405180910390fd5b6040516001600160e01b031960e085901b1660208201526bffffffffffffffffffffffff19606084901b16602482015260009060380160408051601f1981840301815291815281516020928301206000818152600790935291205490915015612c725760405163a741a04560e01b815260040160405180910390fd5b6000908152600760205260409020555050565b612c8d612f99565b60008060007f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b031663c0fd8bde866040518263ffffffff1660e01b8152600401612cde9190615b5f565b60006040518083038186803b158015612cf657600080fd5b505afa158015612d0a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d329190810190615510565b925092509250818190612d585760405162461bcd60e51b81526004016112119190615b5f565b50612d6b836080015184606001516134c6565b30612d7a611a63896098613a92565b6001600160a01b031614612da05760405162bc52d160e21b815260040160405180910390fd5b6000612dac858961438d565b90506000612db982613477565b8051906020012090508460e00151516020141580612de6575060e0850151612de2906000613a92565b8114155b15612e0457604051637c6953f960e01b815260040160405180910390fd5b816020015160ff166002148015612e395750612e238260800151613b30565b6001600160a01b0316336001600160a01b031614155b15612e56576040516282b42960e81b815260040160405180910390fd5b600080612e638b8b6134f9565b91509150808460c001516001600160401b03161115612e95576040516308fefc0560e21b815260040160405180910390fd5b612ead33838660c001516001600160401b0316614499565b6000612ebc8560800151613b30565b9050612eec818660c001516001600160401b031684612edb9190615e6a565b6001600160a01b0386169190613bde565b60a08501516001600160401b031615612f49576000612f198660a001516001600160401b03166012613af8565b9050803414612f3b57604051636e51edcd60e11b815260040160405180910390fd5b612f4782826000613b5f565b505b50505050505050506123ec6001600055565b6002546001600160a01b03163314612f85576040516282b42960e81b815260040160405180910390fd5b611f166001600160a01b0384168284613bde565b60026000541415612fec5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611211565b6002600055565b6040516001600160a01b03808516602483015283166044820152606481018290526123ec9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152614590565b604051636eb1769f60e11b81523060048201526001600160a01b038481166024830152859160009183169063dd62ed3e9060440160206040518083038186803b1580156130bf57600080fd5b505afa1580156130d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130f791906156c4565b905083811015612b4657801561311c5761311c6001600160a01b038316866000614678565b612b46858461312b578561312f565b6000195b6001600160a01b0385169190614678565b600063ffffffff821660081415613226577f0000000000000000000000004e744b28e787c3ad0e810ed65a24461d4ac5a7626001600160a01b0316636fd3504e848461318c86896147a3565b6040516001600160e01b031960e086901b168152600481019390935263ffffffff91909116602483015260448201526001600160a01b0387166064820152608401602060405180830381600087803b1580156131e757600080fd5b505af11580156131fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061321f9190615801565b9050611dcb565b7f0000000000000000000000004e744b28e787c3ad0e810ed65a24461d4ac5a7626001600160a01b031663f856ddb6848461326186896147a3565b8861326b88613dc3565b6040516001600160e01b031960e088901b168152600481019590955263ffffffff93909316602485015260448401919091526001600160a01b03166064830152608482015260a401602060405180830381600087803b1580156132cd57600080fd5b505af11580156132e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a239190615801565b6060816000015182602001518360400151846060015185608001518660a001518760c001518860e001518961010001518a61012001518b61014001518c61016001518d61018001518e6101a001516040516020016133709e9d9c9b9a9998979695949392919061589d565b6040516020818303038152906040529050919050565b60608160000151826020015183604001518460600151604051602001613370949392919060f894851b6001600160f81b031990811682529390941b909216600184015260c01b6001600160c01b031916600283015260e01b6001600160e01b031916600a820152600e0190565b6060806040519050835180825260208201818101602087015b8183101561342457805183526020928301920161340c565b50855184518101855292509050808201602086015b81831015613451578051835260209283019201613439565b508651929092011591909101601f01601f191660405250905092915050565b6001600055565b6060816000015182602001518360400151846060015185608001518660a001518760c001518860e001518961010001518a61012001516040516020016133709a99989796959493929190615ac9565b61ffff811660009081526005602052604090205482146116d157604051632c6bb35560e01b815260040160405180910390fd5b60008080613508856004613a2c565b90506000613517866078613a92565b905060007f0000000000000000000000004e744b28e787c3ad0e810ed65a24461d4ac5a7626001600160a01b031663cb75c11c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561357457600080fd5b505afa158015613588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135ac9190614df6565b604051633c502b2f60e11b815263ffffffff85166004820152602481018490526001600160a01b0391909116906378a0565e9060440160206040518083038186803b1580156135fa57600080fd5b505afa15801561360e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136329190614df6565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b15801561367757600080fd5b505afa15801561368b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136af91906156c4565b905060007f0000000000000000000000004e744b28e787c3ad0e810ed65a24461d4ac5a7626001600160a01b0316632c1219216040518163ffffffff1660e01b815260040160206040518083038186803b15801561370c57600080fd5b505afa158015613720573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137449190614df6565b6001600160a01b03166357ecfd288a8a6040518363ffffffff1660e01b8152600401613771929190615b72565b602060405180830381600087803b15801561378b57600080fd5b505af115801561379f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c39190615042565b9050806137e35760405163605c687360e01b815260040160405180910390fd5b6040516370a0823160e01b815230600482015282906001600160a01b038516906370a082319060240160206040518083038186803b15801561382457600080fd5b505afa158015613838573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061385c91906156c4565b6138669190615e6a565b9299929850919650505050505050565b604080516101c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a0810191909152604080516101c0810190915280600160ff16815260016020808301919091528451604083015284015161ffff166060820152608001613927856078613a92565b81526020016139378560d06139c6565b6001600160401b0316815260200185606001518152602001856080015161ffff1681526020018560a0015181526020018560c001516001600160401b0316815260200185604001516001600160401b031681526020018561010001516001600160401b031681526020018560e001516001600160401b0316815260200185610120015181525090509392505050565b60006139d3826008615cdb565b83511015613a235760405162461bcd60e51b815260206004820152601460248201527f746f55696e7436345f6f75744f66426f756e64730000000000000000000000006044820152606401611211565b50016008015190565b6000613a39826004615cdb565b83511015613a895760405162461bcd60e51b815260206004820152601460248201527f746f55696e7433325f6f75744f66426f756e64730000000000000000000000006044820152606401611211565b50016004015190565b6000613a9f826020615cdb565b83511015613aef5760405162461bcd60e51b815260206004820152601560248201527f746f427974657333325f6f75744f66426f756e647300000000000000000000006044820152606401611211565b50016020015190565b600060088260ff161115613b2957613b11600883615ea6565b613b1c90600a615da0565b613b269084615e4b565b92505b5090919050565b60006001600160a01b0319821615613b5b5760405163e6c4247b60e01b815260040160405180910390fd5b5090565b6000836001600160a01b03168360405160006040518083038185875af1925050503d8060008114613bac576040519150601f19603f3d011682016040523d82523d6000602084013e613bb1565b606091505b5050905081156123ec576001811515146123ec57604051630db2c7f160e31b815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052611f1690849063a9059cbb60e01b90606401613027565b7f4f7c61703b83b54f1af0ca9b67d73dc13cc2e91262faf81b0a4927cbce924239613c3a836004613a2c565b613c4584600c6139c6565b6040805163ffffffff90931683526001600160401b039091166020830152810183905260600160405180910390a15050565b8051602080830151604080850151606080870151608088015160a0890151945160f898891b6001600160f81b0319908116988201989098529590971b909516602185015260c091821b6001600160c01b0319908116602286015260e09590951b6001600160e01b031916602a850152602e8401959095521b909116604e820152605601613370565b600060088260ff161115613b2957613d18600883615ea6565b613d2390600a615da0565b613b269084615d3d565b8051602080830151604080850151606086810151608088015160a089015160c0808b015196516001600160f81b031960f89b8c1b81169a82019a909a529790991b90971660218701526001600160c01b031993881b841660228701526001600160e01b031960e09290921b91909116602a860152602e8501529390941b909316604e820152605681019290925290607601613370565b63ffffffff811660009081526006602052604090205480610dae5760405163133bff2160e21b815260040160405180910390fd5b60408051610220808201835260008083526020808401829052838501829052606084018290526080840182905260a0840182905260c0840182905260e08401829052610100840182905261012084018290526101408401829052610160840182905261018084018290526101a084018290526101c084018290526101e08401829052610200840191909152835191820184526002825260019082015290918101613ea2846078613a92565b8152602001613eb28460d06139c6565b6001600160401b0316815260200184600001518152602001846020015161ffff1681526020018460400151815260200184606001516001600160401b0316815260200184608001516001600160401b031681526020018460a001516001600160401b031681526020018460c001516001600160401b031681526020018460e00151815260200184610100015160ff16815260200184610120015160ff168152602001613f68600c856139c690919063ffffffff16565b6001600160401b03168152602001613f81846004613a2c565b63ffffffff168152602001846101400151815250905092915050565b600080613fa98361481d565b90506000614018846101c00151856101e001518661020001516040516020016140019392919060c09390931b6001600160c01b031916835260e09190911b6001600160e01b0319166008830152600c820152602c0190565b60408051601f1981840301815291905283906133f3565b8051602090910120949350505050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663313ce56760e01b179052905160009182916001600160a01b0385169161408091615881565b600060405180830381855afa9150503d80600081146140bb576040519150601f19603f3d011682016040523d82523d6000602084013e6140c0565b606091505b5091505080806020019051810190611dcb9190615839565b60006140e8846101600151613b30565b905060006001600160a01b0382161580159061410b575061018085015160ff1615155b156141345761271085610180015160ff16846141279190615e4b565b6141319190615d3d565b90505b6000856101a0015160ff1660001461416a57612710866101a0015160ff168561415d9190615e4b565b6141679190615d3d565b90505b60006141798760800151613b30565b90506001600160a01b03861661424c57821561419b5761419b84846000613b5f565b811561422757600154604080516331056e5760e21b81529051614227926001600160a01b03169163c415b95c916004808301926020929190829003018186803b1580156141e757600080fd5b505afa1580156141fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061421f9190614df6565b836000613b5f565b61424781836142368689615e6a565b6142409190615e6a565b6001613b5f565b614384565b6101008701516001600160401b0316156142ab57600061427b8861010001516001600160401b03166012613af8565b905080341461429d57604051636e51edcd60e11b815260040160405180910390fd5b6142a982826000613b5f565b505b82156142c5576142c56001600160a01b0387168585613bde565b811561435a57600154604080516331056e5760e21b8152905161435a926001600160a01b03169163c415b95c916004808301926020929190829003018186803b15801561431157600080fd5b505afa158015614325573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143499190614df6565b6001600160a01b0388169084613bde565b61438481836143698689615e6a565b6143739190615e6a565b6001600160a01b0389169190613bde565b50505050505050565b60408051610140808201835260008083526020808401829052838501829052606084018290526080840182905260a0840182905260c0840182905260e0840182905261010084018290526101208401919091528351918201845260038252855160ff16908201529091810161440384600c6139c6565b6001600160401b0316815260200161441c846004613a2c565b63ffffffff1681526020018460200151815260200184604001516001600160401b0316815260200184606001516001600160401b0316815260200161446b60d0856139c690919063ffffffff16565b6001600160401b03168152602001614484846078613a92565b81526020018460c00151815250905092915050565b60015460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018390529083169063a9059cbb90604401602060405180830381600087803b1580156144e757600080fd5b505af11580156144fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061451f9190615042565b50600154604051631c43245560e01b81526001600160a01b03858116600483015284811660248301526044820184905290911690631c43245590606401600060405180830381600087803b15801561457657600080fd5b505af1925050508015614587575060015b611f1657505050565b60006145e5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166148889092919063ffffffff16565b90508051600014806146065750808060200190518101906146069190615042565b611f165760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611211565b8015806147015750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156146c757600080fd5b505afa1580156146db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146ff91906156c4565b155b6147735760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401611211565b6040516001600160a01b038316602482015260448101829052611f1690849063095ea7b360e01b90606401613027565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff191660248301528251601881840301815260389092018352815191810191909120600090815260079091529081205480611dcb57604051626130e960e01b815260040160405180910390fd5b6060816000015182602001518360400151846060015185608001518660a001518760c001518860e001518961010001518a61012001518b61014001518c61016001518d61018001518e6101a001516040516020016133709e9d9c9b9a999897969594939291906159aa565b6060611a23848460008585600080866001600160a01b031685876040516148af9190615881565b60006040518083038185875af1925050503d80600081146148ec576040519150601f19603f3d011682016040523d82523d6000602084013e6148f1565b606091505b50915091506149028783838761490d565b979650505050505050565b60608315614979578251614972576001600160a01b0385163b6149725760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611211565b5081611a23565b611a23838381511561498e5781518083602001fd5b8060405162461bcd60e51b81526004016112119190615b5f565b8035610dae81615f3c565b600082601f8301126149c3578081fd5b815160206149d86149d383615c91565b615c61565b80838252828201915082860187848660071b89010111156149f7578586fd5b855b85811015614a5e57608080838b031215614a11578788fd5b614a19615bd2565b835181528684015187820152604080850151614a3481615f99565b90820152606084810151614a4781615f99565b9082015285529385019391909101906001016149f9565b5090979650505050505050565b600082601f830112614a7b578081fd5b81356020614a8b6149d383615c91565b80838252828201915082860187848660051b8901011115614aaa578586fd5b855b85811015614a5e578135614abf81615f72565b84529284019290840190600101614aac565b8051610dae81615f54565b600082601f830112614aec578081fd5b8135614afa6149d382615cb4565b818152846020838601011115614b0e578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112614b38578081fd5b8151614b466149d382615cb4565b818152846020838601011115614b5a578283fd5b611a23826020830160208701615ec9565b60006101608284031215614b7d578081fd5b614b85615bfa565b905081358152614b9760208301614d8d565b602082015260408201356040820152614bb260608301614dae565b6060820152614bc360808301614dae565b6080820152614bd460a08301614dae565b60a0820152614be560c08301614dae565b60c082015260e082013560e0820152610100614c02818401614dc4565b90820152610120614c14838201614dc4565b818301525061014080830135818301525092915050565b60006101608284031215614c3d578081fd5b614c45615bfa565b9050614c50826149a8565b815260208201356020820152614c6860408301614dae565b604082015260608201356060820152614c8360808301614d8d565b608082015260a082013560a0820152614c9e60c08301614dae565b60c0820152614caf60e08301614dae565b60e0820152610100614cc2818401614dae565b908201526101208281013590820152610140614cdf818401614dc4565b9082015292915050565b600060c08284031215614cfa578081fd5b60405160c081018181106001600160401b0382111715614d1c57614d1c615f26565b6040529050808235614d2d81615f99565b81526020830135614d3d81615f99565b60208201526040830135614d5081615f84565b60408201526060830135614d6381615f72565b60608201526080838101359082015260a0830135614d8081615f84565b60a0919091015292915050565b8035610dae81615f62565b8051610dae81615f62565b8051610dae81615f72565b8035610dae81615f84565b8051610dae81615f84565b8035610dae81615f99565b8051610dae81615f99565b600060208284031215614deb578081fd5b8135611dcb81615f3c565b600060208284031215614e07578081fd5b8151611dcb81615f3c565b600080600060608486031215614e26578182fd5b8335614e3181615f3c565b9250602084013591506040840135614e4881615f3c565b809150509250925092565b60008060008060008060c08789031215614e6b578384fd5b8635614e7681615f3c565b9550602087013594506040870135614e8d81615f84565b9350606087013592506080870135614ea481615f72565b8092505060a087013590509295509295509295565b600080600080600080600080610100898b031215614ed5578586fd5b8835614ee081615f3c565b9750602089013596506040890135614ef781615f84565b95506060890135614f0781615f84565b94506080890135935060a0890135614f1e81615f72565b925060c0890135614f2e81615f99565b915060e08901356001600160401b03811115614f48578182fd5b614f548b828c01614adc565b9150509295985092959890939650565b60008060408385031215614f76578182fd5b82356001600160401b0380821115614f8c578384fd5b818501915085601f830112614f9f578384fd5b81356020614faf6149d383615c91565b8083825282820191508286018a848660051b8901011115614fce578889fd5b8896505b84871015614ff9578035614fe581615f62565b835260019690960195918301918301614fd2565b509650508601359250508082111561500f578283fd5b5061501c85828601614a6b565b9150509250929050565b600060208284031215615037578081fd5b8135611dcb81615f54565b600060208284031215615053578081fd5b8151611dcb81615f54565b60006020828403121561506f578081fd5b5035919050565b60008060006060848603121561508a578081fd5b83356001600160401b03808211156150a0578283fd5b6150ac87838801614adc565b945060208601359150808211156150c1578283fd5b506150ce86828701614adc565b925050604084013590509250925092565b6000806000808486036101408112156150f6578283fd5b85356001600160401b038082111561510c578485fd5b61511889838a01614adc565b9650602088013591508082111561512d578485fd5b61513989838a01614adc565b9550604088013591508082111561514e578485fd5b5061515b88828901614adc565b93505060e0605f198201121561516f578182fd5b50615178615c1d565b606086013561518681615f99565b81526080860135602082015260a08601356151a081615f84565b604082015260c08601356151b381615f84565b60608201526151c460e08701614dae565b608082015261010086013560a08201526101209095013560c0860152509194909350909190565b6000806000806000806102008789031215615204578384fd5b86356001600160401b038082111561521a578586fd5b6152268a838b01614adc565b9750602089013591508082111561523b578586fd5b6152478a838b01614adc565b9650604089013591508082111561525c578586fd5b6152688a838b01614adc565b95506152778a60608b01614b6b565b94506152866101c08a016149a8565b93506101e089013591508082111561529c578283fd5b506152a989828a01614adc565b9150509295509295509295565b60008060008060008587036102208112156152cf578384fd5b86356001600160401b03808211156152e5578586fd5b6152f18a838b01614adc565b97506020890135915080821115615306578586fd5b6153128a838b01614adc565b96506040890135915080821115615327578586fd5b5061533489828a01614adc565b9450506153448860608901614c2b565b925060606101bf1982011215615358578182fd5b50615361615c3f565b6101c087013581526101e087013561537881615f62565b602082015261020087013561538c81615f99565b6040820152949793965091945092919050565b6000806000808486036101e08112156153b6578283fd5b85356001600160401b03808211156153cc578485fd5b6153d889838a01614adc565b965060208801359150808211156153ed578485fd5b506153fa88828901614adc565b94505061540a8760408801614ce9565b925060e060ff198201121561541d578182fd5b50615426615c1d565b61010086013561543581615f99565b815261012086013561544681615f99565b602082015261014086013561545a81615f84565b604082015261016086013561546e81615f72565b6060820152610180860135608082015261548b6101a08701614dae565b60a08201526101c086013560c08201528091505092959194509250565b60008060e083850312156154ba578182fd5b82356001600160401b038111156154cf578283fd5b6154db85828601614adc565b9250506154eb8460208501614ce9565b90509250929050565b60006101608284031215615506578081fd5b611dcb8383614c2b565b600080600060608486031215615524578081fd5b83516001600160401b038082111561553a578283fd5b90850190610160828803121561554e578283fd5b615556615bfa565b61555f83614dcf565b815261556d60208401614da3565b602082015261557e60408401614da3565b604082015261558f60608401614d98565b6060820152608083015160808201526155aa60a08401614db9565b60a08201526155bb60c08401614dcf565b60c082015260e0830151828111156155d1578485fd5b6155dd89828601614b28565b60e0830152506101006155f1818501614da3565b908201526101208381015183811115615608578586fd5b6156148a8287016149b3565b91830191909152506101408381015190820152945061563560208701614ad1565b9350604086015191508082111561564a578283fd5b5061565786828701614b28565b9150509250925092565b600060208284031215615672578081fd5b8135611dcb81615f62565b60006020828403121561568e578081fd5b8151611dcb81615f62565b600080604083850312156156ab578182fd5b82356156b681615f62565b946020939093013593505050565b6000602082840312156156d5578081fd5b5051919050565b600080604083850312156156ee578182fd5b82359150602083013561570081615f3c565b809150509250929050565b60006020828403121561571c578081fd5b8135611dcb81615f72565b600060208284031215615738578081fd5b8151611dcb81615f72565b600080600060608486031215615757578081fd5b833561576281615f72565b9250602084013561577281615f3c565b929592945050506040919091013590565b60008060408385031215615795578182fd5b82356156b681615f72565b600080600080608085870312156157b5578182fd5b84356157c081615f72565b935060208501356157d081615f72565b93969395505050506040820135916060013590565b6000602082840312156157f6578081fd5b8135611dcb81615f84565b600060208284031215615812578081fd5b8151611dcb81615f84565b60006020828403121561582e578081fd5b8135611dcb81615f99565b60006020828403121561584a578081fd5b8151611dcb81615f99565b6000815180845261586d816020860160208601615ec9565b601f01601f19169290920160200192915050565b60008251615893818460208701615ec9565b9190910192915050565b60f88f901b6001600160f81b03191681526158c7600182018f60f81b6001600160f81b0319169052565b8c60028201526158e6602282018d60f01b6001600160f01b0319169052565b8a6024820152615905604482018b60c01b6001600160c01b0319169052565b88604c820152615924606c82018960f01b6001600160f01b0319169052565b86606e820152615943608e82018760c01b6001600160c01b0319169052565b61595c609682018660c01b6001600160c01b0319169052565b615975609e82018560c01b6001600160c01b0319169052565b61598e60a682018460c01b6001600160c01b0319169052565b60ae81019190915260ce019d9c50505050505050505050505050565b60f88f901b6001600160f81b03191681526159d4600182018f60f81b6001600160f81b0319169052565b8c60028201526159f3602282018d60c01b6001600160c01b0319169052565b8a602a820152615a12604a82018b60f01b6001600160f01b0319169052565b88604c820152615a31606c82018960c01b6001600160c01b0319169052565b615a4a607482018860c01b6001600160c01b0319169052565b615a63607c82018760c01b6001600160c01b0319169052565b615a7c608482018660c01b6001600160c01b0319169052565b83608c820152615a9b60ac82018460f81b6001600160f81b0319169052565b615ab460ad82018360f81b6001600160f81b0319169052565b60ae019e9d5050505050505050505050505050565b6001600160f81b031960f88c811b821683528b901b1660018201526001600160c01b031960c08a811b821660028401526001600160e01b031960e08b901b16600a840152600e830189905287811b8216602e84015286901b1660368201526000615b42603e83018660c01b6001600160c01b0319169052565b506046810192909252606682015260860198975050505050505050565b602081526000611dcb6020830184615855565b604081526000615b856040830185615855565b8281036020840152615b978185615855565b95945050505050565b63ffffffff84168152606060208201526000615bbf6060830185615855565b905060ff83166040830152949350505050565b604051608081016001600160401b0381118282101715615bf457615bf4615f26565b60405290565b60405161016081016001600160401b0381118282101715615bf457615bf4615f26565b60405160e081016001600160401b0381118282101715615bf457615bf4615f26565b604051606081016001600160401b0381118282101715615bf457615bf4615f26565b604051601f8201601f191681016001600160401b0381118282101715615c8957615c89615f26565b604052919050565b60006001600160401b03821115615caa57615caa615f26565b5060051b60200190565b60006001600160401b03821115615ccd57615ccd615f26565b50601f01601f191660200190565b60008219821115615cee57615cee615f10565b500190565b600063ffffffff808316818516808303821115615d1257615d12615f10565b01949350505050565b60006001600160401b03808316818516808303821115615d1257615d12615f10565b600082615d5857634e487b7160e01b81526012600452602481fd5b500490565b600181815b80851115615d98578160001904821115615d7e57615d7e615f10565b80851615615d8b57918102915b93841c9390800290615d62565b509250929050565b6000611dcb60ff841683600082615db9575060016117fc565b81615dc6575060006117fc565b8160018114615ddc5760028114615de657615e02565b60019150506117fc565b60ff841115615df757615df7615f10565b50506001821b6117fc565b5060208310610133831016604e8410600b8410161715615e25575081810a6117fc565b615e2f8383615d5d565b8060001904821115615e4357615e43615f10565b029392505050565b6000816000190483118215151615615e6557615e65615f10565b500290565b600082821015615e7c57615e7c615f10565b500390565b600063ffffffff83811690831681811015615e9e57615e9e615f10565b039392505050565b600060ff821660ff841680821015615ec057615ec0615f10565b90039392505050565b60005b83811015615ee4578181015183820152602001615ecc565b838111156123ec5750506000910152565b6000600019821415615f0957615f09615f10565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114615f5157600080fd5b50565b8015158114615f5157600080fd5b61ffff81168114615f5157600080fd5b63ffffffff81168114615f5157600080fd5b6001600160401b0381168114615f5157600080fd5b60ff81168114615f5157600080fdfea26469706673582212205ac7d0e9ed298919276884025f98a08fe9bc83d17a3dacd396b608e527e56c1d64736f6c63430008040033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004e744b28e787c3ad0e810ed65a24461d4ac5a762000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018315814095c3ee003c10a905070b33f5a9ad18057cedf16e8192c8d3fc118ec80000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : _cctpTokenMessenger (address): 0x4e744b28E787c3aD0e810eD65A24461D4ac5a762
Arg [1] : _wormhole (address): 0xCa1D5a146B03f6303baF59e5AD5615ae0b9d146D
Arg [2] : _feeManager (address): 0x0000000000000000000000000000000000000000
Arg [3] : _auctionChainId (uint16): 1
Arg [4] : _auctionAddr (bytes32): 0x8315814095c3ee003c10a905070b33f5a9ad18057cedf16e8192c8d3fc118ec8
Arg [5] : _consistencyLevel (uint8): 1
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000004e744b28e787c3ad0e810ed65a24461d4ac5a762
Arg [1] : 000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [4] : 8315814095c3ee003c10a905070b33f5a9ad18057cedf16e8192c8d3fc118ec8
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000001
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$146.28
Net Worth in ETH
0.05136
Token Allocations
ETH
57.09%
USDC
42.91%
POL
0.00%
Multichain Portfolio | 35 Chains
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.