Source Code
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
SwiftSource
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 1000 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "../interfaces/IWormhole.sol";
import "../interfaces/IFeeManager.sol";
import "../libs/BytesLib.sol";
import "../libs/SignatureVerifier.sol";
import "./SwiftStructs.sol";
import "./SwiftErrors.sol";
contract SwiftSource is ReentrancyGuard {
event OrderCreated(bytes32 key);
event OrderFulfilled(bytes32 key, uint64 sequence, uint256 netAmount);
event OrderUnlocked(bytes32 key);
event OrderCanceled(bytes32 key, uint64 sequence);
event OrderRefunded(bytes32 key, uint256 netAmount);
using SafeERC20 for IERC20;
using BytesLib for bytes;
using SignatureVerifier for bytes;
uint8 constant BPS_FEE_LIMIT = 200;
uint8 constant NATIVE_DECIMALS = 18;
IWormhole public immutable wormhole;
IWormhole public refundVerifier;
uint16 public refundEmitterChainId;
bytes32 public refundEmitterAddr;
IFeeManager public feeManager;
address public immutable rescueVault;
address public guardian;
address public nextGuardian;
bool public paused;
bytes32 private domainSeparator;
mapping(bytes32 => Order) public orders;
mapping(uint16 => bytes32) public emitters;
mapping(uint64 => bool) public usedSequences;
constructor(
address _wormhole,
address _refundVerifier,
uint16 _refundEmitterChainId,
bytes32 _refundEmitterAddr,
address _feeManager,
address _rescueVault
) {
guardian = msg.sender;
wormhole = IWormhole(_wormhole);
refundVerifier = IWormhole(_refundVerifier);
refundEmitterChainId = _refundEmitterChainId;
refundEmitterAddr = _refundEmitterAddr;
feeManager = IFeeManager(_feeManager);
rescueVault = _rescueVault;
domainSeparator = keccak256(abi.encode(
keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"),
keccak256("Mayan Swift"),
uint256(block.chainid),
address(this)
));
}
function createOrderWithEth(OrderParams memory params, bytes memory customPayload) nonReentrant external payable returns (bytes32 orderHash) {
if (paused) {
revert Paused();
}
uint64 normlizedAmountIn = uint64(normalizeAmount(msg.value, NATIVE_DECIMALS));
if (normlizedAmountIn == 0) {
revert SmallAmountIn();
}
if (params.cancelFee + params.refundFee >= normlizedAmountIn) {
revert FeesTooHigh();
}
if (params.tokenOut == bytes32(0) && params.gasDrop != 0) {
revert InvalidGasDrop();
}
uint8 protocolBps = feeManager.calcSwiftProtocolBps(address(0), msg.value, params);
if (params.referrerBps > BPS_FEE_LIMIT || protocolBps > BPS_FEE_LIMIT) {
revert InvalidBpsFee();
}
bytes32 customPayloadHash;
if (params.payloadType == 2) {
customPayloadHash = keccak256(customPayload);
}
Key memory key = buildKey(params, bytes32(0), wormhole.chainId(), protocolBps, customPayloadHash);
orderHash = keccak256(encodeKey(key));
if (emitters[params.destChainId] == 0 || params.destChainId == wormhole.chainId()) {
revert InvalidDestChain();
}
Order memory order = orders[orderHash];
if (orders[orderHash].destChainId != 0) {
if (normlizedAmountIn > order.amountIn && order.status == Status.CREATED) {
payEth(truncateAddress(params.trader), deNormalizeAmount(order.amountIn, NATIVE_DECIMALS), false);
} else {
revert DuplicateOrder();
}
}
orders[orderHash] = Order({
status: Status.CREATED,
amountIn: normlizedAmountIn,
destChainId: params.destChainId
});
emit OrderCreated(orderHash);
}
function createOrderWithToken(
address tokenIn,
uint256 amountIn,
OrderParams memory params,
bytes memory customPayload
) nonReentrant external returns (bytes32 orderHash) {
if (paused) {
revert Paused();
}
amountIn = pullTokensFrom(tokenIn, amountIn, msg.sender);
uint64 normlizedAmountIn = uint64(normalizeAmount(amountIn, decimalsOf(tokenIn)));
if (normlizedAmountIn == 0) {
revert SmallAmountIn();
}
if (params.cancelFee + params.refundFee >= normlizedAmountIn) {
revert FeesTooHigh();
}
if (params.tokenOut == bytes32(0) && params.gasDrop != 0) {
revert InvalidGasDrop();
}
uint8 protocolBps = feeManager.calcSwiftProtocolBps(tokenIn, amountIn, params);
if (params.referrerBps > BPS_FEE_LIMIT || protocolBps > BPS_FEE_LIMIT) {
revert InvalidBpsFee();
}
bytes32 customPayloadHash;
if (params.payloadType == 2) {
customPayloadHash = keccak256(customPayload);
}
Key memory key = buildKey(params, bytes32(uint256(uint160(tokenIn))), wormhole.chainId(), protocolBps, customPayloadHash);
orderHash = keccak256(encodeKey(key));
if (emitters[params.destChainId] == 0 || params.destChainId == wormhole.chainId()) {
revert InvalidDestChain();
}
Order memory order = orders[orderHash];
if (order.destChainId != 0) {
if (normlizedAmountIn > order.amountIn && order.status == Status.CREATED) {
IERC20(tokenIn).transfer(truncateAddress(params.trader), deNormalizeAmount(order.amountIn, decimalsOf(tokenIn)));
} else {
revert DuplicateOrder();
}
}
orders[orderHash] = Order({
status: Status.CREATED,
amountIn: normlizedAmountIn,
destChainId: params.destChainId
});
emit OrderCreated(orderHash);
}
function createOrderWithSig(
address tokenIn,
uint256 amountIn,
OrderParams memory params,
bytes memory customPayload,
uint256 submissionFee,
bytes calldata signedOrderHash,
PermitParams calldata permitParams
) nonReentrant external returns (bytes32 orderHash) {
if (paused) {
revert Paused();
}
address trader = truncateAddress(params.trader);
if (IERC20(tokenIn).allowance(trader, address(this)) < amountIn + submissionFee) {
execPermit(tokenIn, trader, permitParams);
}
amountIn = pullTokensFrom(tokenIn, amountIn, trader);
if (submissionFee > 0) {
IERC20(tokenIn).safeTransferFrom(trader, address(feeManager), submissionFee);
feeManager.depositFee(msg.sender, tokenIn, submissionFee);
}
uint64 normlizedAmountIn = uint64(normalizeAmount(amountIn, decimalsOf(tokenIn)));
if (normlizedAmountIn == 0) {
revert SmallAmountIn();
}
if (params.cancelFee + params.refundFee >= normlizedAmountIn) {
revert FeesTooHigh();
}
if (params.tokenOut == bytes32(0) && params.gasDrop != 0) {
revert InvalidGasDrop();
}
uint8 protocolBps = feeManager.calcSwiftProtocolBps(tokenIn, amountIn, params);
if (params.referrerBps > BPS_FEE_LIMIT || protocolBps > BPS_FEE_LIMIT) {
revert InvalidBpsFee();
}
orderHash = keccak256(encodeKey(buildKey(
params,
bytes32(uint256(uint160(tokenIn))),
wormhole.chainId(),
protocolBps,
params.payloadType == 2 ? keccak256(customPayload) : bytes32(0)
)));
signedOrderHash.verify(hashTypedData(orderHash, amountIn, submissionFee), trader);
if (emitters[params.destChainId] == 0 || params.destChainId == wormhole.chainId()) {
revert InvalidDestChain();
}
if (orders[orderHash].destChainId != 0) {
revert DuplicateOrder();
}
orders[orderHash] = Order({
status: Status.CREATED,
amountIn: normlizedAmountIn,
destChainId: params.destChainId
});
emit OrderCreated(orderHash);
}
function unlockOrder(UnlockMsg memory unlockMsg, Order memory order) internal {
if (unlockMsg.srcChainId != wormhole.chainId()) {
revert InvalidSrcChain();
}
if (order.status != Status.CREATED) {
revert InvalidOrderStatus();
}
orders[unlockMsg.orderHash].status = Status.UNLOCKED;
address receiver = truncateAddress(unlockMsg.unlockReceiver);
address tokenIn = truncateAddress(unlockMsg.tokenIn);
uint8 decimals;
if (tokenIn == address(0)) {
decimals = NATIVE_DECIMALS;
} else {
decimals = decimalsOf(tokenIn);
}
uint64 normalizedReferrerFee = order.amountIn * unlockMsg.referrerBps / 10000;
address referrerAddress = address(uint160(uint256(unlockMsg.referrerAddr)));
uint64 normalizedProtocolFee = order.amountIn * unlockMsg.protocolBps / 10000;
address feeCollector;
try feeManager.feeCollector() returns (address _feeCollector) {
feeCollector = _feeCollector;
} catch {}
uint64 netAmount = order.amountIn - normalizedReferrerFee - normalizedProtocolFee;
if (tokenIn == address(0)) {
if (normalizedReferrerFee > 0 && referrerAddress != address(0)) {
uint256 referrerFee = deNormalizeAmount(normalizedReferrerFee, decimals);
try feeManager.depositFee {value: referrerFee} (referrerAddress, address(0), referrerFee) {} catch {}
}
if (normalizedProtocolFee > 0 && feeCollector != address(0)) {
uint256 protocolFee = deNormalizeAmount(normalizedProtocolFee, decimals);
try feeManager.depositFee {value: protocolFee} (feeCollector, address(0), protocolFee) {} catch {}
}
if (netAmount > 0) {
payEth(receiver, deNormalizeAmount(netAmount, decimals), true);
}
} else {
uint256 totalFee = 0;
if (normalizedReferrerFee > 0 && referrerAddress != address(0)) {
uint256 referrerFee = deNormalizeAmount(normalizedReferrerFee, decimals);
try feeManager.depositFee(referrerAddress, tokenIn, referrerFee) {totalFee += referrerFee;} catch {}
}
if (normalizedProtocolFee > 0 && feeCollector != address(0)) {
uint256 protocolFee = deNormalizeAmount(normalizedProtocolFee, decimals);
try feeManager.depositFee(feeCollector, tokenIn, protocolFee) {totalFee += protocolFee;} catch {}
}
if (totalFee > 0) {
try IERC20(tokenIn).transfer(address(feeManager), totalFee) {} catch {}
}
if (netAmount > 0) {
IERC20(tokenIn).safeTransfer(receiver, deNormalizeAmount(netAmount, decimals));
}
}
emit OrderUnlocked(unlockMsg.orderHash);
}
function refundOrder(bytes memory encodedVm, bool fast) nonReentrant() public {
IWormhole.VM memory vm;
bool valid;
string memory reason;
if (fast && address(refundVerifier) != address(0)) {
(vm, valid,reason) = refundVerifier.parseAndVerifyVM(encodedVm);
} else {
(vm, valid,reason) = wormhole.parseAndVerifyVM(encodedVm);
}
require(valid, reason);
RefundMsg memory refundMsg = parseRefundPayload(vm.payload);
Order memory order = orders[refundMsg.orderHash];
if (refundMsg.srcChainId != wormhole.chainId()) {
revert InvalidSrcChain();
}
if (order.destChainId == 0) {
revert OrderNotExists(refundMsg.orderHash);
}
if (order.status != Status.CREATED) {
revert InvalidOrderStatus();
}
orders[refundMsg.orderHash].status = Status.REFUNDED;
if (fast) {
if (vm.emitterChainId != refundEmitterChainId) {
revert InvalidEmitterChain();
}
if (vm.emitterAddress != refundEmitterAddr) {
revert InvalidEmitterAddress();
}
} else {
if (vm.emitterChainId != order.destChainId) {
revert InvalidEmitterChain();
}
if (vm.emitterAddress != emitters[order.destChainId]) {
revert InvalidEmitterAddress();
}
}
address trader = truncateAddress(refundMsg.trader);
// no error if canceler is invalid
address canceler = address(uint160(uint256(refundMsg.canceler)));
address tokenIn = truncateAddress(refundMsg.tokenIn);
uint8 decimals;
if (tokenIn == address(0)) {
decimals = NATIVE_DECIMALS;
} else {
decimals = decimalsOf(tokenIn);
}
uint256 cancelFee = deNormalizeAmount(refundMsg.cancelFee, decimals);
uint256 refundFee = deNormalizeAmount(refundMsg.refundFee, decimals);
uint256 amountIn = deNormalizeAmount(order.amountIn, decimals);
uint256 netAmount = amountIn - cancelFee - refundFee;
if (tokenIn == address(0)) {
if (cancelFee > 0) {
try feeManager.depositFee {value: cancelFee} (canceler, address(0), cancelFee) {} catch {}
}
if (refundFee > 0) {
try feeManager.depositFee {value: refundFee} (msg.sender, address(0), refundFee) {} catch {}
}
payEth(trader, netAmount, true);
} else {
if (cancelFee > 0) {
try feeManager.depositFee(canceler, tokenIn, cancelFee) {} catch {}
}
if (refundFee > 0) {
try feeManager.depositFee(msg.sender, tokenIn, refundFee) {} catch {}
}
uint256 totalFee = cancelFee + refundFee;
if (totalFee > 0) {
try IERC20(tokenIn).transfer(address(feeManager), totalFee) {} catch {}
}
IERC20(tokenIn).safeTransfer(trader, netAmount);
}
emit OrderRefunded(refundMsg.orderHash, netAmount);
}
function unlockSingle(bytes memory encodedVm) nonReentrant public {
(IWormhole.VM memory vm, bool valid, string memory reason) = wormhole.parseAndVerifyVM(encodedVm);
require(valid, reason);
UnlockMsg memory unlockMsg = parseUnlockPayload(vm.payload);
Order memory order = orders[unlockMsg.orderHash];
if (order.destChainId == 0) {
revert OrderNotExists(unlockMsg.orderHash);
}
if (vm.emitterChainId != order.destChainId) {
revert InvalidEmitterChain();
}
if (vm.emitterAddress != emitters[order.destChainId]) {
revert InvalidEmitterAddress();
}
unlockOrder(unlockMsg, order);
}
function unlockCompressedBatch(bytes memory encodedVm, bytes memory encodedPayload, uint16[] memory indexes) nonReentrant public {
(IWormhole.VM memory vm, bool valid, string memory reason) = wormhole.parseAndVerifyVM(encodedVm);
require(valid, reason);
uint8 action = vm.payload.toUint8(0);
if (action != uint8(Action.COMPRESSED_UNLOCK)) {
revert InvalidAction();
}
uint16 count = vm.payload.toUint16(1);
if (count * UNLOCK_MSG_SIZE != encodedPayload.length) {
revert InvalidPayloadLength();
}
bytes32 computedHash = keccak256(encodedPayload);
bytes32 msgHash = vm.payload.toBytes32(3);
if (computedHash != msgHash) {
revert InvalidPayload();
}
processUnlocks(encodedPayload, count, vm.emitterChainId, vm.emitterAddress, indexes);
}
function rescue(bytes memory encodedVm) public {
if (msg.sender != guardian) {
revert Unauthorized();
}
(IWormhole.VM memory vm, bool valid, string memory reason) = IWormhole(wormhole).parseAndVerifyVM(encodedVm);
require(valid, reason);
if (usedSequences[vm.sequence]) {
revert SequenceAlreadyUsed();
}
usedSequences[vm.sequence] = true;
if (vm.emitterChainId != 1) {
revert InvalidEmitterChain();
}
if (vm.emitterAddress != emitters[1]) {
revert InvalidEmitterAddress();
}
RescueMsg memory rescueMsg = parseRescuePayload(vm.payload);
if (rescueMsg.chainId != wormhole.chainId()) {
revert InvalidSrcChain();
}
if (rescueMsg.orderHash != bytes32(0)) {
orders[rescueMsg.orderHash].status = Status(rescueMsg.orderStatus);
}
if (rescueMsg.amount > 0) {
if (rescueMsg.token == address(0)) {
payEth(rescueVault, rescueMsg.amount, true);
} else {
IERC20(rescueMsg.token).safeTransfer(rescueVault, rescueMsg.amount);
}
}
}
function setRefundVerifier(bytes memory encodedVm) public {
if (msg.sender != guardian) {
revert Unauthorized();
}
(IWormhole.VM memory vm, bool valid, string memory reason) = refundVerifier.parseAndVerifyVM(encodedVm);
require(valid, reason);
if (usedSequences[vm.sequence]) {
revert SequenceAlreadyUsed();
}
usedSequences[vm.sequence] = true;
if (vm.emitterChainId != refundEmitterChainId) {
revert InvalidEmitterChain();
}
if (vm.emitterAddress != refundEmitterAddr) {
revert InvalidEmitterAddress();
}
RefundVerifier memory payload = parseRefundVerifierPayload(vm.payload);
refundVerifier = IWormhole(payload.verifier);
refundEmitterChainId = payload.emitterChainId;
refundEmitterAddr = payload.emitterAddr;
}
function processUnlocks(bytes memory payload, uint16 count, uint16 emitterChainId, bytes32 emitterAddress, uint16[] memory indexes) internal {
// If indexes array is empty, create a default array to iterate over all indices
if (indexes.length == 0) {
indexes = new uint16[](count);
for (uint16 i = 0; i < count; i++) {
indexes[i] = i;
}
}
for (uint i = 0; i < indexes.length; i++) {
uint16 index = indexes[i];
if (index >= count) {
revert InvalidBatchIndex();
}
uint currentOffset = index * UNLOCK_MSG_SIZE;
UnlockMsg memory unlockMsg = UnlockMsg({
action: uint8(Action.UNLOCK),
orderHash: payload.toBytes32(currentOffset),
srcChainId: payload.toUint16(currentOffset + 32),
tokenIn: payload.toBytes32(currentOffset + 34),
referrerAddr: payload.toBytes32(currentOffset + 66),
referrerBps: payload.toUint8(currentOffset + 98),
protocolBps: payload.toUint8(currentOffset + 99),
unlockReceiver: payload.toBytes32(currentOffset + 100),
driver: payload.toBytes32(currentOffset + 132),
fulfillTime: payload.toUint64(currentOffset + 164)
});
Order memory order = orders[unlockMsg.orderHash];
if (order.status != Status.CREATED) {
continue;
}
if (emitterChainId != order.destChainId) {
revert InvalidEmitterChain();
}
if (emitterAddress != emitters[order.destChainId]) {
revert InvalidEmitterAddress();
}
unlockOrder(unlockMsg, order);
}
}
function buildKey(
OrderParams memory params,
bytes32 tokenIn,
uint16 srcChainId,
uint8 protocolBps,
bytes32 customPayloadHash
) internal pure returns (Key memory) {
return Key({
payloadType: params.payloadType,
trader: params.trader,
srcChainId: srcChainId,
tokenIn: tokenIn,
destAddr: params.destAddr,
destChainId: params.destChainId,
tokenOut: params.tokenOut,
minAmountOut: params.minAmountOut,
gasDrop: params.gasDrop,
cancelFee: params.cancelFee,
refundFee: params.refundFee,
deadline: params.deadline,
referrerAddr: params.referrerAddr,
referrerBps: params.referrerBps,
protocolBps: protocolBps,
auctionMode: params.auctionMode,
random: params.random,
customPayloadHash: customPayloadHash
});
}
function parseFulfillPayload(bytes memory encoded) public pure returns (FulfillMsg memory fulfillMsg) {
uint index = 0;
fulfillMsg.action = encoded.toUint8(index);
index += 1;
if (fulfillMsg.action != uint8(Action.FULFILL)) {
revert InvalidAction();
}
fulfillMsg.orderHash = encoded.toBytes32(index);
index += 32;
fulfillMsg.driver = encoded.toBytes32(index);
index += 32;
fulfillMsg.promisedAmount = encoded.toUint64(index);
index += 8;
}
function parseUnlockPayload(bytes memory encoded) public pure returns (UnlockMsg memory unlockMsg) {
uint index = 0;
unlockMsg.action = encoded.toUint8(index);
index += 1;
if (unlockMsg.action != uint8(Action.UNLOCK)) {
revert InvalidAction();
}
unlockMsg.orderHash = encoded.toBytes32(index);
index += 32;
unlockMsg.srcChainId = encoded.toUint16(index);
index += 2;
unlockMsg.tokenIn = encoded.toBytes32(index);
index += 32;
unlockMsg.referrerAddr = encoded.toBytes32(index);
index += 32;
unlockMsg.referrerBps = encoded.toUint8(index);
index += 1;
unlockMsg.protocolBps = encoded.toUint8(index);
index += 1;
unlockMsg.unlockReceiver = encoded.toBytes32(index);
index += 32;
}
function parseRefundPayload(bytes memory encoded) public pure returns (RefundMsg memory refundMsg) {
uint index = 0;
refundMsg.action = encoded.toUint8(index);
index += 1;
if (refundMsg.action != uint8(Action.REFUND)) {
revert InvalidAction();
}
refundMsg.orderHash = encoded.toBytes32(index);
index += 32;
refundMsg.srcChainId = encoded.toUint16(index);
index += 2;
refundMsg.tokenIn = encoded.toBytes32(index);
index += 32;
refundMsg.trader = encoded.toBytes32(index);
index += 32;
refundMsg.canceler = encoded.toBytes32(index);
index += 32;
refundMsg.cancelFee = encoded.toUint64(index);
index += 8;
refundMsg.refundFee = encoded.toUint64(index);
index += 8;
}
function parseRescuePayload(bytes memory encoded) public pure returns (RescueMsg memory rescueMsg) {
uint index = 0;
rescueMsg.action = encoded.toUint8(index);
index += 1;
if (rescueMsg.action != uint8(Action.RESCUE)) {
revert InvalidAction();
}
rescueMsg.chainId = encoded.toUint16(index);
index += 2;
rescueMsg.orderHash = encoded.toBytes32(index);
index += 32;
rescueMsg.orderStatus = encoded.toUint8(index);
index += 1;
rescueMsg.token = address(uint160(encoded.toUint256(index)));
index += 32;
rescueMsg.amount = encoded.toUint64(index);
index += 8;
}
function parseRefundVerifierPayload(bytes memory encoded) public pure returns (RefundVerifier memory verifier) {
uint index = 0;
verifier.action = encoded.toUint8(index);
index += 1;
if (verifier.action != uint8(Action.SET_REFUND_VERIFIER)) {
revert InvalidAction();
}
verifier.verifier = address(uint160(encoded.toUint256(index)));
index += 32;
verifier.emitterChainId = encoded.toUint16(index);
index += 2;
verifier.emitterAddr = encoded.toBytes32(index);
index += 32;
}
function encodeKey(Key memory key) internal pure returns (bytes memory encoded) {
encoded = abi.encodePacked(
key.payloadType,
key.trader,
key.srcChainId,
key.tokenIn,
key.destAddr,
key.destChainId,
key.tokenOut,
key.minAmountOut,
key.gasDrop,
key.cancelFee,
key.refundFee,
key.deadline
);
encoded = encoded.concat(abi.encodePacked(
key.referrerAddr,
key.referrerBps,
key.protocolBps,
key.auctionMode,
key.random,
key.customPayloadHash
));
}
function payEth(address to, uint256 amount, bool revertOnFailure) internal {
(bool success, ) = payable(to).call{value: amount}('');
if (revertOnFailure) {
require(success, 'payment failed');
}
}
function truncateAddress(bytes32 b) internal pure returns (address) {
if (bytes12(b) != 0) {
revert InvalidEvmAddr();
}
return address(uint160(uint256(b)));
}
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 hashTypedData(bytes32 orderHash, uint256 amountIn, uint256 submissionFee) internal view returns (bytes32) {
bytes memory encoded = abi.encode(keccak256("CreateOrder(bytes32 OrderId,uint256 InputAmount,uint256 SubmissionFee)"), orderHash, amountIn, submissionFee);
return toTypedDataHash(domainSeparator, keccak256(encoded));
}
function toTypedDataHash(bytes32 _domainSeparator, bytes32 _structHash) internal pure returns (bytes32 digest) {
assembly {
let ptr := mload(0x40)
mstore(ptr, "\x19\x01")
mstore(add(ptr, 0x02), _domainSeparator)
mstore(add(ptr, 0x22), _structHash)
digest := keccak256(ptr, 0x42)
}
}
function pullTokensFrom(address tokenIn, uint256 amount, address from) internal returns (uint256) {
uint256 balance = IERC20(tokenIn).balanceOf(address(this));
IERC20(tokenIn).safeTransferFrom(from, address(this), amount);
return IERC20(tokenIn).balanceOf(address(this)) - balance;
}
function execPermit(
address token,
address owner,
PermitParams calldata permitParams
) internal {
IERC20Permit(token).permit(
owner,
address(this),
permitParams.value,
permitParams.deadline,
permitParams.v,
permitParams.r,
permitParams.s
);
}
function setPause(bool _pause) public {
if (msg.sender != guardian) {
revert Unauthorized();
}
paused = _pause;
}
function setFeeManager(address _feeManager) public {
if (msg.sender != guardian) {
revert Unauthorized();
}
feeManager = IFeeManager(_feeManager);
}
function setEmitters(uint16[] memory chainIds, bytes32[] memory addresses) public {
if (msg.sender != guardian) {
revert Unauthorized();
}
require(chainIds.length == addresses.length, 'invalid array length');
for (uint i=0; i<chainIds.length; i++) {
if (emitters[chainIds[i]] != bytes32(0)) {
revert EmitterAddressExists();
}
emitters[chainIds[i]] = addresses[i];
}
}
function changeGuardian(address newGuardian) public {
if (msg.sender != guardian) {
revert Unauthorized();
}
nextGuardian = newGuardian;
}
function claimGuardian() public {
if (msg.sender != nextGuardian) {
revert Unauthorized();
}
guardian = nextGuardian;
}
function getOrders(bytes32[] memory orderHashes) public view returns (Order[] memory) {
Order[] memory result = new Order[](orderHashes.length);
for (uint i=0; i<orderHashes.length; i++) {
result[i] = orders[orderHashes[i]];
}
return result;
}
receive() external payable {}
}// 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) (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: 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: MIT
pragma solidity ^0.8.0;
import "../swift/SwiftStructs.sol";
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 calcSwiftProtocolBps(
address tokenIn,
uint256 amountIn,
OrderParams memory params
) external returns (uint8);
function calcFastMCTPProtocolBps(
uint8 payloadType,
address localToken,
uint256 recievedAmount,
address tokenOut,
address referrerAddr,
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: Unlicense /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.8.0 <0.9.0; library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore(0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. )) } return tempBytes; } function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes.slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { require(_bytes.length >= _start + 1 , "toUint8_outOfBounds"); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } }
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IERC1271} from "../interfaces/IERC1271.sol";
library SignatureVerifier {
/// @notice Thrown when the passed in signature is not a valid length
error InvalidSignatureLength();
/// @notice Thrown when the recovered signer is equal to the zero address
error InvalidSignature();
/// @notice Thrown when the recovered signer does not equal the claimedSigner
error InvalidSigner();
/// @notice Thrown when the recovered contract signature is incorrect
error InvalidContractSignature();
bytes32 constant UPPER_BIT_MASK = (0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
function verify(bytes calldata signature, bytes32 hash, address claimedSigner) internal view {
bytes32 r;
bytes32 s;
uint8 v;
if (claimedSigner.code.length == 0) {
if (signature.length == 65) {
(r, s) = abi.decode(signature, (bytes32, bytes32));
v = uint8(signature[64]);
} else if (signature.length == 64) {
// EIP-2098
bytes32 vs;
(r, vs) = abi.decode(signature, (bytes32, bytes32));
s = vs & UPPER_BIT_MASK;
v = uint8(uint256(vs >> 255)) + 27;
} else {
revert InvalidSignatureLength();
}
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) revert InvalidSignature();
if (signer != claimedSigner) revert InvalidSigner();
} else {
bytes4 magicValue = IERC1271(claimedSigner).isValidSignature(hash, signature);
if (magicValue != IERC1271.isValidSignature.selector) revert InvalidContractSignature();
}
}
}struct Order {
Status status;
uint64 amountIn;
uint16 destChainId;
}
struct OrderParams {
uint8 payloadType;
bytes32 trader;
bytes32 destAddr;
uint16 destChainId;
bytes32 referrerAddr;
bytes32 tokenOut;
uint64 minAmountOut;
uint64 gasDrop;
uint64 cancelFee;
uint64 refundFee;
uint64 deadline;
uint8 referrerBps;
uint8 auctionMode;
bytes32 random;
}
struct ExtraParams {
uint16 srcChainId;
bytes32 tokenIn;
uint8 protocolBps;
bytes32 customPayloadHash;
}
struct PermitParams {
uint256 value;
uint256 deadline;
uint8 v;
bytes32 r;
bytes32 s;
}
struct Key {
uint8 payloadType;
bytes32 trader;
uint16 srcChainId;
bytes32 tokenIn;
bytes32 destAddr;
uint16 destChainId;
bytes32 tokenOut;
uint64 minAmountOut;
uint64 gasDrop;
uint64 cancelFee;
uint64 refundFee;
uint64 deadline;
bytes32 referrerAddr;
uint8 referrerBps;
uint8 protocolBps;
uint8 auctionMode;
bytes32 random;
bytes32 customPayloadHash;
}
struct PaymentParams {
uint8 payloadType;
bytes32 orderHash;
uint64 promisedAmount;
uint64 minAmountOut;
address destAddr;
address tokenOut;
uint64 gasDrop;
bool batch;
}
enum Status {
CREATED,
FULFILLED,
SETTLED,
UNLOCKED,
CANCELED,
REFUNDED
}
enum Action {
INVALID,
FULFILL,
UNLOCK,
REFUND,
BATCH_UNLOCK,
COMPRESSED_UNLOCK,
SET_REFUND_VERIFIER,
RESCUE
}
enum AuctionMode {
INVALID,
LIMIT_ORDER,
ENGLISH
}
struct UnlockMsg {
uint8 action;
bytes32 orderHash;
uint16 srcChainId;
bytes32 tokenIn;
bytes32 referrerAddr;
uint8 referrerBps;
uint8 protocolBps;
bytes32 unlockReceiver;
bytes32 driver;
uint64 fulfillTime;
}
uint constant UNLOCK_MSG_SIZE = 172; // excluding the action field
struct RefundMsg {
uint8 action;
bytes32 orderHash;
uint16 srcChainId;
bytes32 tokenIn;
bytes32 trader;
bytes32 canceler;
uint64 cancelFee;
uint64 refundFee;
}
struct FulfillMsg {
uint8 action;
bytes32 orderHash;
bytes32 driver;
uint64 promisedAmount;
uint16 penaltyPeriod;
}
struct TransferParams {
address from;
uint256 validAfter;
uint256 validBefore;
}
struct UnlockParams {
bytes32 recipient;
bytes32 driver;
bool batch;
}
struct RescueMsg {
uint8 action;
uint16 chainId;
bytes32 orderHash;
uint8 orderStatus;
address token;
uint64 amount;
}
struct RefundVerifier {
uint8 action;
address verifier;
uint16 emitterChainId;
bytes32 emitterAddr;
}error Paused(); error Unauthorized(); error InvalidAction(); error InvalidBpsFee(); error InvalidOrderStatus(); error InvalidOrderHash(); error InvalidEmitterChain(); error InvalidEmitterAddress(); error InvalidSrcChain(); error OrderNotExists(bytes32 orderHash); error SmallAmountIn(); error FeesTooHigh(); error InvalidGasDrop(); error InvalidDestChain(); error DuplicateOrder(); error InsufficientAmount(); error InvalidAmount(); error DeadlineViolation(); error InvalidWormholeFee(); error InvalidAuctionMode(); error InvalidEvmAddr(); error InvalidPayload(); error InvalidPayloadLength(); error EmitterAddressExists(); error InvalidBatchIndex(); error InvalidAuctionConfig(); error SequenceAlreadyUsed();
// 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) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC1271 {
/// @dev Should return whether the signature provided is valid for the provided data
/// @param hash Hash of the data to be signed
/// @param signature Signature byte array associated with _data
/// @return magicValue The bytes4 magic value 0x1626ba7e
function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}{
"remappings": [
"ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"openzeppelin/=lib/openzeppelin-contracts/contracts/",
"@openzeppelin/=lib/openzeppelin-contracts/",
"ExcessivelySafeCall/=lib/ExcessivelySafeCall/src/"
],
"optimizer": {
"enabled": true,
"runs": 1000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_wormhole","type":"address"},{"internalType":"address","name":"_refundVerifier","type":"address"},{"internalType":"uint16","name":"_refundEmitterChainId","type":"uint16"},{"internalType":"bytes32","name":"_refundEmitterAddr","type":"bytes32"},{"internalType":"address","name":"_feeManager","type":"address"},{"internalType":"address","name":"_rescueVault","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DuplicateOrder","type":"error"},{"inputs":[],"name":"EmitterAddressExists","type":"error"},{"inputs":[],"name":"FeesTooHigh","type":"error"},{"inputs":[],"name":"InvalidAction","type":"error"},{"inputs":[],"name":"InvalidBatchIndex","type":"error"},{"inputs":[],"name":"InvalidBpsFee","type":"error"},{"inputs":[],"name":"InvalidContractSignature","type":"error"},{"inputs":[],"name":"InvalidDestChain","type":"error"},{"inputs":[],"name":"InvalidEmitterAddress","type":"error"},{"inputs":[],"name":"InvalidEmitterChain","type":"error"},{"inputs":[],"name":"InvalidEvmAddr","type":"error"},{"inputs":[],"name":"InvalidGasDrop","type":"error"},{"inputs":[],"name":"InvalidOrderStatus","type":"error"},{"inputs":[],"name":"InvalidPayload","type":"error"},{"inputs":[],"name":"InvalidPayloadLength","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidSignatureLength","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidSrcChain","type":"error"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"OrderNotExists","type":"error"},{"inputs":[],"name":"Paused","type":"error"},{"inputs":[],"name":"SequenceAlreadyUsed","type":"error"},{"inputs":[],"name":"SmallAmountIn","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"key","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"sequence","type":"uint64"}],"name":"OrderCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"OrderCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"key","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"sequence","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"netAmount","type":"uint256"}],"name":"OrderFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"key","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"netAmount","type":"uint256"}],"name":"OrderRefunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"OrderUnlocked","type":"event"},{"inputs":[{"internalType":"address","name":"newGuardian","type":"address"}],"name":"changeGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint8","name":"payloadType","type":"uint8"},{"internalType":"bytes32","name":"trader","type":"bytes32"},{"internalType":"bytes32","name":"destAddr","type":"bytes32"},{"internalType":"uint16","name":"destChainId","type":"uint16"},{"internalType":"bytes32","name":"referrerAddr","type":"bytes32"},{"internalType":"bytes32","name":"tokenOut","type":"bytes32"},{"internalType":"uint64","name":"minAmountOut","type":"uint64"},{"internalType":"uint64","name":"gasDrop","type":"uint64"},{"internalType":"uint64","name":"cancelFee","type":"uint64"},{"internalType":"uint64","name":"refundFee","type":"uint64"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint8","name":"referrerBps","type":"uint8"},{"internalType":"uint8","name":"auctionMode","type":"uint8"},{"internalType":"bytes32","name":"random","type":"bytes32"}],"internalType":"struct OrderParams","name":"params","type":"tuple"},{"internalType":"bytes","name":"customPayload","type":"bytes"}],"name":"createOrderWithEth","outputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"components":[{"internalType":"uint8","name":"payloadType","type":"uint8"},{"internalType":"bytes32","name":"trader","type":"bytes32"},{"internalType":"bytes32","name":"destAddr","type":"bytes32"},{"internalType":"uint16","name":"destChainId","type":"uint16"},{"internalType":"bytes32","name":"referrerAddr","type":"bytes32"},{"internalType":"bytes32","name":"tokenOut","type":"bytes32"},{"internalType":"uint64","name":"minAmountOut","type":"uint64"},{"internalType":"uint64","name":"gasDrop","type":"uint64"},{"internalType":"uint64","name":"cancelFee","type":"uint64"},{"internalType":"uint64","name":"refundFee","type":"uint64"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint8","name":"referrerBps","type":"uint8"},{"internalType":"uint8","name":"auctionMode","type":"uint8"},{"internalType":"bytes32","name":"random","type":"bytes32"}],"internalType":"struct OrderParams","name":"params","type":"tuple"},{"internalType":"bytes","name":"customPayload","type":"bytes"},{"internalType":"uint256","name":"submissionFee","type":"uint256"},{"internalType":"bytes","name":"signedOrderHash","type":"bytes"},{"components":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct PermitParams","name":"permitParams","type":"tuple"}],"name":"createOrderWithSig","outputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"components":[{"internalType":"uint8","name":"payloadType","type":"uint8"},{"internalType":"bytes32","name":"trader","type":"bytes32"},{"internalType":"bytes32","name":"destAddr","type":"bytes32"},{"internalType":"uint16","name":"destChainId","type":"uint16"},{"internalType":"bytes32","name":"referrerAddr","type":"bytes32"},{"internalType":"bytes32","name":"tokenOut","type":"bytes32"},{"internalType":"uint64","name":"minAmountOut","type":"uint64"},{"internalType":"uint64","name":"gasDrop","type":"uint64"},{"internalType":"uint64","name":"cancelFee","type":"uint64"},{"internalType":"uint64","name":"refundFee","type":"uint64"},{"internalType":"uint64","name":"deadline","type":"uint64"},{"internalType":"uint8","name":"referrerBps","type":"uint8"},{"internalType":"uint8","name":"auctionMode","type":"uint8"},{"internalType":"bytes32","name":"random","type":"bytes32"}],"internalType":"struct OrderParams","name":"params","type":"tuple"},{"internalType":"bytes","name":"customPayload","type":"bytes"}],"name":"createOrderWithToken","outputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"emitters","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":"bytes32[]","name":"orderHashes","type":"bytes32[]"}],"name":"getOrders","outputs":[{"components":[{"internalType":"enum Status","name":"status","type":"uint8"},{"internalType":"uint64","name":"amountIn","type":"uint64"},{"internalType":"uint16","name":"destChainId","type":"uint16"}],"internalType":"struct Order[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextGuardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"orders","outputs":[{"internalType":"enum Status","name":"status","type":"uint8"},{"internalType":"uint64","name":"amountIn","type":"uint64"},{"internalType":"uint16","name":"destChainId","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encoded","type":"bytes"}],"name":"parseFulfillPayload","outputs":[{"components":[{"internalType":"uint8","name":"action","type":"uint8"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"bytes32","name":"driver","type":"bytes32"},{"internalType":"uint64","name":"promisedAmount","type":"uint64"},{"internalType":"uint16","name":"penaltyPeriod","type":"uint16"}],"internalType":"struct FulfillMsg","name":"fulfillMsg","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encoded","type":"bytes"}],"name":"parseRefundPayload","outputs":[{"components":[{"internalType":"uint8","name":"action","type":"uint8"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"uint16","name":"srcChainId","type":"uint16"},{"internalType":"bytes32","name":"tokenIn","type":"bytes32"},{"internalType":"bytes32","name":"trader","type":"bytes32"},{"internalType":"bytes32","name":"canceler","type":"bytes32"},{"internalType":"uint64","name":"cancelFee","type":"uint64"},{"internalType":"uint64","name":"refundFee","type":"uint64"}],"internalType":"struct RefundMsg","name":"refundMsg","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encoded","type":"bytes"}],"name":"parseRefundVerifierPayload","outputs":[{"components":[{"internalType":"uint8","name":"action","type":"uint8"},{"internalType":"address","name":"verifier","type":"address"},{"internalType":"uint16","name":"emitterChainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddr","type":"bytes32"}],"internalType":"struct RefundVerifier","name":"verifier","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encoded","type":"bytes"}],"name":"parseRescuePayload","outputs":[{"components":[{"internalType":"uint8","name":"action","type":"uint8"},{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"uint8","name":"orderStatus","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint64","name":"amount","type":"uint64"}],"internalType":"struct RescueMsg","name":"rescueMsg","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encoded","type":"bytes"}],"name":"parseUnlockPayload","outputs":[{"components":[{"internalType":"uint8","name":"action","type":"uint8"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"uint16","name":"srcChainId","type":"uint16"},{"internalType":"bytes32","name":"tokenIn","type":"bytes32"},{"internalType":"bytes32","name":"referrerAddr","type":"bytes32"},{"internalType":"uint8","name":"referrerBps","type":"uint8"},{"internalType":"uint8","name":"protocolBps","type":"uint8"},{"internalType":"bytes32","name":"unlockReceiver","type":"bytes32"},{"internalType":"bytes32","name":"driver","type":"bytes32"},{"internalType":"uint64","name":"fulfillTime","type":"uint64"}],"internalType":"struct UnlockMsg","name":"unlockMsg","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refundEmitterAddr","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refundEmitterChainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedVm","type":"bytes"},{"internalType":"bool","name":"fast","type":"bool"}],"name":"refundOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"refundVerifier","outputs":[{"internalType":"contract IWormhole","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedVm","type":"bytes"}],"name":"rescue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rescueVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16[]","name":"chainIds","type":"uint16[]"},{"internalType":"bytes32[]","name":"addresses","type":"bytes32[]"}],"name":"setEmitters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeManager","type":"address"}],"name":"setFeeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_pause","type":"bool"}],"name":"setPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedVm","type":"bytes"}],"name":"setRefundVerifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedVm","type":"bytes"},{"internalType":"bytes","name":"encodedPayload","type":"bytes"},{"internalType":"uint16[]","name":"indexes","type":"uint16[]"}],"name":"unlockCompressedBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedVm","type":"bytes"}],"name":"unlockSingle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"usedSequences","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wormhole","outputs":[{"internalType":"contract IWormhole","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60c060405234801561000f575f5ffd5b50604051615e96380380615e9683398101604081905261002e91610132565b60015f819055600480546001600160a01b031990811633179091556001600160a01b039788166080908152825461ffff97909716600160a01b026001600160b01b03199097169789169790971795909517905560029290925560038054918616919093161790915590911660a0908152604080517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a8666020808301919091527f31470924aa18e932d2ed4194a9334695b7301e5a1f1225acc3e6f40db2647de7828401524660608301523082860152825180830390950185529201905281519101206006556101a4565b80516001600160a01b038116811461012d575f5ffd5b919050565b5f5f5f5f5f5f60c08789031215610147575f5ffd5b61015087610117565b955061015e60208801610117565b9450604087015161ffff81168114610174575f5ffd5b6060880151909450925061018a60808801610117565b915061019860a08801610117565b90509295509295509295565b60805160a051615c6861022e5f395f81816105bc01528181612fbb0152612ff901525f81816103b40152818161078101528181610981015281816113de015281816114c4015281816118770152818161193301528181611ec001528181612013015281816128de0152818161296f01528181612cf601528181612e9501526132830152615c685ff3fe6080604052600436106101d3575f3560e01c80639c3f1e90116100fd578063bedb86fb11610092578063d383e3e711610062578063d383e3e7146105fd578063dae2fc121461065f578063f1d3ac4f1461067e578063f6203990146106ee575f5ffd5b8063bedb86fb14610579578063ca5662b014610598578063cc8388d0146105ab578063d0fb0203146105de575f5ffd5b8063ac432e63116100cd578063ac432e63146104e8578063b365b19114610507578063b854c12b14610526578063bdacaae71461055a575f5ffd5b80639c3f1e90146104195780639e70a74014610472578063a3a308341461049d578063a5e1ea7d146104bc575f5ffd5b806346963505116101735780636147435b116101435780636147435b1461037657806384acd1bb146103a35780638b2ab1b7146103d6578063919a1704146103eb575f5ffd5b806346963505146102e9578063472d35b9146103085780634818e84d146103275780635c975abb14610346575f5ffd5b806339f3fbd9116101ae57806339f3fbd91461023d5780633d47486614610272578063452a93201461029e578063459656ee146102d5575f5ffd5b8063119abf67146101de5780632d67b5ea146101ff5780632fcb4f041461021e575f5ffd5b366101da57005b5f5ffd5b3480156101e9575f5ffd5b506101fd6101f8366004614bcd565b610774565b005b34801561020a575f5ffd5b506101fd610219366004614cad565b610974565b348015610229575f5ffd5b506101fd610238366004614d4c565b610b45565b348015610248575f5ffd5b5061025c610257366004614bcd565b610b9e565b6040516102699190614d67565b60405180910390f35b34801561027d575f5ffd5b5061029161028c366004614e34565b610d03565b6040516102699190614e99565b3480156102a9575f5ffd5b506004546102bd906001600160a01b031681565b6040516001600160a01b039091168152602001610269565b3480156102e0575f5ffd5b506101fd610e34565b3480156102f4575f5ffd5b506101fd610303366004614bcd565b610e8f565b348015610313575f5ffd5b506101fd610322366004614d4c565b611081565b348015610332575f5ffd5b506005546102bd906001600160a01b031681565b348015610351575f5ffd5b5060055461036690600160a01b900460ff1681565b6040519015158152602001610269565b348015610381575f5ffd5b5061039561039036600461504c565b6110da565b604051908152602001610269565b3480156103ae575f5ffd5b506102bd7f000000000000000000000000000000000000000000000000000000000000000081565b3480156103e1575f5ffd5b5061039560025481565b3480156103f6575f5ffd5b5061036661040536600461512d565b60096020525f908152604090205460ff1681565b348015610424575f5ffd5b50610463610433366004615148565b60076020525f908152604090205460ff81169061010081046001600160401b031690600160481b900461ffff1683565b6040516102699392919061515f565b34801561047d575f5ffd5b5061039561048c36600461518e565b60086020525f908152604090205481565b3480156104a8575f5ffd5b506103956104b73660046151a9565b61169f565b3480156104c7575f5ffd5b506104db6104d6366004614bcd565b611c4d565b6040516102699190615211565b3480156104f3575f5ffd5b506101fd6105023660046152ba565b611dae565b348015610512575f5ffd5b506101fd610521366004615308565b612573565b348015610531575f5ffd5b5060015461054790600160a01b900461ffff1681565b60405161ffff9091168152602001610269565b348015610565575f5ffd5b506001546102bd906001600160a01b031681565b348015610584575f5ffd5b506101fd61059336600461536b565b6126bb565b6103956105a6366004615386565b61271e565b3480156105b6575f5ffd5b506102bd7f000000000000000000000000000000000000000000000000000000000000000081565b3480156105e9575f5ffd5b506003546102bd906001600160a01b031681565b348015610608575f5ffd5b5061061c610617366004614bcd565b612c00565b6040516102699190815160ff1681526020808301516001600160a01b03169082015260408083015161ffff16908201526060918201519181019190915260800190565b34801561066a575f5ffd5b506101fd610679366004614bcd565b612cc7565b348015610689575f5ffd5b5061069d610698366004614bcd565b61304a565b60405161026991905f60a08201905060ff835116825260208301516020830152604083015160408301526001600160401b03606084015116606083015261ffff608084015116608083015292915050565b3480156106f9575f5ffd5b5061070d610708366004614bcd565b613114565b60405161026991905f60c08201905060ff835116825261ffff60208401511660208301526040830151604083015260ff60608401511660608301526001600160a01b0360808401511660808301526001600160401b0360a08401511660a083015292915050565b61077c61322a565b5f5f5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c0fd8bde856040518263ffffffff1660e01b81526004016107cb91906153f7565b5f60405180830381865afa1580156107e5573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261080c919081019061553d565b92509250925081819061083b5760405162461bcd60e51b815260040161083291906153f7565b60405180910390fd5b505f61084a8460e00151611c4d565b6020808201515f9081526007909152604080822081516060810190925280549394509192909190829060ff16600581111561088757610887614e65565b600581111561089857610898614e65565b815290546001600160401b03610100820416602083015261ffff600160481b909104811660409283015290820151919250165f036108f157816020015160405163956fc85760e01b815260040161083291815260200190565b806040015161ffff16856060015161ffff1614610921576040516327e8d62960e11b815260040160405180910390fd5b60408082015161ffff165f908152600860205220546080860151146109595760405163d08bf9e160e01b815260040160405180910390fd5b6109638282613281565b505050505061097160015f55565b50565b61097c61322a565b5f5f5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c0fd8bde876040518263ffffffff1660e01b81526004016109cb91906153f7565b5f60405180830381865afa1580156109e5573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610a0c919081019061553d565b925092509250818190610a325760405162461bcd60e51b815260040161083291906153f7565b5060e08301515f90610a449082613896565b905060ff8116600514610a6a57604051634a7f394f60e01b815260040160405180910390fd5b60e08401515f90610a7c9060016138fb565b8751909150610a9060ac61ffff84166156a7565b14610ac7576040517f5e7407c200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8651602088012060e08601515f90610ae0906003613960565b9050808214610b1b576040517f7c6953f900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b30898489606001518a608001518c6139c5565b50505050505050610b4060015f55565b505050565b6004546001600160a01b03163314610b6f576040516282b42960e81b815260040160405180910390fd5b6005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905290610be88382613896565b60ff168252610bf86001826156be565b825190915060ff16600314610c2057604051634a7f394f60e01b815260040160405180910390fd5b610c2a8382613960565b602080840191909152610c3d90826156be565b9050610c4983826138fb565b61ffff166040830152610c5d6002826156be565b9050610c698382613960565b6060830152610c796020826156be565b9050610c858382613960565b6080830152610c956020826156be565b9050610ca18382613960565b60a0830152610cb16020826156be565b9050610cbd8382613cec565b6001600160401b031660c0830152610cd66008826156be565b9050610ce28382613cec565b6001600160401b031660e0830152610cfb6008826156be565b905050919050565b60605f82516001600160401b03811115610d1f57610d1f614aa3565b604051908082528060200260200182016040528015610d6857816020015b604080516060810182525f80825260208083018290529282015282525f19909201910181610d3d5790505b5090505f5b8351811015610e2d5760075f858381518110610d8b57610d8b6156d1565b602002602001015181526020019081526020015f206040518060600160405290815f82015f9054906101000a900460ff166005811115610dcd57610dcd614e65565b6005811115610dde57610dde614e65565b8152905461010081046001600160401b03166020830152600160481b900461ffff166040909101528251839083908110610e1a57610e1a6156d1565b6020908102919091010152600101610d6d565b5092915050565b6005546001600160a01b03163314610e5e576040516282b42960e81b815260040160405180910390fd5b6005546004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909216919091179055565b6004546001600160a01b03163314610eb9576040516282b42960e81b815260040160405180910390fd5b60015460405163607ec5ef60e11b81525f91829182916001600160a01b03169063c0fd8bde90610eed9087906004016153f7565b5f60405180830381865afa158015610f07573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610f2e919081019061553d565b925092509250818190610f545760405162461bcd60e51b815260040161083291906153f7565b5060a08301516001600160401b03165f9081526009602052604090205460ff1615610f9257604051633891b8bb60e11b815260040160405180910390fd5b60a08301516001600160401b03165f908152600960205260409020805460ff1916600190811790915554606084015161ffff908116600160a01b9092041614610fee576040516327e8d62960e11b815260040160405180910390fd5b6002548360800151146110145760405163d08bf9e160e01b815260040160405180910390fd5b5f6110228460e00151612c00565b602081015160018054604084015161ffff16600160a01b027fffffffffffffffffffff000000000000000000000000000000000000000000009091166001600160a01b0390931692909217919091179055606001516002555050505050565b6004546001600160a01b031633146110ab576040516282b42960e81b815260040160405180910390fd5b6003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b5f6110e361322a565b600554600160a01b900460ff161561110e576040516313d0ff5960e31b815260040160405180910390fd5b5f61111c8860200151613d51565b9050611128868a6156be565b6040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301523060248301528c169063dd62ed3e90604401602060405180830381865afa15801561118b573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111af91906156e5565b10156111c0576111c08a8285613da5565b6111cb8a8a83613e58565b98508515611257576003546111ef906001600160a01b038c81169184911689613f54565b600354604051631c43245560e01b81523360048201526001600160a01b038c811660248301526044820189905290911690631c432455906064015f604051808303815f87803b158015611240575f5ffd5b505af1158015611252573d5f5f3e3d5ffd5b505050505b5f61126a8a6112658d613ff3565b6140bf565b9050806001600160401b03165f03611295576040516356fdd81f60e11b815260040160405180910390fd5b806001600160401b03168961012001518a61010001516112b591906156fc565b6001600160401b0316106112dc5760405163192069c360e31b815260040160405180910390fd5b60a08901511580156112fa575060e08901516001600160401b031615155b1561131857604051636e51edcd60e11b815260040160405180910390fd5b600354604051633972bf5560e11b81525f916001600160a01b0316906372e57eaa9061134c908f908f908f9060040161571b565b6020604051808303815f875af1158015611368573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061138c9190615828565b905060c860ff168a610160015160ff1611806113ab575060c860ff8216115b156113c957604051633f6e8d0d60e21b815260040160405180910390fd5b61148361147e8b8e6001600160a01b03165f1b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa158015611438573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061145c9190615843565b858f5f015160ff16600214611471575f6140f6565b8e805190602001206140f6565b614285565b8051906020012093506114a461149a858d8b614396565b8890889086614434565b60608a015161ffff165f90815260086020526040902054158061155157507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa15801561151e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115429190615843565b61ffff168a6060015161ffff16145b1561156f576040516355ef7a1d60e11b815260040160405180910390fd5b5f84815260076020526040902054600160481b900461ffff16156115a65760405163015b9d8b60e41b815260040160405180910390fd5b6040805160608101909152805f81526001600160401b03841660208083019190915260608d015161ffff166040928301525f87815260079091522081518154829060ff191660018360058111156115ff576115ff614e65565b02179055506020820151815460409384015161ffff16600160481b026affff000000000000000000196001600160401b0390931661010002929092166affffffffffffffffffff001990911617179055517f918554b6bd6e2895ce6553de5de0e1a69db5289aa0e4fe193a0dcd1f143474779061167f9086815260200190565b60405180910390a150505061169360015f55565b98975050505050505050565b5f6116a861322a565b600554600160a01b900460ff16156116d3576040516313d0ff5960e31b815260040160405180910390fd5b6116de858533613e58565b93505f6116ee8561126588613ff3565b9050806001600160401b03165f03611719576040516356fdd81f60e11b815260040160405180910390fd5b806001600160401b031684610120015185610100015161173991906156fc565b6001600160401b0316106117605760405163192069c360e31b815260040160405180910390fd5b60a084015115801561177e575060e08401516001600160401b031615155b1561179c57604051636e51edcd60e11b815260040160405180910390fd5b600354604051633972bf5560e11b81525f916001600160a01b0316906372e57eaa906117d0908a908a908a9060040161571b565b6020604051808303815f875af11580156117ec573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118109190615828565b905060c860ff1685610160015160ff16118061182f575060c860ff8216115b1561184d57604051633f6e8d0d60e21b815260040160405180910390fd5b84515f9060ff166002036118645750835160208501205b5f6118fc878a6001600160a01b03165f1b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118d1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118f59190615843565b86866140f6565b905061190781614285565b8051602091820120606089015161ffff165f908152600890925260409091205490955015806119c057507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa15801561198d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119b19190615843565b61ffff16876060015161ffff16145b156119de576040516355ef7a1d60e11b815260040160405180910390fd5b5f858152600760205260408082208151606081019092528054829060ff166005811115611a0d57611a0d614e65565b6005811115611a1e57611a1e614e65565b815290546001600160401b03610100820416602083015261ffff600160481b9091048116604092830152908201519192501615611b565780602001516001600160401b0316856001600160401b0316118015611a8b57505f81516005811115611a8957611a89614e65565b145b15611b3d57896001600160a01b031663a9059cbb611aac8a60200151613d51565b611acb84602001516001600160401b0316611ac68f613ff3565b6146c5565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af1158015611b13573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b37919061585e565b50611b56565b60405163015b9d8b60e41b815260040160405180910390fd5b6040805160608101909152805f81526001600160401b03871660208083019190915260608b015161ffff166040928301525f89815260079091522081518154829060ff19166001836005811115611baf57611baf614e65565b02179055506020820151815460409384015161ffff16600160481b026affff000000000000000000196001600160401b0390931661010002929092166affffffffffffffffffff001990911617179055517f918554b6bd6e2895ce6553de5de0e1a69db5289aa0e4fe193a0dcd1f1434747790611c2f9088815260200190565b60405180910390a15050505050611c4560015f55565b949350505050565b60408051610140810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905290611ca78382613896565b60ff168252611cb76001826156be565b825190915060ff16600214611cdf57604051634a7f394f60e01b815260040160405180910390fd5b611ce98382613960565b602080840191909152611cfc90826156be565b9050611d0883826138fb565b61ffff166040830152611d1c6002826156be565b9050611d288382613960565b6060830152611d386020826156be565b9050611d448382613960565b6080830152611d546020826156be565b9050611d608382613896565b60ff1660a0830152611d736001826156be565b9050611d7f8382613896565b60ff1660c0830152611d926001826156be565b9050611d9e8382613960565b60e0830152610cfb6020826156be565b611db661322a565b60408051610160810182525f8082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820181905261010082018390526101208201526101408101919091525f6060838015611e2757506001546001600160a01b031615155b15611ea95760015460405163607ec5ef60e11b81526001600160a01b039091169063c0fd8bde90611e5c9088906004016153f7565b5f60405180830381865afa158015611e76573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611e9d919081019061553d565b91945092509050611f3e565b60405163607ec5ef60e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c0fd8bde90611ef59088906004016153f7565b5f60405180830381865afa158015611f0f573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611f36919081019061553d565b919450925090505b8082611f5d5760405162461bcd60e51b815260040161083291906153f7565b505f611f6c8460e00151610b9e565b6020808201515f9081526007909152604080822081516060810190925280549394509192909190829060ff166005811115611fa957611fa9614e65565b6005811115611fba57611fba614e65565b8152905461010081046001600160401b0316602080840191909152600160481b90910461ffff1660409283015281517f9a8a059200000000000000000000000000000000000000000000000000000000815291519293507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031692639a8a05929260048082019392918290030181865afa158015612061573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120859190615843565b61ffff16826040015161ffff16146120b057604051633bec3b7d60e11b815260040160405180910390fd5b806040015161ffff165f036120e057816020015160405163956fc85760e01b815260040161083291815260200190565b5f815160058111156120f4576120f4614e65565b1461211257604051632916ae3360e01b815260040160405180910390fd5b6020828101515f908152600790915260409020805460ff19166005179055851561219657600154606086015161ffff908116600160a01b909204161461216b576040516327e8d62960e11b815260040160405180910390fd5b6002548560800151146121915760405163d08bf9e160e01b815260040160405180910390fd5b6121fe565b806040015161ffff16856060015161ffff16146121c6576040516327e8d62960e11b815260040160405180910390fd5b60408082015161ffff165f908152600860205220546080860151146121fe5760405163d08bf9e160e01b815260040160405180910390fd5b5f61220c8360800151613d51565b60a08401516060850151919250905f9061222590613d51565b90505f6001600160a01b03821661223e5750601261224a565b61224782613ff3565b90505b5f6122628760c001516001600160401b0316836146c5565b90505f61227c8860e001516001600160401b0316846146c5565b90505f61229688602001516001600160401b0316856146c5565b90505f826122a48584615879565b6122ae9190615879565b90506001600160a01b0386166123a757831561232b57600354604051631c43245560e01b81526001600160a01b0389811660048301525f60248301526044820187905290911690631c4324559086906064015f604051808303818588803b158015612317575f5ffd5b505af193505050508015612329575060015b505b821561239657600354604051631c43245560e01b81523360048201525f6024820152604481018590526001600160a01b0390911690631c4324559085906064015f604051808303818588803b158015612382575f5ffd5b505af193505050508015612394575060015b505b6123a2888260016146f2565b61251b565b831561241357600354604051631c43245560e01b81526001600160a01b03898116600483015288811660248301526044820187905290911690631c432455906064015f604051808303815f87803b158015612400575f5ffd5b505af1925050508015612411575060015b505b821561247d57600354604051631c43245560e01b81523360048201526001600160a01b0388811660248301526044820186905290911690631c432455906064015f604051808303815f87803b15801561246a575f5ffd5b505af192505050801561247b575060015b505b5f61248884866156be565b905080156125055760035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018390529088169063a9059cbb906044016020604051808303815f875af19250505080156124fe575060408051601f3d908101601f191682019092526124fb9181019061585e565b60015b1561250557505b6125196001600160a01b0388168a84614797565b505b6020808b0151604080519182529181018390527fbff5487f6422ba4acbcde6bd5e0ccb83124c240b9deb6a72e7b5eb8c7b71d6fc910160405180910390a15050505050505050505050505061256f60015f55565b5050565b6004546001600160a01b0316331461259d576040516282b42960e81b815260040160405180910390fd5b80518251146125ee5760405162461bcd60e51b815260206004820152601460248201527f696e76616c6964206172726179206c656e6774680000000000000000000000006044820152606401610832565b5f5b8251811015610b40575f5f1b60085f858481518110612611576126116156d1565b602002602001015161ffff1661ffff1681526020019081526020015f205414612666576040517f9a23a9de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818181518110612678576126786156d1565b602002602001015160085f858481518110612695576126956156d1565b60209081029190910181015161ffff1682528101919091526040015f20556001016125f0565b6004546001600160a01b031633146126e5576040516282b42960e81b815260040160405180910390fd5b60058054911515600160a01b027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b5f61272761322a565b600554600160a01b900460ff1615612752576040516313d0ff5960e31b815260040160405180910390fd5b5f61275e3460126140bf565b9050806001600160401b03165f03612789576040516356fdd81f60e11b815260040160405180910390fd5b806001600160401b03168461012001518561010001516127a991906156fc565b6001600160401b0316106127d05760405163192069c360e31b815260040160405180910390fd5b60a08401511580156127ee575060e08401516001600160401b031615155b1561280c57604051636e51edcd60e11b815260040160405180910390fd5b600354604051633972bf5560e11b81525f916001600160a01b0316906372e57eaa9061284090849034908a9060040161571b565b6020604051808303815f875af115801561285c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128809190615828565b905060c860ff1685610160015160ff16118061289f575060c860ff8216115b156128bd57604051633f6e8d0d60e21b815260040160405180910390fd5b84515f9060ff166002036128d45750835160208501205b5f612938875f5f1b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118d1573d5f5f3e3d5ffd5b905061294381614285565b8051602091820120606089015161ffff165f908152600890925260409091205490955015806129fc57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129c9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129ed9190615843565b61ffff16876060015161ffff16145b15612a1a576040516355ef7a1d60e11b815260040160405180910390fd5b5f858152600760205260408082208151606081019092528054829060ff166005811115612a4957612a49614e65565b6005811115612a5a57612a5a614e65565b815290546001600160401b0361010082041660208084019190915261ffff600160481b9283900481166040948501525f8b81526007909252929020549293509091041615612b0b5780602001516001600160401b0316856001600160401b0316118015612ad857505f81516005811115612ad657612ad6614e65565b145b15611b3d57612b0b612aed8960200151613d51565b612b0583602001516001600160401b031660126146c5565b5f6146f2565b6040805160608101909152805f81526001600160401b03871660208083019190915260608b015161ffff166040928301525f89815260079091522081518154829060ff19166001836005811115612b6457612b64614e65565b02179055506020820151815460409384015161ffff16600160481b026affff000000000000000000196001600160401b0390931661010002929092166affffffffffffffffffff001990911617179055517f918554b6bd6e2895ce6553de5de0e1a69db5289aa0e4fe193a0dcd1f1434747790612be49088815260200190565b60405180910390a15050505050612bfa60015f55565b92915050565b604080516080810182525f808252602082018190529181018290526060810182905290612c2d8382613896565b60ff168252612c3d6001826156be565b825190915060ff16600614612c6557604051634a7f394f60e01b815260040160405180910390fd5b612c6f83826147c7565b6001600160a01b0316602080840191909152612c8b90826156be565b9050612c9783826138fb565b61ffff166040830152612cab6002826156be565b9050612cb78382613960565b6060830152610cfb6020826156be565b6004546001600160a01b03163314612cf1576040516282b42960e81b815260040160405180910390fd5b5f5f5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c0fd8bde856040518263ffffffff1660e01b8152600401612d4091906153f7565b5f60405180830381865afa158015612d5a573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612d81919081019061553d565b925092509250818190612da75760405162461bcd60e51b815260040161083291906153f7565b5060a08301516001600160401b03165f9081526009602052604090205460ff1615612de557604051633891b8bb60e11b815260040160405180910390fd5b60a08301516001600160401b03165f908152600960205260409020805460ff19166001908117909155606084015161ffff1614612e35576040516327e8d62960e11b815260040160405180910390fd5b60015f5260086020527fad67d757c34507f157cacfa2e3153e9f260a2244f30428821be7be64587ac55f54608084015114612e835760405163d08bf9e160e01b815260040160405180910390fd5b5f612e918460e00151613114565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa158015612eef573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f139190615843565b61ffff16816020015161ffff1614612f3e57604051633bec3b7d60e11b815260040160405180910390fd5b604081015115612f9157806060015160ff166005811115612f6157612f61614e65565b6040808301515f908152600760205220805460ff19166001836005811115612f8b57612f8b614e65565b02179055505b60a08101516001600160401b0316156130435760808101516001600160a01b0316612ff457612fef7f00000000000000000000000000000000000000000000000000000000000000008260a001516001600160401b031660016146f2565b613043565b6130437f00000000000000000000000000000000000000000000000000000000000000008260a001516001600160401b031683608001516001600160a01b03166147979092919063ffffffff16565b5050505050565b6040805160a0810182525f8082526020820181905291810182905260608101829052608081018290529061307e8382613896565b60ff16825261308e6001826156be565b825190915060ff166001146130b657604051634a7f394f60e01b815260040160405180910390fd5b6130c08382613960565b6020808401919091526130d390826156be565b90506130df8382613960565b60408301526130ef6020826156be565b90506130fb8382613cec565b6001600160401b03166060830152610cfb6008826156be565b6040805160c0810182525f80825260208201819052918101829052606081018290526080810182905260a081018290529061314f8382613896565b60ff16825261315f6001826156be565b825190915060ff1660071461318757604051634a7f394f60e01b815260040160405180910390fd5b61319183826138fb565b61ffff1660208301526131a56002826156be565b90506131b18382613960565b60408301526131c16020826156be565b90506131cd8382613896565b60ff1660608301526131e06001826156be565b90506131ec83826147c7565b6001600160a01b031660808301526132056020826156be565b90506132118382613cec565b6001600160401b031660a0830152610cfb6008826156be565b60025f540361327b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610832565b60025f55565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132dd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906133019190615843565b61ffff16826040015161ffff161461332c57604051633bec3b7d60e11b815260040160405180910390fd5b5f8151600581111561334057613340614e65565b1461335e57604051632916ae3360e01b815260040160405180910390fd5b6020828101515f908152600790915260408120805460ff1916600317905560e083015161338a90613d51565b90505f61339a8460600151613d51565b90505f6001600160a01b0382166133b3575060126133bf565b6133bc82613ff3565b90505b5f6127108660a0015160ff1686602001516133da919061588c565b6133e491906158c2565b90505f86608001515f1c90505f6127108860c0015160ff16886020015161340b919061588c565b61341591906158c2565b90505f60035f9054906101000a90046001600160a01b03166001600160a01b031663c415b95c6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015613486575060408051601f3d908101601f19168201909252613483918101906158ef565b60015b1561348e5790505b5f82858a602001516134a0919061590a565b6134aa919061590a565b90506001600160a01b038716613632575f856001600160401b03161180156134da57506001600160a01b03841615155b1561355d575f6134f3866001600160401b0316886146c5565b600354604051631c43245560e01b81526001600160a01b0388811660048301525f602483015260448201849052929350911690631c4324559083906064015f604051808303818588803b158015613548575f5ffd5b505af19350505050801561355a575060015b50505b5f836001600160401b031611801561357d57506001600160a01b03821615155b15613600575f613596846001600160401b0316886146c5565b600354604051631c43245560e01b81526001600160a01b0386811660048301525f602483015260448201849052929350911690631c4324559083906064015f604051808303818588803b1580156135eb575f5ffd5b505af1935050505080156135fd575060015b50505b6001600160401b0381161561362d5761362d88613626836001600160401b0316896146c5565b60016146f2565b61384d565b5f6001600160401b0386161580159061365357506001600160a01b03851615155b156136e6575f61366c876001600160401b0316896146c5565b600354604051631c43245560e01b81526001600160a01b0389811660048301528c8116602483015260448201849052929350911690631c432455906064015f604051808303815f87803b1580156136c1575f5ffd5b505af19250505080156136d2575060015b156136e4576136e181836156be565b91505b505b5f846001600160401b031611801561370657506001600160a01b03831615155b15613799575f61371f856001600160401b0316896146c5565b600354604051631c43245560e01b81526001600160a01b0387811660048301528c8116602483015260448201849052929350911690631c432455906064015f604051808303815f87803b158015613774575f5ffd5b505af1925050508015613785575060015b156137975761379481836156be565b91505b505b80156138145760035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018390529089169063a9059cbb906044016020604051808303815f875af192505050801561380d575060408051601f3d908101601f1916820190925261380a9181019061585e565b60015b1561381457505b6001600160401b0382161561384b5761384b8961383a846001600160401b03168a6146c5565b6001600160a01b038b169190614797565b505b7f4bdcff348c4d11383c487afb95f732f243d93fbfc478aa736a4981cf6a6409118a6020015160405161388291815260200190565b60405180910390a150505050505050505050565b5f6138a28260016156be565b835110156138f25760405162461bcd60e51b815260206004820152601360248201527f746f55696e74385f6f75744f66426f756e6473000000000000000000000000006044820152606401610832565b50016001015190565b5f6139078260026156be565b835110156139575760405162461bcd60e51b815260206004820152601460248201527f746f55696e7431365f6f75744f66426f756e64730000000000000000000000006044820152606401610832565b50016002015190565b5f61396c8260206156be565b835110156139bc5760405162461bcd60e51b815260206004820152601560248201527f746f427974657333325f6f75744f66426f756e647300000000000000000000006044820152606401610832565b50016020015190565b80515f03613a5b578361ffff166001600160401b038111156139e9576139e9614aa3565b604051908082528060200260200182016040528015613a12578160200160208202803683370190505b5090505f5b8461ffff168161ffff161015613a595780828261ffff1681518110613a3e57613a3e6156d1565b61ffff90921660209283029190910190910152600101613a17565b505b5f5b8151811015613ce4575f828281518110613a7957613a796156d1565b602002602001015190508561ffff168161ffff1610613ac4576040517f782cacc000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f613ad460ac61ffff84166156a7565b90505f60405180610140016040528060026007811115613af657613af6614e65565b60ff168152602001613b088b85613960565b8152602001613b24846020613b1d91906156be565b8c906138fb565b61ffff168152602001613b42613b3b8560226156be565b8c90613960565b8152602001613b55613b3b8560426156be565b8152602001613b6f613b688560626156be565b8c90613896565b60ff168152602001613b85613b688560636156be565b60ff168152602001613b9b613b3b8560646156be565b8152602001613bae613b3b8560846156be565b8152602001613bc8613bc18560a46156be565b8c90613cec565b6001600160401b031690526020808201515f9081526007909152604080822081516060810190925280549394509192909190829060ff166005811115613c1057613c10614e65565b6005811115613c2157613c21614e65565b8152905461010081046001600160401b03166020830152600160481b900461ffff1660409091015290505f81516005811115613c5f57613c5f614e65565b14613c6d5750505050613cdc565b806040015161ffff168861ffff1614613c99576040516327e8d62960e11b815260040160405180910390fd5b60408082015161ffff165f908152600860205220548714613ccd5760405163d08bf9e160e01b815260040160405180910390fd5b613cd78282613281565b505050505b600101613a5d565b505050505050565b5f613cf88260086156be565b83511015613d485760405162461bcd60e51b815260206004820152601460248201527f746f55696e7436345f6f75744f66426f756e64730000000000000000000000006044820152606401610832565b50016008015190565b5f73ffffffffffffffffffffffffffffffffffffffff19821615613da1576040517ff652ddbc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5090565b6001600160a01b03831663d505accf833084356020860135613dcd6060880160408901615929565b6040516001600160e01b031960e088901b1681526001600160a01b0395861660048201529490931660248501526044840191909152606483015260ff166084820152606084013560a4820152608084013560c482015260e4015f604051808303815f87803b158015613e3d575f5ffd5b505af1158015613e4f573d5f5f3e3d5ffd5b50505050505050565b6040516370a0823160e01b81523060048201525f9081906001600160a01b038616906370a0823190602401602060405180830381865afa158015613e9e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613ec291906156e5565b9050613ed96001600160a01b038616843087613f54565b6040516370a0823160e01b815230600482015281906001600160a01b038716906370a0823190602401602060405180830381865afa158015613f1d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613f4191906156e5565b613f4b9190615879565b95945050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052613fed9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152614823565b50505050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f9182916001600160a01b0385169161406391615944565b5f60405180830381855afa9150503d805f811461409b576040519150601f19603f3d011682016040523d82523d5f602084013e6140a0565b606091505b50915050808060200190518101906140b89190615828565b9392505050565b5f60088260ff1611156140ef576140d760088361595a565b6140e290600a615a56565b6140ec9084615a64565b92505b5090919050565b60408051610240810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081018290526102008101829052610220810191909152604051806102400160405280875f015160ff168152602001876020015181526020018561ffff16815260200186815260200187604001518152602001876060015161ffff1681526020018760a0015181526020018760c001516001600160401b031681526020018760e001516001600160401b031681526020018761010001516001600160401b031681526020018761012001516001600160401b031681526020018761014001516001600160401b031681526020018760800151815260200187610160015160ff1681526020018460ff16815260200187610180015160ff168152602001876101a00151815260200183815250905095945050505050565b6060815f015182602001518360400151846060015185608001518660a001518760c001518860e001518961010001518a61012001518b61014001518c61016001516040516020016142e19c9b9a99989796959493929190615a77565b60408051601f19818403018152908290526101808401516101a08501516101c08601516101e0870151610200880151610220890151959750612bfa9661437f969060200195865260f894851b7fff00000000000000000000000000000000000000000000000000000000000000908116602088015293851b841660218701529190931b90911660228401526023830191909152604382015260630190565b60408051601f198184030181529190528290614909565b604080517fc1e8426d70a8367e3d86a5f2e0bdec2344bd6a74f82bfdf50cdfdc08a36500f1602082015290810184905260608101839052608081018290525f90819060a0016040516020818303038152906040529050613f4b60065482805190602001206040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b5f5f5f836001600160a01b03163b5f036145fe5760418690036144865761445d86880188615b9d565b909350915086866040818110614475576144756156d1565b919091013560f81c915061450f9050565b60408690036144dd575f61449c87890189615b9d565b9094507f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116935090506144d560ff82901c601b615bbd565b91505061450f565b6040517f4be6321b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080515f8082526020820180845288905260ff841692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa158015614560573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b0381166145ad576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846001600160a01b0316816001600160a01b0316146145f8576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50613e4f565b604051630b135d3f60e11b81525f906001600160a01b03861690631626ba7e906146309089908c908c90600401615bd6565b602060405180830381865afa15801561464b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061466f9190615c0b565b90506001600160e01b03198116630b135d3f60e11b146146bb576040517fb0669cbc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b5f60088260ff1611156140ef576146dd60088361595a565b6146e890600a615a56565b6140ec90846156a7565b5f836001600160a01b0316836040515f6040518083038185875af1925050503d805f811461473b576040519150601f19603f3d011682016040523d82523d5f602084013e614740565b606091505b505090508115613fed5780613fed5760405162461bcd60e51b815260206004820152600e60248201527f7061796d656e74206661696c65640000000000000000000000000000000000006044820152606401610832565b6040516001600160a01b038316602482015260448101829052610b4090849063a9059cbb60e01b90606401613fa1565b5f6147d38260206156be565b835110156139bc5760405162461bcd60e51b815260206004820152601560248201527f746f55696e743235365f6f75744f66426f756e647300000000000000000000006044820152606401610832565b5f614877826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166149869092919063ffffffff16565b905080515f1480614897575080806020019051810190614897919061585e565b610b405760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610832565b6060806040519050835180825260208201818101602087015b8183101561493a578051835260209283019201614922565b50855184518101855292509050808201602086015b8183101561496757805183526020928301920161494f565b508651929092011591909101601f01601f191660405250905092915050565b6060611c4584845f85855f5f866001600160a01b031685876040516149ab9190615944565b5f6040518083038185875af1925050503d805f81146149e5576040519150601f19603f3d011682016040523d82523d5f602084013e6149ea565b606091505b50915091506149fb87838387614a06565b979650505050505050565b60608315614a745782515f03614a6d576001600160a01b0385163b614a6d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610832565b5081611c45565b611c458383815115614a895781518083602001fd5b8060405162461bcd60e51b815260040161083291906153f7565b634e487b7160e01b5f52604160045260245ffd5b6040516101c081016001600160401b0381118282101715614ada57614ada614aa3565b60405290565b604051608081016001600160401b0381118282101715614ada57614ada614aa3565b60405161016081016001600160401b0381118282101715614ada57614ada614aa3565b604051601f8201601f191681016001600160401b0381118282101715614b4d57614b4d614aa3565b604052919050565b5f6001600160401b03821115614b6d57614b6d614aa3565b50601f01601f191660200190565b5f82601f830112614b8a575f5ffd5b8135614b9d614b9882614b55565b614b25565b818152846020838601011115614bb1575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f60208284031215614bdd575f5ffd5b81356001600160401b03811115614bf2575f5ffd5b611c4584828501614b7b565b5f6001600160401b03821115614c1657614c16614aa3565b5060051b60200190565b61ffff81168114610971575f5ffd5b8035614c3a81614c20565b919050565b5f82601f830112614c4e575f5ffd5b8135614c5c614b9882614bfe565b8082825260208201915060208360051b860101925085831115614c7d575f5ffd5b602085015b83811015614ca3578035614c9581614c20565b835260209283019201614c82565b5095945050505050565b5f5f5f60608486031215614cbf575f5ffd5b83356001600160401b03811115614cd4575f5ffd5b614ce086828701614b7b565b93505060208401356001600160401b03811115614cfb575f5ffd5b614d0786828701614b7b565b92505060408401356001600160401b03811115614d22575f5ffd5b614d2e86828701614c3f565b9150509250925092565b6001600160a01b0381168114610971575f5ffd5b5f60208284031215614d5c575f5ffd5b81356140b881614d38565b5f6101008201905060ff83511682526020830151602083015261ffff6040840151166040830152606083015160608301526080830151608083015260a083015160a08301526001600160401b0360c08401511660c083015260e0830151610e2d60e08401826001600160401b03169052565b5f82601f830112614de8575f5ffd5b8135614df6614b9882614bfe565b8082825260208201915060208360051b860101925085831115614e17575f5ffd5b602085015b83811015614ca3578035835260209283019201614e1c565b5f60208284031215614e44575f5ffd5b81356001600160401b03811115614e59575f5ffd5b611c4584828501614dd9565b634e487b7160e01b5f52602160045260245ffd5b60068110614e9557634e487b7160e01b5f52602160045260245ffd5b9052565b602080825282518282018190525f918401906040840190835b81811015614f00578351614ec7848251614e79565b6001600160401b03602082015116602085015261ffff604082015116604085015250606083019250602084019350600181019050614eb2565b509095945050505050565b60ff81168114610971575f5ffd5b8035614c3a81614f0b565b6001600160401b0381168114610971575f5ffd5b8035614c3a81614f24565b5f6101c08284031215614f54575f5ffd5b614f5c614ab7565b9050614f6782614f19565b81526020828101359082015260408083013590820152614f8960608301614c2f565b60608201526080828101359082015260a08083013590820152614fae60c08301614f38565b60c0820152614fbf60e08301614f38565b60e0820152614fd16101008301614f38565b610100820152614fe46101208301614f38565b610120820152614ff76101408301614f38565b61014082015261500a6101608301614f19565b61016082015261501d6101808301614f19565b6101808201526101a09182013591810191909152919050565b5f60a08284031215615046575f5ffd5b50919050565b5f5f5f5f5f5f5f5f610300898b031215615064575f5ffd5b883561506f81614d38565b9750602089013596506150858a60408b01614f43565b95506102008901356001600160401b038111156150a0575f5ffd5b6150ac8b828c01614b7b565b95505061022089013593506102408901356001600160401b038111156150d0575f5ffd5b8901601f81018b136150e0575f5ffd5b80356001600160401b038111156150f5575f5ffd5b8b6020828401011115615106575f5ffd5b6020919091019350915061511e8a6102608b01615036565b90509295985092959890939650565b5f6020828403121561513d575f5ffd5b81356140b881614f24565b5f60208284031215615158575f5ffd5b5035919050565b6060810161516d8286614e79565b6001600160401b038416602083015261ffff83166040830152949350505050565b5f6020828403121561519e575f5ffd5b81356140b881614c20565b5f5f5f5f61022085870312156151bd575f5ffd5b84356151c881614d38565b9350602085013592506151de8660408701614f43565b91506102008501356001600160401b038111156151f9575f5ffd5b61520587828801614b7b565b91505092959194509250565b815160ff168152610140810160208301516020830152604083015161523c604084018261ffff169052565b50606083015160608301526080830151608083015260a083015161526560a084018260ff169052565b5060c083015161527a60c084018260ff169052565b5060e083015160e0830152610100830151610100830152610120830151610e2d6101208401826001600160401b03169052565b8015158114610971575f5ffd5b5f5f604083850312156152cb575f5ffd5b82356001600160401b038111156152e0575f5ffd5b6152ec85828601614b7b565b92505060208301356152fd816152ad565b809150509250929050565b5f5f60408385031215615319575f5ffd5b82356001600160401b0381111561532e575f5ffd5b61533a85828601614c3f565b92505060208301356001600160401b03811115615355575f5ffd5b61536185828601614dd9565b9150509250929050565b5f6020828403121561537b575f5ffd5b81356140b8816152ad565b5f5f6101e08385031215615398575f5ffd5b6153a28484614f43565b91506101c08301356001600160401b038111156153bd575f5ffd5b61536185828601614b7b565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6140b860208301846153c9565b8051614c3a81614f0b565b805163ffffffff81168114614c3a575f5ffd5b8051614c3a81614c20565b8051614c3a81614f24565b5f82601f83011261544c575f5ffd5b8151602083015f61545f614b9884614b55565b9050828152858383011115615472575f5ffd5b8282602083015e5f92810160200192909252509392505050565b5f82601f83011261549b575f5ffd5b81516154a9614b9882614bfe565b8082825260208201915060208360071b8601019250858311156154ca575f5ffd5b602085015b83811015614ca357608081880312156154e6575f5ffd5b6154ee614ae0565b8151815260208083015190820152604082015161550a81614f0b565b6040820152606082015161551d81614f0b565b606082015283526020909201916080016154cf565b8051614c3a816152ad565b5f5f5f6060848603121561554f575f5ffd5b83516001600160401b03811115615564575f5ffd5b84016101608187031215615576575f5ffd5b61557e614b02565b61558782615409565b815261559560208301615414565b60208201526155a660408301615414565b60408201526155b760608301615427565b6060820152608082810151908201526155d260a08301615432565b60a08201526155e360c08301615409565b60c082015260e08201516001600160401b03811115615600575f5ffd5b61560c8882850161543d565b60e08301525061561f6101008301615414565b6101008201526101208201516001600160401b0381111561563e575f5ffd5b61564a8882850161548c565b610120830152506101409182015191810191909152925061566d60208501615532565b915060408401516001600160401b03811115615687575f5ffd5b614d2e8682870161543d565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417612bfa57612bfa615693565b80820180821115612bfa57612bfa615693565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156156f5575f5ffd5b5051919050565b6001600160401b038181168382160190811115612bfa57612bfa615693565b6001600160a01b038416815260208101839052815160ff16604082015261020081016020830151606083015260408301516080830152606083015161576660a084018261ffff169052565b50608083015160c083015260a083015160e083015260c08301516157966101008401826001600160401b03169052565b5060e08301516001600160401b038116610120840152506101008301516001600160401b038116610140840152506101208301516001600160401b038116610160840152506101408301516001600160401b0381166101808401525061016083015160ff81166101a08401525061018083015160ff81166101c0840152506101a08301516101e0830152949350505050565b5f60208284031215615838575f5ffd5b81516140b881614f0b565b5f60208284031215615853575f5ffd5b81516140b881614c20565b5f6020828403121561586e575f5ffd5b81516140b8816152ad565b81810381811115612bfa57612bfa615693565b6001600160401b038181168382160290811690818114610e2d57610e2d615693565b634e487b7160e01b5f52601260045260245ffd5b5f6001600160401b038316806158da576158da6158ae565b806001600160401b0384160491505092915050565b5f602082840312156158ff575f5ffd5b81516140b881614d38565b6001600160401b038281168282160390811115612bfa57612bfa615693565b5f60208284031215615939575f5ffd5b81356140b881614f0b565b5f82518060208501845e5f920191825250919050565b60ff8281168282160390811115612bfa57612bfa615693565b6001815b60018411156159ae5780850481111561599257615992615693565b60018416156159a057908102905b60019390931c928002615977565b935093915050565b5f826159c457506001612bfa565b816159d057505f612bfa565b81600181146159e657600281146159f057615a0c565b6001915050612bfa565b60ff841115615a0157615a01615693565b50506001821b612bfa565b5060208310610133831016604e8410600b8410161715615a2f575081810a612bfa565b615a3b5f198484615973565b805f1904821115615a4e57615a4e615693565b029392505050565b5f6140b860ff8416836159b6565b5f82615a7257615a726158ae565b500490565b7fff000000000000000000000000000000000000000000000000000000000000008d60f81b1681528b60018201527fffff0000000000000000000000000000000000000000000000000000000000008b60f01b1660218201528960238201528860438201527fffff0000000000000000000000000000000000000000000000000000000000008860f01b166063820152866065820152615b26608582018760c01b6001600160c01b0319169052565b615b3f608d82018660c01b6001600160c01b0319169052565b615b58609582018560c01b6001600160c01b0319169052565b615b71609d82018460c01b6001600160c01b0319169052565b615b8a60a582018360c01b6001600160c01b0319169052565b60ad019c9b505050505050505050505050565b5f5f60408385031215615bae575f5ffd5b50508035926020909101359150565b60ff8181168382160190811115612bfa57612bfa615693565b83815260406020820152816040820152818360608301375f818301606090810191909152601f909201601f1916010192915050565b5f60208284031215615c1b575f5ffd5b81516001600160e01b0319811681146140b8575f5ffdfea2646970667358221220deb0c0505c94b940dfcedfa843a9d0de31d0ebcea418c16f2033b4bb69e5537864736f6c634300081c0033000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d00000000000000000000000000000000000000000000000000000000000000017eabb0ebb9b559ede7a22b52d905dc7ade19cd8e4acf1650683865b2e015caea000000000000000000000000da95d2e1b54893d424da8959bcabeabbfc911884000000000000000000000000c3f33ee53933c32e1fcd52fa3933ab508663ee6a
Deployed Bytecode
0x6080604052600436106101d3575f3560e01c80639c3f1e90116100fd578063bedb86fb11610092578063d383e3e711610062578063d383e3e7146105fd578063dae2fc121461065f578063f1d3ac4f1461067e578063f6203990146106ee575f5ffd5b8063bedb86fb14610579578063ca5662b014610598578063cc8388d0146105ab578063d0fb0203146105de575f5ffd5b8063ac432e63116100cd578063ac432e63146104e8578063b365b19114610507578063b854c12b14610526578063bdacaae71461055a575f5ffd5b80639c3f1e90146104195780639e70a74014610472578063a3a308341461049d578063a5e1ea7d146104bc575f5ffd5b806346963505116101735780636147435b116101435780636147435b1461037657806384acd1bb146103a35780638b2ab1b7146103d6578063919a1704146103eb575f5ffd5b806346963505146102e9578063472d35b9146103085780634818e84d146103275780635c975abb14610346575f5ffd5b806339f3fbd9116101ae57806339f3fbd91461023d5780633d47486614610272578063452a93201461029e578063459656ee146102d5575f5ffd5b8063119abf67146101de5780632d67b5ea146101ff5780632fcb4f041461021e575f5ffd5b366101da57005b5f5ffd5b3480156101e9575f5ffd5b506101fd6101f8366004614bcd565b610774565b005b34801561020a575f5ffd5b506101fd610219366004614cad565b610974565b348015610229575f5ffd5b506101fd610238366004614d4c565b610b45565b348015610248575f5ffd5b5061025c610257366004614bcd565b610b9e565b6040516102699190614d67565b60405180910390f35b34801561027d575f5ffd5b5061029161028c366004614e34565b610d03565b6040516102699190614e99565b3480156102a9575f5ffd5b506004546102bd906001600160a01b031681565b6040516001600160a01b039091168152602001610269565b3480156102e0575f5ffd5b506101fd610e34565b3480156102f4575f5ffd5b506101fd610303366004614bcd565b610e8f565b348015610313575f5ffd5b506101fd610322366004614d4c565b611081565b348015610332575f5ffd5b506005546102bd906001600160a01b031681565b348015610351575f5ffd5b5060055461036690600160a01b900460ff1681565b6040519015158152602001610269565b348015610381575f5ffd5b5061039561039036600461504c565b6110da565b604051908152602001610269565b3480156103ae575f5ffd5b506102bd7f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d81565b3480156103e1575f5ffd5b5061039560025481565b3480156103f6575f5ffd5b5061036661040536600461512d565b60096020525f908152604090205460ff1681565b348015610424575f5ffd5b50610463610433366004615148565b60076020525f908152604090205460ff81169061010081046001600160401b031690600160481b900461ffff1683565b6040516102699392919061515f565b34801561047d575f5ffd5b5061039561048c36600461518e565b60086020525f908152604090205481565b3480156104a8575f5ffd5b506103956104b73660046151a9565b61169f565b3480156104c7575f5ffd5b506104db6104d6366004614bcd565b611c4d565b6040516102699190615211565b3480156104f3575f5ffd5b506101fd6105023660046152ba565b611dae565b348015610512575f5ffd5b506101fd610521366004615308565b612573565b348015610531575f5ffd5b5060015461054790600160a01b900461ffff1681565b60405161ffff9091168152602001610269565b348015610565575f5ffd5b506001546102bd906001600160a01b031681565b348015610584575f5ffd5b506101fd61059336600461536b565b6126bb565b6103956105a6366004615386565b61271e565b3480156105b6575f5ffd5b506102bd7f000000000000000000000000c3f33ee53933c32e1fcd52fa3933ab508663ee6a81565b3480156105e9575f5ffd5b506003546102bd906001600160a01b031681565b348015610608575f5ffd5b5061061c610617366004614bcd565b612c00565b6040516102699190815160ff1681526020808301516001600160a01b03169082015260408083015161ffff16908201526060918201519181019190915260800190565b34801561066a575f5ffd5b506101fd610679366004614bcd565b612cc7565b348015610689575f5ffd5b5061069d610698366004614bcd565b61304a565b60405161026991905f60a08201905060ff835116825260208301516020830152604083015160408301526001600160401b03606084015116606083015261ffff608084015116608083015292915050565b3480156106f9575f5ffd5b5061070d610708366004614bcd565b613114565b60405161026991905f60c08201905060ff835116825261ffff60208401511660208301526040830151604083015260ff60608401511660608301526001600160a01b0360808401511660808301526001600160401b0360a08401511660a083015292915050565b61077c61322a565b5f5f5f7f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b031663c0fd8bde856040518263ffffffff1660e01b81526004016107cb91906153f7565b5f60405180830381865afa1580156107e5573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261080c919081019061553d565b92509250925081819061083b5760405162461bcd60e51b815260040161083291906153f7565b60405180910390fd5b505f61084a8460e00151611c4d565b6020808201515f9081526007909152604080822081516060810190925280549394509192909190829060ff16600581111561088757610887614e65565b600581111561089857610898614e65565b815290546001600160401b03610100820416602083015261ffff600160481b909104811660409283015290820151919250165f036108f157816020015160405163956fc85760e01b815260040161083291815260200190565b806040015161ffff16856060015161ffff1614610921576040516327e8d62960e11b815260040160405180910390fd5b60408082015161ffff165f908152600860205220546080860151146109595760405163d08bf9e160e01b815260040160405180910390fd5b6109638282613281565b505050505061097160015f55565b50565b61097c61322a565b5f5f5f7f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b031663c0fd8bde876040518263ffffffff1660e01b81526004016109cb91906153f7565b5f60405180830381865afa1580156109e5573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610a0c919081019061553d565b925092509250818190610a325760405162461bcd60e51b815260040161083291906153f7565b5060e08301515f90610a449082613896565b905060ff8116600514610a6a57604051634a7f394f60e01b815260040160405180910390fd5b60e08401515f90610a7c9060016138fb565b8751909150610a9060ac61ffff84166156a7565b14610ac7576040517f5e7407c200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8651602088012060e08601515f90610ae0906003613960565b9050808214610b1b576040517f7c6953f900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b30898489606001518a608001518c6139c5565b50505050505050610b4060015f55565b505050565b6004546001600160a01b03163314610b6f576040516282b42960e81b815260040160405180910390fd5b6005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905290610be88382613896565b60ff168252610bf86001826156be565b825190915060ff16600314610c2057604051634a7f394f60e01b815260040160405180910390fd5b610c2a8382613960565b602080840191909152610c3d90826156be565b9050610c4983826138fb565b61ffff166040830152610c5d6002826156be565b9050610c698382613960565b6060830152610c796020826156be565b9050610c858382613960565b6080830152610c956020826156be565b9050610ca18382613960565b60a0830152610cb16020826156be565b9050610cbd8382613cec565b6001600160401b031660c0830152610cd66008826156be565b9050610ce28382613cec565b6001600160401b031660e0830152610cfb6008826156be565b905050919050565b60605f82516001600160401b03811115610d1f57610d1f614aa3565b604051908082528060200260200182016040528015610d6857816020015b604080516060810182525f80825260208083018290529282015282525f19909201910181610d3d5790505b5090505f5b8351811015610e2d5760075f858381518110610d8b57610d8b6156d1565b602002602001015181526020019081526020015f206040518060600160405290815f82015f9054906101000a900460ff166005811115610dcd57610dcd614e65565b6005811115610dde57610dde614e65565b8152905461010081046001600160401b03166020830152600160481b900461ffff166040909101528251839083908110610e1a57610e1a6156d1565b6020908102919091010152600101610d6d565b5092915050565b6005546001600160a01b03163314610e5e576040516282b42960e81b815260040160405180910390fd5b6005546004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909216919091179055565b6004546001600160a01b03163314610eb9576040516282b42960e81b815260040160405180910390fd5b60015460405163607ec5ef60e11b81525f91829182916001600160a01b03169063c0fd8bde90610eed9087906004016153f7565b5f60405180830381865afa158015610f07573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610f2e919081019061553d565b925092509250818190610f545760405162461bcd60e51b815260040161083291906153f7565b5060a08301516001600160401b03165f9081526009602052604090205460ff1615610f9257604051633891b8bb60e11b815260040160405180910390fd5b60a08301516001600160401b03165f908152600960205260409020805460ff1916600190811790915554606084015161ffff908116600160a01b9092041614610fee576040516327e8d62960e11b815260040160405180910390fd5b6002548360800151146110145760405163d08bf9e160e01b815260040160405180910390fd5b5f6110228460e00151612c00565b602081015160018054604084015161ffff16600160a01b027fffffffffffffffffffff000000000000000000000000000000000000000000009091166001600160a01b0390931692909217919091179055606001516002555050505050565b6004546001600160a01b031633146110ab576040516282b42960e81b815260040160405180910390fd5b6003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b5f6110e361322a565b600554600160a01b900460ff161561110e576040516313d0ff5960e31b815260040160405180910390fd5b5f61111c8860200151613d51565b9050611128868a6156be565b6040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301523060248301528c169063dd62ed3e90604401602060405180830381865afa15801561118b573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111af91906156e5565b10156111c0576111c08a8285613da5565b6111cb8a8a83613e58565b98508515611257576003546111ef906001600160a01b038c81169184911689613f54565b600354604051631c43245560e01b81523360048201526001600160a01b038c811660248301526044820189905290911690631c432455906064015f604051808303815f87803b158015611240575f5ffd5b505af1158015611252573d5f5f3e3d5ffd5b505050505b5f61126a8a6112658d613ff3565b6140bf565b9050806001600160401b03165f03611295576040516356fdd81f60e11b815260040160405180910390fd5b806001600160401b03168961012001518a61010001516112b591906156fc565b6001600160401b0316106112dc5760405163192069c360e31b815260040160405180910390fd5b60a08901511580156112fa575060e08901516001600160401b031615155b1561131857604051636e51edcd60e11b815260040160405180910390fd5b600354604051633972bf5560e11b81525f916001600160a01b0316906372e57eaa9061134c908f908f908f9060040161571b565b6020604051808303815f875af1158015611368573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061138c9190615828565b905060c860ff168a610160015160ff1611806113ab575060c860ff8216115b156113c957604051633f6e8d0d60e21b815260040160405180910390fd5b61148361147e8b8e6001600160a01b03165f1b7f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa158015611438573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061145c9190615843565b858f5f015160ff16600214611471575f6140f6565b8e805190602001206140f6565b614285565b8051906020012093506114a461149a858d8b614396565b8890889086614434565b60608a015161ffff165f90815260086020526040902054158061155157507f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa15801561151e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115429190615843565b61ffff168a6060015161ffff16145b1561156f576040516355ef7a1d60e11b815260040160405180910390fd5b5f84815260076020526040902054600160481b900461ffff16156115a65760405163015b9d8b60e41b815260040160405180910390fd5b6040805160608101909152805f81526001600160401b03841660208083019190915260608d015161ffff166040928301525f87815260079091522081518154829060ff191660018360058111156115ff576115ff614e65565b02179055506020820151815460409384015161ffff16600160481b026affff000000000000000000196001600160401b0390931661010002929092166affffffffffffffffffff001990911617179055517f918554b6bd6e2895ce6553de5de0e1a69db5289aa0e4fe193a0dcd1f143474779061167f9086815260200190565b60405180910390a150505061169360015f55565b98975050505050505050565b5f6116a861322a565b600554600160a01b900460ff16156116d3576040516313d0ff5960e31b815260040160405180910390fd5b6116de858533613e58565b93505f6116ee8561126588613ff3565b9050806001600160401b03165f03611719576040516356fdd81f60e11b815260040160405180910390fd5b806001600160401b031684610120015185610100015161173991906156fc565b6001600160401b0316106117605760405163192069c360e31b815260040160405180910390fd5b60a084015115801561177e575060e08401516001600160401b031615155b1561179c57604051636e51edcd60e11b815260040160405180910390fd5b600354604051633972bf5560e11b81525f916001600160a01b0316906372e57eaa906117d0908a908a908a9060040161571b565b6020604051808303815f875af11580156117ec573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118109190615828565b905060c860ff1685610160015160ff16118061182f575060c860ff8216115b1561184d57604051633f6e8d0d60e21b815260040160405180910390fd5b84515f9060ff166002036118645750835160208501205b5f6118fc878a6001600160a01b03165f1b7f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118d1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118f59190615843565b86866140f6565b905061190781614285565b8051602091820120606089015161ffff165f908152600890925260409091205490955015806119c057507f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa15801561198d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119b19190615843565b61ffff16876060015161ffff16145b156119de576040516355ef7a1d60e11b815260040160405180910390fd5b5f858152600760205260408082208151606081019092528054829060ff166005811115611a0d57611a0d614e65565b6005811115611a1e57611a1e614e65565b815290546001600160401b03610100820416602083015261ffff600160481b9091048116604092830152908201519192501615611b565780602001516001600160401b0316856001600160401b0316118015611a8b57505f81516005811115611a8957611a89614e65565b145b15611b3d57896001600160a01b031663a9059cbb611aac8a60200151613d51565b611acb84602001516001600160401b0316611ac68f613ff3565b6146c5565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af1158015611b13573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b37919061585e565b50611b56565b60405163015b9d8b60e41b815260040160405180910390fd5b6040805160608101909152805f81526001600160401b03871660208083019190915260608b015161ffff166040928301525f89815260079091522081518154829060ff19166001836005811115611baf57611baf614e65565b02179055506020820151815460409384015161ffff16600160481b026affff000000000000000000196001600160401b0390931661010002929092166affffffffffffffffffff001990911617179055517f918554b6bd6e2895ce6553de5de0e1a69db5289aa0e4fe193a0dcd1f1434747790611c2f9088815260200190565b60405180910390a15050505050611c4560015f55565b949350505050565b60408051610140810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905290611ca78382613896565b60ff168252611cb76001826156be565b825190915060ff16600214611cdf57604051634a7f394f60e01b815260040160405180910390fd5b611ce98382613960565b602080840191909152611cfc90826156be565b9050611d0883826138fb565b61ffff166040830152611d1c6002826156be565b9050611d288382613960565b6060830152611d386020826156be565b9050611d448382613960565b6080830152611d546020826156be565b9050611d608382613896565b60ff1660a0830152611d736001826156be565b9050611d7f8382613896565b60ff1660c0830152611d926001826156be565b9050611d9e8382613960565b60e0830152610cfb6020826156be565b611db661322a565b60408051610160810182525f8082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820181905261010082018390526101208201526101408101919091525f6060838015611e2757506001546001600160a01b031615155b15611ea95760015460405163607ec5ef60e11b81526001600160a01b039091169063c0fd8bde90611e5c9088906004016153f7565b5f60405180830381865afa158015611e76573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611e9d919081019061553d565b91945092509050611f3e565b60405163607ec5ef60e11b81526001600160a01b037f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d169063c0fd8bde90611ef59088906004016153f7565b5f60405180830381865afa158015611f0f573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611f36919081019061553d565b919450925090505b8082611f5d5760405162461bcd60e51b815260040161083291906153f7565b505f611f6c8460e00151610b9e565b6020808201515f9081526007909152604080822081516060810190925280549394509192909190829060ff166005811115611fa957611fa9614e65565b6005811115611fba57611fba614e65565b8152905461010081046001600160401b0316602080840191909152600160481b90910461ffff1660409283015281517f9a8a059200000000000000000000000000000000000000000000000000000000815291519293507f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b031692639a8a05929260048082019392918290030181865afa158015612061573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120859190615843565b61ffff16826040015161ffff16146120b057604051633bec3b7d60e11b815260040160405180910390fd5b806040015161ffff165f036120e057816020015160405163956fc85760e01b815260040161083291815260200190565b5f815160058111156120f4576120f4614e65565b1461211257604051632916ae3360e01b815260040160405180910390fd5b6020828101515f908152600790915260409020805460ff19166005179055851561219657600154606086015161ffff908116600160a01b909204161461216b576040516327e8d62960e11b815260040160405180910390fd5b6002548560800151146121915760405163d08bf9e160e01b815260040160405180910390fd5b6121fe565b806040015161ffff16856060015161ffff16146121c6576040516327e8d62960e11b815260040160405180910390fd5b60408082015161ffff165f908152600860205220546080860151146121fe5760405163d08bf9e160e01b815260040160405180910390fd5b5f61220c8360800151613d51565b60a08401516060850151919250905f9061222590613d51565b90505f6001600160a01b03821661223e5750601261224a565b61224782613ff3565b90505b5f6122628760c001516001600160401b0316836146c5565b90505f61227c8860e001516001600160401b0316846146c5565b90505f61229688602001516001600160401b0316856146c5565b90505f826122a48584615879565b6122ae9190615879565b90506001600160a01b0386166123a757831561232b57600354604051631c43245560e01b81526001600160a01b0389811660048301525f60248301526044820187905290911690631c4324559086906064015f604051808303818588803b158015612317575f5ffd5b505af193505050508015612329575060015b505b821561239657600354604051631c43245560e01b81523360048201525f6024820152604481018590526001600160a01b0390911690631c4324559085906064015f604051808303818588803b158015612382575f5ffd5b505af193505050508015612394575060015b505b6123a2888260016146f2565b61251b565b831561241357600354604051631c43245560e01b81526001600160a01b03898116600483015288811660248301526044820187905290911690631c432455906064015f604051808303815f87803b158015612400575f5ffd5b505af1925050508015612411575060015b505b821561247d57600354604051631c43245560e01b81523360048201526001600160a01b0388811660248301526044820186905290911690631c432455906064015f604051808303815f87803b15801561246a575f5ffd5b505af192505050801561247b575060015b505b5f61248884866156be565b905080156125055760035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018390529088169063a9059cbb906044016020604051808303815f875af19250505080156124fe575060408051601f3d908101601f191682019092526124fb9181019061585e565b60015b1561250557505b6125196001600160a01b0388168a84614797565b505b6020808b0151604080519182529181018390527fbff5487f6422ba4acbcde6bd5e0ccb83124c240b9deb6a72e7b5eb8c7b71d6fc910160405180910390a15050505050505050505050505061256f60015f55565b5050565b6004546001600160a01b0316331461259d576040516282b42960e81b815260040160405180910390fd5b80518251146125ee5760405162461bcd60e51b815260206004820152601460248201527f696e76616c6964206172726179206c656e6774680000000000000000000000006044820152606401610832565b5f5b8251811015610b40575f5f1b60085f858481518110612611576126116156d1565b602002602001015161ffff1661ffff1681526020019081526020015f205414612666576040517f9a23a9de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818181518110612678576126786156d1565b602002602001015160085f858481518110612695576126956156d1565b60209081029190910181015161ffff1682528101919091526040015f20556001016125f0565b6004546001600160a01b031633146126e5576040516282b42960e81b815260040160405180910390fd5b60058054911515600160a01b027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b5f61272761322a565b600554600160a01b900460ff1615612752576040516313d0ff5960e31b815260040160405180910390fd5b5f61275e3460126140bf565b9050806001600160401b03165f03612789576040516356fdd81f60e11b815260040160405180910390fd5b806001600160401b03168461012001518561010001516127a991906156fc565b6001600160401b0316106127d05760405163192069c360e31b815260040160405180910390fd5b60a08401511580156127ee575060e08401516001600160401b031615155b1561280c57604051636e51edcd60e11b815260040160405180910390fd5b600354604051633972bf5560e11b81525f916001600160a01b0316906372e57eaa9061284090849034908a9060040161571b565b6020604051808303815f875af115801561285c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128809190615828565b905060c860ff1685610160015160ff16118061289f575060c860ff8216115b156128bd57604051633f6e8d0d60e21b815260040160405180910390fd5b84515f9060ff166002036128d45750835160208501205b5f612938875f5f1b7f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118d1573d5f5f3e3d5ffd5b905061294381614285565b8051602091820120606089015161ffff165f908152600890925260409091205490955015806129fc57507f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129c9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129ed9190615843565b61ffff16876060015161ffff16145b15612a1a576040516355ef7a1d60e11b815260040160405180910390fd5b5f858152600760205260408082208151606081019092528054829060ff166005811115612a4957612a49614e65565b6005811115612a5a57612a5a614e65565b815290546001600160401b0361010082041660208084019190915261ffff600160481b9283900481166040948501525f8b81526007909252929020549293509091041615612b0b5780602001516001600160401b0316856001600160401b0316118015612ad857505f81516005811115612ad657612ad6614e65565b145b15611b3d57612b0b612aed8960200151613d51565b612b0583602001516001600160401b031660126146c5565b5f6146f2565b6040805160608101909152805f81526001600160401b03871660208083019190915260608b015161ffff166040928301525f89815260079091522081518154829060ff19166001836005811115612b6457612b64614e65565b02179055506020820151815460409384015161ffff16600160481b026affff000000000000000000196001600160401b0390931661010002929092166affffffffffffffffffff001990911617179055517f918554b6bd6e2895ce6553de5de0e1a69db5289aa0e4fe193a0dcd1f1434747790612be49088815260200190565b60405180910390a15050505050612bfa60015f55565b92915050565b604080516080810182525f808252602082018190529181018290526060810182905290612c2d8382613896565b60ff168252612c3d6001826156be565b825190915060ff16600614612c6557604051634a7f394f60e01b815260040160405180910390fd5b612c6f83826147c7565b6001600160a01b0316602080840191909152612c8b90826156be565b9050612c9783826138fb565b61ffff166040830152612cab6002826156be565b9050612cb78382613960565b6060830152610cfb6020826156be565b6004546001600160a01b03163314612cf1576040516282b42960e81b815260040160405180910390fd5b5f5f5f7f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b031663c0fd8bde856040518263ffffffff1660e01b8152600401612d4091906153f7565b5f60405180830381865afa158015612d5a573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612d81919081019061553d565b925092509250818190612da75760405162461bcd60e51b815260040161083291906153f7565b5060a08301516001600160401b03165f9081526009602052604090205460ff1615612de557604051633891b8bb60e11b815260040160405180910390fd5b60a08301516001600160401b03165f908152600960205260409020805460ff19166001908117909155606084015161ffff1614612e35576040516327e8d62960e11b815260040160405180910390fd5b60015f5260086020527fad67d757c34507f157cacfa2e3153e9f260a2244f30428821be7be64587ac55f54608084015114612e835760405163d08bf9e160e01b815260040160405180910390fd5b5f612e918460e00151613114565b90507f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa158015612eef573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f139190615843565b61ffff16816020015161ffff1614612f3e57604051633bec3b7d60e11b815260040160405180910390fd5b604081015115612f9157806060015160ff166005811115612f6157612f61614e65565b6040808301515f908152600760205220805460ff19166001836005811115612f8b57612f8b614e65565b02179055505b60a08101516001600160401b0316156130435760808101516001600160a01b0316612ff457612fef7f000000000000000000000000c3f33ee53933c32e1fcd52fa3933ab508663ee6a8260a001516001600160401b031660016146f2565b613043565b6130437f000000000000000000000000c3f33ee53933c32e1fcd52fa3933ab508663ee6a8260a001516001600160401b031683608001516001600160a01b03166147979092919063ffffffff16565b5050505050565b6040805160a0810182525f8082526020820181905291810182905260608101829052608081018290529061307e8382613896565b60ff16825261308e6001826156be565b825190915060ff166001146130b657604051634a7f394f60e01b815260040160405180910390fd5b6130c08382613960565b6020808401919091526130d390826156be565b90506130df8382613960565b60408301526130ef6020826156be565b90506130fb8382613cec565b6001600160401b03166060830152610cfb6008826156be565b6040805160c0810182525f80825260208201819052918101829052606081018290526080810182905260a081018290529061314f8382613896565b60ff16825261315f6001826156be565b825190915060ff1660071461318757604051634a7f394f60e01b815260040160405180910390fd5b61319183826138fb565b61ffff1660208301526131a56002826156be565b90506131b18382613960565b60408301526131c16020826156be565b90506131cd8382613896565b60ff1660608301526131e06001826156be565b90506131ec83826147c7565b6001600160a01b031660808301526132056020826156be565b90506132118382613cec565b6001600160401b031660a0830152610cfb6008826156be565b60025f540361327b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610832565b60025f55565b7f000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d6001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132dd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906133019190615843565b61ffff16826040015161ffff161461332c57604051633bec3b7d60e11b815260040160405180910390fd5b5f8151600581111561334057613340614e65565b1461335e57604051632916ae3360e01b815260040160405180910390fd5b6020828101515f908152600790915260408120805460ff1916600317905560e083015161338a90613d51565b90505f61339a8460600151613d51565b90505f6001600160a01b0382166133b3575060126133bf565b6133bc82613ff3565b90505b5f6127108660a0015160ff1686602001516133da919061588c565b6133e491906158c2565b90505f86608001515f1c90505f6127108860c0015160ff16886020015161340b919061588c565b61341591906158c2565b90505f60035f9054906101000a90046001600160a01b03166001600160a01b031663c415b95c6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015613486575060408051601f3d908101601f19168201909252613483918101906158ef565b60015b1561348e5790505b5f82858a602001516134a0919061590a565b6134aa919061590a565b90506001600160a01b038716613632575f856001600160401b03161180156134da57506001600160a01b03841615155b1561355d575f6134f3866001600160401b0316886146c5565b600354604051631c43245560e01b81526001600160a01b0388811660048301525f602483015260448201849052929350911690631c4324559083906064015f604051808303818588803b158015613548575f5ffd5b505af19350505050801561355a575060015b50505b5f836001600160401b031611801561357d57506001600160a01b03821615155b15613600575f613596846001600160401b0316886146c5565b600354604051631c43245560e01b81526001600160a01b0386811660048301525f602483015260448201849052929350911690631c4324559083906064015f604051808303818588803b1580156135eb575f5ffd5b505af1935050505080156135fd575060015b50505b6001600160401b0381161561362d5761362d88613626836001600160401b0316896146c5565b60016146f2565b61384d565b5f6001600160401b0386161580159061365357506001600160a01b03851615155b156136e6575f61366c876001600160401b0316896146c5565b600354604051631c43245560e01b81526001600160a01b0389811660048301528c8116602483015260448201849052929350911690631c432455906064015f604051808303815f87803b1580156136c1575f5ffd5b505af19250505080156136d2575060015b156136e4576136e181836156be565b91505b505b5f846001600160401b031611801561370657506001600160a01b03831615155b15613799575f61371f856001600160401b0316896146c5565b600354604051631c43245560e01b81526001600160a01b0387811660048301528c8116602483015260448201849052929350911690631c432455906064015f604051808303815f87803b158015613774575f5ffd5b505af1925050508015613785575060015b156137975761379481836156be565b91505b505b80156138145760035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018390529089169063a9059cbb906044016020604051808303815f875af192505050801561380d575060408051601f3d908101601f1916820190925261380a9181019061585e565b60015b1561381457505b6001600160401b0382161561384b5761384b8961383a846001600160401b03168a6146c5565b6001600160a01b038b169190614797565b505b7f4bdcff348c4d11383c487afb95f732f243d93fbfc478aa736a4981cf6a6409118a6020015160405161388291815260200190565b60405180910390a150505050505050505050565b5f6138a28260016156be565b835110156138f25760405162461bcd60e51b815260206004820152601360248201527f746f55696e74385f6f75744f66426f756e6473000000000000000000000000006044820152606401610832565b50016001015190565b5f6139078260026156be565b835110156139575760405162461bcd60e51b815260206004820152601460248201527f746f55696e7431365f6f75744f66426f756e64730000000000000000000000006044820152606401610832565b50016002015190565b5f61396c8260206156be565b835110156139bc5760405162461bcd60e51b815260206004820152601560248201527f746f427974657333325f6f75744f66426f756e647300000000000000000000006044820152606401610832565b50016020015190565b80515f03613a5b578361ffff166001600160401b038111156139e9576139e9614aa3565b604051908082528060200260200182016040528015613a12578160200160208202803683370190505b5090505f5b8461ffff168161ffff161015613a595780828261ffff1681518110613a3e57613a3e6156d1565b61ffff90921660209283029190910190910152600101613a17565b505b5f5b8151811015613ce4575f828281518110613a7957613a796156d1565b602002602001015190508561ffff168161ffff1610613ac4576040517f782cacc000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f613ad460ac61ffff84166156a7565b90505f60405180610140016040528060026007811115613af657613af6614e65565b60ff168152602001613b088b85613960565b8152602001613b24846020613b1d91906156be565b8c906138fb565b61ffff168152602001613b42613b3b8560226156be565b8c90613960565b8152602001613b55613b3b8560426156be565b8152602001613b6f613b688560626156be565b8c90613896565b60ff168152602001613b85613b688560636156be565b60ff168152602001613b9b613b3b8560646156be565b8152602001613bae613b3b8560846156be565b8152602001613bc8613bc18560a46156be565b8c90613cec565b6001600160401b031690526020808201515f9081526007909152604080822081516060810190925280549394509192909190829060ff166005811115613c1057613c10614e65565b6005811115613c2157613c21614e65565b8152905461010081046001600160401b03166020830152600160481b900461ffff1660409091015290505f81516005811115613c5f57613c5f614e65565b14613c6d5750505050613cdc565b806040015161ffff168861ffff1614613c99576040516327e8d62960e11b815260040160405180910390fd5b60408082015161ffff165f908152600860205220548714613ccd5760405163d08bf9e160e01b815260040160405180910390fd5b613cd78282613281565b505050505b600101613a5d565b505050505050565b5f613cf88260086156be565b83511015613d485760405162461bcd60e51b815260206004820152601460248201527f746f55696e7436345f6f75744f66426f756e64730000000000000000000000006044820152606401610832565b50016008015190565b5f73ffffffffffffffffffffffffffffffffffffffff19821615613da1576040517ff652ddbc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5090565b6001600160a01b03831663d505accf833084356020860135613dcd6060880160408901615929565b6040516001600160e01b031960e088901b1681526001600160a01b0395861660048201529490931660248501526044840191909152606483015260ff166084820152606084013560a4820152608084013560c482015260e4015f604051808303815f87803b158015613e3d575f5ffd5b505af1158015613e4f573d5f5f3e3d5ffd5b50505050505050565b6040516370a0823160e01b81523060048201525f9081906001600160a01b038616906370a0823190602401602060405180830381865afa158015613e9e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613ec291906156e5565b9050613ed96001600160a01b038616843087613f54565b6040516370a0823160e01b815230600482015281906001600160a01b038716906370a0823190602401602060405180830381865afa158015613f1d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613f4191906156e5565b613f4b9190615879565b95945050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052613fed9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152614823565b50505050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f9182916001600160a01b0385169161406391615944565b5f60405180830381855afa9150503d805f811461409b576040519150601f19603f3d011682016040523d82523d5f602084013e6140a0565b606091505b50915050808060200190518101906140b89190615828565b9392505050565b5f60088260ff1611156140ef576140d760088361595a565b6140e290600a615a56565b6140ec9084615a64565b92505b5090919050565b60408051610240810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081018290526102008101829052610220810191909152604051806102400160405280875f015160ff168152602001876020015181526020018561ffff16815260200186815260200187604001518152602001876060015161ffff1681526020018760a0015181526020018760c001516001600160401b031681526020018760e001516001600160401b031681526020018761010001516001600160401b031681526020018761012001516001600160401b031681526020018761014001516001600160401b031681526020018760800151815260200187610160015160ff1681526020018460ff16815260200187610180015160ff168152602001876101a00151815260200183815250905095945050505050565b6060815f015182602001518360400151846060015185608001518660a001518760c001518860e001518961010001518a61012001518b61014001518c61016001516040516020016142e19c9b9a99989796959493929190615a77565b60408051601f19818403018152908290526101808401516101a08501516101c08601516101e0870151610200880151610220890151959750612bfa9661437f969060200195865260f894851b7fff00000000000000000000000000000000000000000000000000000000000000908116602088015293851b841660218701529190931b90911660228401526023830191909152604382015260630190565b60408051601f198184030181529190528290614909565b604080517fc1e8426d70a8367e3d86a5f2e0bdec2344bd6a74f82bfdf50cdfdc08a36500f1602082015290810184905260608101839052608081018290525f90819060a0016040516020818303038152906040529050613f4b60065482805190602001206040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b5f5f5f836001600160a01b03163b5f036145fe5760418690036144865761445d86880188615b9d565b909350915086866040818110614475576144756156d1565b919091013560f81c915061450f9050565b60408690036144dd575f61449c87890189615b9d565b9094507f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116935090506144d560ff82901c601b615bbd565b91505061450f565b6040517f4be6321b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080515f8082526020820180845288905260ff841692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa158015614560573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b0381166145ad576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846001600160a01b0316816001600160a01b0316146145f8576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50613e4f565b604051630b135d3f60e11b81525f906001600160a01b03861690631626ba7e906146309089908c908c90600401615bd6565b602060405180830381865afa15801561464b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061466f9190615c0b565b90506001600160e01b03198116630b135d3f60e11b146146bb576040517fb0669cbc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050565b5f60088260ff1611156140ef576146dd60088361595a565b6146e890600a615a56565b6140ec90846156a7565b5f836001600160a01b0316836040515f6040518083038185875af1925050503d805f811461473b576040519150601f19603f3d011682016040523d82523d5f602084013e614740565b606091505b505090508115613fed5780613fed5760405162461bcd60e51b815260206004820152600e60248201527f7061796d656e74206661696c65640000000000000000000000000000000000006044820152606401610832565b6040516001600160a01b038316602482015260448101829052610b4090849063a9059cbb60e01b90606401613fa1565b5f6147d38260206156be565b835110156139bc5760405162461bcd60e51b815260206004820152601560248201527f746f55696e743235365f6f75744f66426f756e647300000000000000000000006044820152606401610832565b5f614877826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166149869092919063ffffffff16565b905080515f1480614897575080806020019051810190614897919061585e565b610b405760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610832565b6060806040519050835180825260208201818101602087015b8183101561493a578051835260209283019201614922565b50855184518101855292509050808201602086015b8183101561496757805183526020928301920161494f565b508651929092011591909101601f01601f191660405250905092915050565b6060611c4584845f85855f5f866001600160a01b031685876040516149ab9190615944565b5f6040518083038185875af1925050503d805f81146149e5576040519150601f19603f3d011682016040523d82523d5f602084013e6149ea565b606091505b50915091506149fb87838387614a06565b979650505050505050565b60608315614a745782515f03614a6d576001600160a01b0385163b614a6d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610832565b5081611c45565b611c458383815115614a895781518083602001fd5b8060405162461bcd60e51b815260040161083291906153f7565b634e487b7160e01b5f52604160045260245ffd5b6040516101c081016001600160401b0381118282101715614ada57614ada614aa3565b60405290565b604051608081016001600160401b0381118282101715614ada57614ada614aa3565b60405161016081016001600160401b0381118282101715614ada57614ada614aa3565b604051601f8201601f191681016001600160401b0381118282101715614b4d57614b4d614aa3565b604052919050565b5f6001600160401b03821115614b6d57614b6d614aa3565b50601f01601f191660200190565b5f82601f830112614b8a575f5ffd5b8135614b9d614b9882614b55565b614b25565b818152846020838601011115614bb1575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f60208284031215614bdd575f5ffd5b81356001600160401b03811115614bf2575f5ffd5b611c4584828501614b7b565b5f6001600160401b03821115614c1657614c16614aa3565b5060051b60200190565b61ffff81168114610971575f5ffd5b8035614c3a81614c20565b919050565b5f82601f830112614c4e575f5ffd5b8135614c5c614b9882614bfe565b8082825260208201915060208360051b860101925085831115614c7d575f5ffd5b602085015b83811015614ca3578035614c9581614c20565b835260209283019201614c82565b5095945050505050565b5f5f5f60608486031215614cbf575f5ffd5b83356001600160401b03811115614cd4575f5ffd5b614ce086828701614b7b565b93505060208401356001600160401b03811115614cfb575f5ffd5b614d0786828701614b7b565b92505060408401356001600160401b03811115614d22575f5ffd5b614d2e86828701614c3f565b9150509250925092565b6001600160a01b0381168114610971575f5ffd5b5f60208284031215614d5c575f5ffd5b81356140b881614d38565b5f6101008201905060ff83511682526020830151602083015261ffff6040840151166040830152606083015160608301526080830151608083015260a083015160a08301526001600160401b0360c08401511660c083015260e0830151610e2d60e08401826001600160401b03169052565b5f82601f830112614de8575f5ffd5b8135614df6614b9882614bfe565b8082825260208201915060208360051b860101925085831115614e17575f5ffd5b602085015b83811015614ca3578035835260209283019201614e1c565b5f60208284031215614e44575f5ffd5b81356001600160401b03811115614e59575f5ffd5b611c4584828501614dd9565b634e487b7160e01b5f52602160045260245ffd5b60068110614e9557634e487b7160e01b5f52602160045260245ffd5b9052565b602080825282518282018190525f918401906040840190835b81811015614f00578351614ec7848251614e79565b6001600160401b03602082015116602085015261ffff604082015116604085015250606083019250602084019350600181019050614eb2565b509095945050505050565b60ff81168114610971575f5ffd5b8035614c3a81614f0b565b6001600160401b0381168114610971575f5ffd5b8035614c3a81614f24565b5f6101c08284031215614f54575f5ffd5b614f5c614ab7565b9050614f6782614f19565b81526020828101359082015260408083013590820152614f8960608301614c2f565b60608201526080828101359082015260a08083013590820152614fae60c08301614f38565b60c0820152614fbf60e08301614f38565b60e0820152614fd16101008301614f38565b610100820152614fe46101208301614f38565b610120820152614ff76101408301614f38565b61014082015261500a6101608301614f19565b61016082015261501d6101808301614f19565b6101808201526101a09182013591810191909152919050565b5f60a08284031215615046575f5ffd5b50919050565b5f5f5f5f5f5f5f5f610300898b031215615064575f5ffd5b883561506f81614d38565b9750602089013596506150858a60408b01614f43565b95506102008901356001600160401b038111156150a0575f5ffd5b6150ac8b828c01614b7b565b95505061022089013593506102408901356001600160401b038111156150d0575f5ffd5b8901601f81018b136150e0575f5ffd5b80356001600160401b038111156150f5575f5ffd5b8b6020828401011115615106575f5ffd5b6020919091019350915061511e8a6102608b01615036565b90509295985092959890939650565b5f6020828403121561513d575f5ffd5b81356140b881614f24565b5f60208284031215615158575f5ffd5b5035919050565b6060810161516d8286614e79565b6001600160401b038416602083015261ffff83166040830152949350505050565b5f6020828403121561519e575f5ffd5b81356140b881614c20565b5f5f5f5f61022085870312156151bd575f5ffd5b84356151c881614d38565b9350602085013592506151de8660408701614f43565b91506102008501356001600160401b038111156151f9575f5ffd5b61520587828801614b7b565b91505092959194509250565b815160ff168152610140810160208301516020830152604083015161523c604084018261ffff169052565b50606083015160608301526080830151608083015260a083015161526560a084018260ff169052565b5060c083015161527a60c084018260ff169052565b5060e083015160e0830152610100830151610100830152610120830151610e2d6101208401826001600160401b03169052565b8015158114610971575f5ffd5b5f5f604083850312156152cb575f5ffd5b82356001600160401b038111156152e0575f5ffd5b6152ec85828601614b7b565b92505060208301356152fd816152ad565b809150509250929050565b5f5f60408385031215615319575f5ffd5b82356001600160401b0381111561532e575f5ffd5b61533a85828601614c3f565b92505060208301356001600160401b03811115615355575f5ffd5b61536185828601614dd9565b9150509250929050565b5f6020828403121561537b575f5ffd5b81356140b8816152ad565b5f5f6101e08385031215615398575f5ffd5b6153a28484614f43565b91506101c08301356001600160401b038111156153bd575f5ffd5b61536185828601614b7b565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6140b860208301846153c9565b8051614c3a81614f0b565b805163ffffffff81168114614c3a575f5ffd5b8051614c3a81614c20565b8051614c3a81614f24565b5f82601f83011261544c575f5ffd5b8151602083015f61545f614b9884614b55565b9050828152858383011115615472575f5ffd5b8282602083015e5f92810160200192909252509392505050565b5f82601f83011261549b575f5ffd5b81516154a9614b9882614bfe565b8082825260208201915060208360071b8601019250858311156154ca575f5ffd5b602085015b83811015614ca357608081880312156154e6575f5ffd5b6154ee614ae0565b8151815260208083015190820152604082015161550a81614f0b565b6040820152606082015161551d81614f0b565b606082015283526020909201916080016154cf565b8051614c3a816152ad565b5f5f5f6060848603121561554f575f5ffd5b83516001600160401b03811115615564575f5ffd5b84016101608187031215615576575f5ffd5b61557e614b02565b61558782615409565b815261559560208301615414565b60208201526155a660408301615414565b60408201526155b760608301615427565b6060820152608082810151908201526155d260a08301615432565b60a08201526155e360c08301615409565b60c082015260e08201516001600160401b03811115615600575f5ffd5b61560c8882850161543d565b60e08301525061561f6101008301615414565b6101008201526101208201516001600160401b0381111561563e575f5ffd5b61564a8882850161548c565b610120830152506101409182015191810191909152925061566d60208501615532565b915060408401516001600160401b03811115615687575f5ffd5b614d2e8682870161543d565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417612bfa57612bfa615693565b80820180821115612bfa57612bfa615693565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156156f5575f5ffd5b5051919050565b6001600160401b038181168382160190811115612bfa57612bfa615693565b6001600160a01b038416815260208101839052815160ff16604082015261020081016020830151606083015260408301516080830152606083015161576660a084018261ffff169052565b50608083015160c083015260a083015160e083015260c08301516157966101008401826001600160401b03169052565b5060e08301516001600160401b038116610120840152506101008301516001600160401b038116610140840152506101208301516001600160401b038116610160840152506101408301516001600160401b0381166101808401525061016083015160ff81166101a08401525061018083015160ff81166101c0840152506101a08301516101e0830152949350505050565b5f60208284031215615838575f5ffd5b81516140b881614f0b565b5f60208284031215615853575f5ffd5b81516140b881614c20565b5f6020828403121561586e575f5ffd5b81516140b8816152ad565b81810381811115612bfa57612bfa615693565b6001600160401b038181168382160290811690818114610e2d57610e2d615693565b634e487b7160e01b5f52601260045260245ffd5b5f6001600160401b038316806158da576158da6158ae565b806001600160401b0384160491505092915050565b5f602082840312156158ff575f5ffd5b81516140b881614d38565b6001600160401b038281168282160390811115612bfa57612bfa615693565b5f60208284031215615939575f5ffd5b81356140b881614f0b565b5f82518060208501845e5f920191825250919050565b60ff8281168282160390811115612bfa57612bfa615693565b6001815b60018411156159ae5780850481111561599257615992615693565b60018416156159a057908102905b60019390931c928002615977565b935093915050565b5f826159c457506001612bfa565b816159d057505f612bfa565b81600181146159e657600281146159f057615a0c565b6001915050612bfa565b60ff841115615a0157615a01615693565b50506001821b612bfa565b5060208310610133831016604e8410600b8410161715615a2f575081810a612bfa565b615a3b5f198484615973565b805f1904821115615a4e57615a4e615693565b029392505050565b5f6140b860ff8416836159b6565b5f82615a7257615a726158ae565b500490565b7fff000000000000000000000000000000000000000000000000000000000000008d60f81b1681528b60018201527fffff0000000000000000000000000000000000000000000000000000000000008b60f01b1660218201528960238201528860438201527fffff0000000000000000000000000000000000000000000000000000000000008860f01b166063820152866065820152615b26608582018760c01b6001600160c01b0319169052565b615b3f608d82018660c01b6001600160c01b0319169052565b615b58609582018560c01b6001600160c01b0319169052565b615b71609d82018460c01b6001600160c01b0319169052565b615b8a60a582018360c01b6001600160c01b0319169052565b60ad019c9b505050505050505050505050565b5f5f60408385031215615bae575f5ffd5b50508035926020909101359150565b60ff8181168382160190811115612bfa57612bfa615693565b83815260406020820152816040820152818360608301375f818301606090810191909152601f909201601f1916010192915050565b5f60208284031215615c1b575f5ffd5b81516001600160e01b0319811681146140b8575f5ffdfea2646970667358221220deb0c0505c94b940dfcedfa843a9d0de31d0ebcea418c16f2033b4bb69e5537864736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d00000000000000000000000000000000000000000000000000000000000000017eabb0ebb9b559ede7a22b52d905dc7ade19cd8e4acf1650683865b2e015caea000000000000000000000000da95d2e1b54893d424da8959bcabeabbfc911884000000000000000000000000c3f33ee53933c32e1fcd52fa3933ab508663ee6a
-----Decoded View---------------
Arg [0] : _wormhole (address): 0xCa1D5a146B03f6303baF59e5AD5615ae0b9d146D
Arg [1] : _refundVerifier (address): 0xCa1D5a146B03f6303baF59e5AD5615ae0b9d146D
Arg [2] : _refundEmitterChainId (uint16): 1
Arg [3] : _refundEmitterAddr (bytes32): 0x7eabb0ebb9b559ede7a22b52d905dc7ade19cd8e4acf1650683865b2e015caea
Arg [4] : _feeManager (address): 0xDA95d2E1b54893D424dA8959BcABeABBFc911884
Arg [5] : _rescueVault (address): 0xC3F33ee53933c32e1fCd52fa3933ab508663ee6a
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d
Arg [1] : 000000000000000000000000ca1d5a146b03f6303baf59e5ad5615ae0b9d146d
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [3] : 7eabb0ebb9b559ede7a22b52d905dc7ade19cd8e4acf1650683865b2e015caea
Arg [4] : 000000000000000000000000da95d2e1b54893d424da8959bcabeabbfc911884
Arg [5] : 000000000000000000000000c3f33ee53933c32e1fcd52fa3933ab508663ee6a
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$14,085.60
Net Worth in ETH
4.831258
Token Allocations
USDC
100.00%
ETH
0.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| OP | 64.23% | $0.999701 | 9,049.8659 | $9,047.16 | |
| AVAX | 11.97% | $0.999542 | 1,686.3429 | $1,685.57 | |
| BASE | 11.58% | $0.999701 | 1,632.0766 | $1,631.59 | |
| BASE | <0.01% | $2,914.12 | 0.000002 | $0.005828 | |
| ETH | 6.57% | $0.9997 | 925.1465 | $924.87 | |
| ARB | 2.44% | $0.999608 | 343.2349 | $343.1 | |
| MONAD | 2.17% | $0.999701 | 306.1864 | $306.09 | |
| UNI | 1.02% | $0.999655 | 144.1093 | $144.06 | |
| POL | 0.02% | $0.999702 | 3.1495 | $3.15 |
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.